2

Prologue: I've read many questions about fixing 'A potentially dangerous request' errors:

Among many others. I know how to fix it several different ways, however I do not want to turn off request validation.


I would like to add form validations to all string view model properties site-wide to guard against the "A potentially dangerous request" exception, since throwing an exception is not ideal if a user can correct their input. I've only been able to think of two different solutions:

  1. Add a regular expression validator to each view model property that accepts a string datatype, which is executed on the browser. This will prevent form submissions, but is a lot of work coding wise for our application

  2. Somehow magically add a validator that is executed on each request that is triggered on all string view model properties that does this validation and gives the user a friendlier message than the Yellow Screen of Doom (tm).

The validation message that should show up by the form field, regardless of solution, should be something like:

The X field contains potentially dangerous characters. Either remove all '<' characters, or ensure a space or punctuation mark occurs before them.

Or something to that affect. Basically, I want a validation message that helps the user resolve the situation instead of blowing the whole application sky-high, which causes them to lose all of their work inputting data into a form.

I did come up with a solution, that involves adding a custom model binder for string properties that gets the value of the property without triggering the validations, and then testing it with a regular expression. A match on the regex then causes a new model state error to be added to that property.

public class MaliciousStringInputModelBinder : IModelBinder
{
    private static readonly Regex maliciousStringPattern = new Regex(@"<[a-zA-Z0-9]");
    private const string validationMessageFormat = "The {0} field contains potentially dangerous characters. Either remove the '<' characters, or ensure a space or puncuation character immediately follows them.";

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // Call extension method to safely get model value without
        // triggering any validations
        var valueResult = controllerContext.GetValueFromProvider(bindingContext);

        if (valueResult == null || valueResult.AttemptedValue == null)
        {
            return null;
        }
        else if (valueResult.AttemptedValue == string.Empty)
        {
            return string.Empty;
        }
        else if (maliciousStringPattern.IsMatch(valueResult.AttemptedValue))
        {
            bindingContext.ModelState.AddModelError(bindingContext.ModelName, string.Format(validationMessageFormat, bindingContext.ModelMetadata.DisplayName));
        }

        bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueResult);

        return valueResult.AttemptedValue;
    }
}

This works, but feels like a hack. I'm not binding the model property, I'm validating it.

I've been looking into ASP.NET MVC action filters, but again I'm jumping through lots of hoops without a clear solution.

How can I add a universal form validation to all string view model properties site-wide in ASP.NET MVC to show a validation message to users instead of throwing an exception?

Greg Burghardt
  • 17,900
  • 9
  • 49
  • 92

0 Answers0