如何避免 ASP.NET MVC 中的 HttpRequestValidationException 呈现导致异常的相同视图

Posted

技术标签:

【中文标题】如何避免 ASP.NET MVC 中的 HttpRequestValidationException 呈现导致异常的相同视图【英文标题】:How to avoid HttpRequestValidationException in ASP.NET MVC rendering the same view which caused the exception 【发布时间】:2010-09-19 22:17:24 【问题描述】:

我只想知道如何在 ASP.NET MVC 中验证(或清理)用户输入,以便无论提交的值如何都不会引发 HttpRequestValidationException。例如,文本输入,如果用户输入<BR/>,则会引发异常并显示黄屏死机。我不想要那个。我想捕获异常并在当前视图中显示用户友好的错误,最好使用加载了相同值的控件提交。

我找到了这个http://www.romsteady.net/blog/2007/06/how-to-catch-httprequestvalidationexcep.html,但它对我的目的毫无用处。另外,我找到了这个http://msdn.microsoft.com/en-us/library/aa973813.aspx 并尝试将其放入模型活页夹中,但无法正常工作。

【问题讨论】:

【参考方案1】:

使用最新版本的 ASP.NET MVC(RC,在撰写本文时),您可以在控制器类或操作方法上放置一个属性,例如:

[ValidateInput(false)]
public ActionResult create()

    // ...method body

ValidateInputAttribute 在 System.Web.Mvc 中。

但正如其他人所说,您必须执行自己的手动输入验证或清理。

使用 MVC 3,您还必须确保它在您的 Web.config 中:<system.web><httpRuntime requestValidationMode="2.0" /></system.web>

【讨论】:

如果 ValidateInputAttribute 能够接受一个字段的名称(或名称列表),那就太好了,这样就可以有选择地关闭验证。全有或全无往往会很糟糕,导致重复工作,而且通常只会让事情变得更麻烦。 使用 MVC 3,您还必须确保它在您的 Web.config 中:<httpRuntime requestValidationMode="2.0" />【参考方案2】:

在 ASP MVC 3 中,您可以在模型/视图模型中的各个字段/属性上使用 [AllowHtml] 属性来关闭对该字段的验证,这非常好。我会将此属性添加到模型中的某些字段,然后使用出色的 AntiXSS 库(也可通过 NuGet 获得)通过调用 Sanitizer.GetSafeHtmlFragment(mymodel.Description)(其中“描述”属性是我的视图模型,它应用了[AllowHtml] 属性)

【讨论】:

【参考方案3】:

有关如何使用过滤器捕获此(和其他)异常的非常详细的示例,请参阅:http://code.google.com/p/geochat/source/browse/Source/Web/GeoChat.MvcExtensions/ExceptionHandlerAttribute.cs

这将允许您继续进行验证,但防止用户看到“黄屏死机”。

这是一个简化(也许过于简化)的版本:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true), AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class ExceptionHandlerAttribute : FilterAttribute, IExceptionFilter 

private HandleErrorAttribute attribute = new HandleErrorAttribute();

public ExceptionHandlerAttribute() 
  this.ExceptionType = typeof(Exception);
  this.Order = 1;


public string View 
  get 
    return attribute.View;
  
  set 
    attribute.View = value;
  


public Type ExceptionType 
  get 
    return attribute.ExceptionType;
  
  set 
    attribute.ExceptionType = value;
  


public void OnException(ExceptionContext filterContext) 
  if (this.ExceptionType.IsInstanceOfType(filterContext.Exception)) 
    string controller = (string)filterContext.RouteData.Values["controller"];
    string action = (string)filterContext.RouteData.Values["action"];
    if (controller == null)
      controller = String.Empty;

    if (action == null)
      action = String.Empty;

    HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controller, action);
    ViewResult result = new ViewResult();
    result.ViewName = this.View;
    result.MasterName = String.Empty;
    result.ViewData = new ViewDataDictionary<HandleErrorInfo>(model);

    result.TempData = filterContext.Controller.TempData;
    filterContext.Result = result;

    filterContext.ExceptionHandled = true;
    filterContext.HttpContext.Response.Clear();
    filterContext.HttpContext.Response.StatusCode = 500;
  

【讨论】:

【参考方案4】:

您可以通过为控制器添加一个错误处理程序来捕获它,而不是在 global.asax Application_Error 中捕获错误,该控制器显式捕获此错误并重定向到带有错误消息和适当视图数据的视图。

我发现这个有点老了,post 关于如何使用属性来做到这一点。

【讨论】:

【参考方案5】:

ValidateInputAttribute 是禁用请求验证的正确方法。视图(aspx)中的声明式方法不起作用,因为控制器负责接收请求(不是视图/aspx)。

【讨论】:

【参考方案6】:

将 ValidateRequest="false" 放入您的 aspx 视图声明中,但在您的代码中清理用户输入文本,以避免一些 xss 攻击。

【讨论】:

谢谢,但我不想在我的 aspx 上停用 ValidateRequest。

以上是关于如何避免 ASP.NET MVC 中的 HttpRequestValidationException 呈现导致异常的相同视图的主要内容,如果未能解决你的问题,请参考以下文章