1

I have this viewmodel

public class FooBarViewModel
{
    public string Foo { get; set; }

    [AllowHtml]
    public string Bar { get; set; }
}

Instead of throwing a HttpRequestValidationException if .Foo is submitted with html in it, I want to add a message to ModelState. How could I do that?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
kenwarner
  • 28,650
  • 28
  • 130
  • 173

2 Answers2

1

You could decorate the Foo property with the [AllowHtml] attribute as well and inside the controller check whether it contains HTML which would allow you to add a custom error to the model state.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • that will probably work for now. I was hoping to leverage the existing bits with an action filter or something but not sure where to start. – kenwarner Jul 16 '11 at 22:08
  • @qntmfred, you could indeed use an action filter which implements the IExceptionFilter interface and trap the HttpRequestValidationException there but the problem is that all you could do is to add the error to the model state and render the view but your controller action will not execute. This means that if you decide to go that route you will also have to take care of passing a view model to the ViewResult you might be returning inside this custom action filter. This being said you could still decorate the Foo property with AllowHtml and then have a custom action filter which checks ... – Darin Dimitrov Jul 16 '11 at 22:14
  • ... whether the posted value contains HTML and if it does simply add an error to the model state. That would of course avoid you repeating this logic over multiple controller actions if you had to. – Darin Dimitrov Jul 16 '11 at 22:17
0

The exception will be thrown within the DefaultModelBinder at the point where it calls ValueProvider.GetValue.

To change the behaviour to catch the exception and convert it into a ModelState error you would need to extend or replace the DefaultModelBinder.

One possibility is to override BindModel, and at the point where it calls GetValue:

ValueProviderResult valueProviderResult = bindingContext.UnvalidatedValueProvider.GetValue(bindingContext.ModelName, skipValidation: !performRequestValidation);

try and catch the exceptions and call bindingContext.ModelState.AddModelError.

The problem is that the DefaultModelBinder is quite complex so you may need to think carefully about how such a change needs to interact with the rest of the model binding ecosystem.

Jack Ukleja
  • 13,061
  • 11
  • 72
  • 113