2

I am working on an MVC4 project and I have a single action on which I would like validation to be disabled, like so:

[HttpPost]
[ValidateAntiForgeryToken]
[ValidateInput(false)]
public ActionResult AddNewItems(AddNewItemsModel model, string postType)
{ ... }

Even though I have 'ValidateInput(false)' set, the application insists on validating the data, etc. I have stepped through the code, and I have confirmed that this action is being called, but it seems as though the attribute is ignored. Is there some simple alternate way to make this work (especially one that won't require another layer of models, etc.) ?

A.R.
  • 15,405
  • 19
  • 77
  • 123
  • Did you try finding the solution here: http://stackoverflow.com/questions/807662/why-is-validateinputfalse-not-working ? – Boris B. Oct 22 '13 at 19:38
  • Did you try reading the question? – A.R. Oct 22 '13 at 19:49
  • I was referring to the answer that (currently) has 105 upvotes, which states that the request on ASP.Net 4 is being validated before it hits the controller action, and the only solution (while still using the ValidateInputAttribute) is to revert the validation mode to 2.0 behavior via web.config. What part of your question did I not understand? – Boris B. Oct 23 '13 at 08:43
  • How am I supposed to know that? If you link to a page with many answers, how am I supposed to know what you are talking about ? – A.R. Oct 23 '13 at 12:50

2 Answers2

1

After doing a lot of research, I have concluded that validation is deeply integrated into the default model binder, and that the ValidateInput attribute is basically ignored by MVC. I will note that using the following in web.config

<system.Web>
  ...
  <httpRuntime requestValidationMode="2.0"/>

Will sometimes remedy the situation, but sometimes not. I noticed that this setting, combined with the 'ValidateInput' attribute is only respected intermittently, which makes it useless IMO. At the end I came up with an action filter, defined as such:

public class ClearModelErrorsAttribute : ActionFilterAttribute
{
  // ---------------------------------------------------------------------------------------
  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
    ModelStateDictionary msd = filterContext.Controller.ViewData.ModelState;
    foreach (var item in msd.Values)
    {
      item.Errors.Clear();
    }
  }
}

You can see that it is doing a brute force removal of all of the errors (thanks to the inability to turn off validation) and this is working for my particular scenario. Obviously, this isn't the most robust solution (and a hack), but it could be easily modified to work for more specific scenarios.

The new signature of my action is like this:

[HttpPost]
[ValidateAntiForgeryToken]
[ClearModelErrors]
public ActionResult AddNewItems(AddNewItemsModel model, string postType)
{ ... }

And I have removed the items from web.config that are mentioned above.

A.R.
  • 15,405
  • 19
  • 77
  • 123
0

If you know which field is not being validated, you can bypass validation like this :

var myForbiddenValue = System.Web.Helpers.Validation.Unvalidated(Request).Form["MyForbiddenField"]

Or you may as well iterate through all properties to unvalidate them. You may need to do that work in a customer model binder.

Réda Mattar
  • 4,361
  • 1
  • 18
  • 19
  • Interesting. I have a few dozen inputs on the form however. Is there a way I can just include the whole form ? (withhout iterating on props) – A.R. Oct 22 '13 at 20:57
  • `System.Web.Helpers.Validation.Unvalidated(Request).Form` gives you all form values without validating them, you'll still have to iterate on properties to get all their values. – Réda Mattar Oct 22 '13 at 21:36