2012-06-27 43 views
3

關於屬性上的修飾器[AllowHtml]或甚至[ValidateInput(false)]上的方法,捕獲HttpRequestValidationException並將其追加到ModelState以在用戶端顯示爲友好錯誤並且不顯示錯誤頁面的最佳方法是(或者。Application_Error下拋出一個新的頁面,或使使用的自定義錯誤頁捕獲HttpRequestValidationException並將其添加到ModelState的最佳方式是什麼?

global.asax裏面我有一個陷阱:

protected void Application_Error() 
{ 
    // http://romsteady.blogspot.dk/2007/06/how-to-catch-httprequestvalidationexcep.html 
    // Code that runs when an unhandled error occurs 

    System.Exception ex = Server.GetLastError(); 

    if (ex is System.Web.HttpRequestValidationException) 
    { 
     // I got the exception here, I can do plenty now! 

     Server.ClearError(); // no need to continue, I know the error 
    } 
} 

我怎麼從這裏到模型狀態,而無需使用任何會話/應用程序變量(想想g關於這裏的雲以及託管用戶請求的所有那些不同的服務器)?

我想添加到路由或TempData但這樣是不是可以在這裏...也許一個Cookie但接縫哈克......

任何想法?

回答

1

我曾經通過自定義模型綁定器和投擲周圍base.BindModel調用一個try/catch來處理這種情況。這很醜陋,但它完成了工作。

我再說一遍,這很醜。

下面是一個例子:

public class FooModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     Foo model; 
     try 
     { 
      model = (Foo)base.BindModel(controllerContext, bindingContext); 
     } 
     catch (HttpRequestValidationException) 
     { 
      // handle here 
     } 
    } 
} 

現在,一個勇敢的努力與錯誤填充ModelState中,我有一個助手類,它會盡力保持狀態。它的使用(和實現)有很多不足之處(很多管道,使用魔術字符串,特定類型,異常消息文本的正則表達式等等),所以我們歡迎任何建議。這是最醜陋的部分,imo。

用法:

// from above code snippet 
catch (HttpRequestValidationException) 
{ 
    // handle any potentially dangerous form values here. Don't want an exception bubbling up to the user 
    // so handle the HttpRequestValidationException by hand here 
    // manually populate the model here so that the original values are presented back to the user 
    model = new Foo() 
    { 
     Bar = HandleHttpRequestValidationExceptionHelper.TryAssignment(bindingContext.ModelState,() => bindingContext.ValueProvider.GetValue("Bar").AttemptedValue), 
     Baz = HandleHttpRequestValidationExceptionHelper.TryAssignment(bindingContext.ModelState,() => bindingContext.ValueProvider.GetValue("Baz").AttemptedValue) 
    }; 
} 

return model; 

助手會盡力挖掘出相關的錯誤信息給用戶,但它是非常糟糕的。 (注意:一個主題?)

實現:

public static class HandleHttpRequestValidationExceptionHelper 
{ 
    /// <summary> 
    /// Use TryAssignment in anticipation of a HttpRequestValidationException; it's used to help return error information to the user 
    /// </summary> 
    /// <param name="modelStateDictionary">The ModelStateDictionary to add the errors to</param> 
    /// <param name="action">The attempted value to assign</param> 
    /// <returns>Either the proper value or the errored value read from the HttpRequestValidationException Message property</returns> 
    public static string TryAssignment(ModelStateDictionary modelStateDictionary, Func<string> action) 
    { 
     try 
     { 
      return action(); 
     } 
     catch (HttpRequestValidationException ex) 
     { 
      // in effort to better inform the user, try to fish out the offending form field 
      var parenthesesMatch = Regex.Match(ex.Message, @"\(([^)]*)\)"); 
      if (parenthesesMatch.Success) 
      { 
       var badFormInput = parenthesesMatch.Groups[1].Value.Split('='); 
       modelStateDictionary.AddModelError(badFormInput[0], badFormInput[1] + " is not valid."); 
       return badFormInput[1].TrimStart('"').TrimEnd('"'); 
      } 
      else 
      { 
       // if attempt to find the offending field fails, just give a general error 
       modelStateDictionary.AddModelError("", "Please enter valid information."); 
       return string.Empty; 
      } 
     } 
    } 

    /// <summary> 
    /// Use TryAssignment in anticipation of a HttpRequestValidationException; it's used to help return error information to the user 
    /// </summary> 
    /// <typeparam name="T">Type of the value</typeparam> 
    /// <param name="modelStateDictionary">The ModelStateDictionary to add the errors to</param> 
    /// <param name="action">The attempted value to assign</param> 
    /// <returns>Either the proper value or default(T)</returns> 
    public static T TryAssignment<T>(ModelStateDictionary modelState, Func<T> action) 
    { 
     try 
     { 
      return action(); 
     } 
     catch (HttpRequestValidationException ex) 
     { 
      // in effort to better inform the user, try to fish out the offending form field 
      var parenthesesMatch = Regex.Match(ex.Message, @"\(([^)]*)\)"); 
      if (parenthesesMatch.Success) 
      { 
       var badFormInput = parenthesesMatch.Groups[1].Value.Split('='); 
       modelState.AddModelError(badFormInput[0], badFormInput[1] + " is not valid."); 
       // can't really cast a string to an unknown type T. safer to just return default(T) 
      } 
      else 
      { 
       // if attempt to find the offending field fails, just give a general error 
       modelState.AddModelError("", "Please enter valid information."); 
      } 
      return default(T); 
     } 
    } 
} 

基本上,在捕獲異常,請嘗試手動重新綁定模型,準備抓潛在HttpRequestValidationException誤差爲每個屬性。如果有人被抓到,請根據我的具體信息填充ModelStateDictionary。

我真的希望這個框架能夠更容易地抓住這個異常,並且2)優雅地處理它,而不是cra住整個牀。

相關問題