9

My question is hopefully pretty straight forward. Upon submitting my form, I would like to flag all properties (fields) that have invalid characters (specifically HTML) as model errors. The issue I am facing is that Request Validation kicks in before model binding/validation and I get HTTP 500... I saw a similar question that advertises either using [AllowHtml] property attribute on your Model/ViewModel or using <httpRuntime requestValidationMode="2.0" /> in web.config, but what I am looking for is how to "globally catch Request Validation exceptions and show them as model errors". Furthermore, I don't want to "strip" HTML tags, I want to notify the user that their input is not valid.

I thought about using Regular Expression validation attributes to find bad input, but as I mentioned, the Request Validation on ASP.NET MVC3 occurs before model binding/validation, so that is a no-go...

A really good overview of the Request Validation can be found here.

Community
  • 1
  • 1
zam6ak
  • 7,229
  • 11
  • 46
  • 84
  • Let me understand your problem. You want to flag your properties in code-behind and manipulate them in code-behind when there are any validation error? – Vinicius Ottoni Feb 13 '12 at 15:04

1 Answers1

10

I think your only intention is to get the Request Validation exception during model binding and show the errors as model state error. Here is the sample,

    using System.Web.Helpers;
    public class MyModelBinder : DefaultModelBinder
    {
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            try
            {
                return base.BindModel(controllerContext, bindingContext);
            }
            catch(HttpRequestValidationException ex)
            {
                var modelState = new ModelState();
                modelState.Errors.Add(ex.Message);
                var key=bindingContext.ModelName;
                var value = controllerContext.RequestContext.HttpContext.Request.Unvalidated().Form[key];
                modelState.Value = new ValueProviderResult(value, value,CultureInfo.InvariantCulture);
                bindingContext.ModelState.Add(key, modelState);
            }
            return null;
        }
    }

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        ModelBinders.Binders.DefaultBinder = new MyModelBinder();
    }

This will add the exception of only request validation in model state. Sorry, If I don't understand your question clearly.

avs099
  • 10,937
  • 6
  • 60
  • 110
imran_ku07
  • 1,404
  • 12
  • 13
  • @zam6ak, Add using System.Web.Helpers and see my updated answer. Note, this is just a quick answer and not very much optimized. Sorry for that. – imran_ku07 Feb 13 '12 at 18:08
  • This seems to work nicely - I am not sure why are you saying it is "not very much optimized" :) – zam6ak Feb 13 '12 at 22:47
  • @zam6ak, I said this because I have created this in a quick time. So, it may be not optimized or there may be some other better way. – imran_ku07 Feb 14 '12 at 02:31
  • For everyone's info, Unvalidated() is new on Request as of .NET 4.5 – kdawg Dec 04 '12 at 20:05
  • When using a custom DefaultBinder like in this example, is there any way of getting the display name of the field set in bindingContext.ModelName? – Chris Miller Jan 03 '13 at 20:16
  • Works perfectly for me. I wanted to return an error message to the user instead of an exception and this code accomplishes that. – John81 Dec 22 '14 at 15:45
  • Very nice. Note: `Unvalidated()` seems to be a property in MVC5. With `controllerContext.RequestContext.HttpContext.Request.Unvalidated.Form[key]` it worked for me. – Christian Gollhardt Apr 11 '17 at 14:17