Как избежать исключения HttpRequestValidationException в ASP.NET MVC, отображая тот же вид, который вызвал исключение
Я просто хочу знать, как проверить (или очистить) ввод пользователя в 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>
Ответ 2
В ASP MVC 3 вы можете использовать атрибут [AllowHtml]
для отдельных полей/свойств в Model/ViewModel, чтобы отключить проверку только для этого поля, что довольно приятно. Я добавлю этот атрибут к определенным полям в моей модели, а затем использую отличную библиотеку 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) не работает, потому что контроллер отвечает за получение запроса (не view/aspx).
Ответ 6
Поместите put ValidateRequest = "false" в ваше объявление представления aspx, но очистите пользователя от ввода текста внутри вашего кода, чтобы избежать некоторых атак xss.