Reputation: 15511
In my custom model binder I use
bindingContext.ValueProvider.GetValue(propertyName);
I do have [ValidateInput(false)] on the action. However the GetValue call above results in
A potentially dangerous Request.QueryString value was detected from the client
How do I make my custom model binder get the unvalidated value from the value provider? Of course when it finds that there's ValidateInput(false) on the action.
Upvotes: 7
Views: 825
Reputation: 15511
Just in case someone is curious, here's a quick solution. Just call CheckUnvalidated() in BindModel/BindProperty methods. This will replace default QueryStringValueProvider with the unvalidated version.
MethodInfo GetActionMethod(ControllerContext controllerContext)
{
var action = controllerContext.RouteData.Values["action"] as string;
return controllerContext.Controller.GetType().GetMethods().FirstOrDefault(x => x.Name == action ||
x.GetCustomAttribute<ActionNameAttribute>().SafeGet(a => a.Name) == action);
}
void CheckUnvalidated(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var method = GetActionMethod(controllerContext);
if (method == null)
return;
if (method.GetCustomAttribute<ValidateInputAttribute>().SafeGet(x => x.EnableValidation, true))
return;
var collection = bindingContext.ValueProvider as ValueProviderCollection;
if (collection == null)
return;
var old = collection.OfType<QueryStringValueProvider>().FirstOrDefault();
if (old != null)
collection.Remove(old);
collection.Add(new UnvalidatedQueryStringValueProvider(controllerContext));
}
class UnvalidatedQueryStringValueProvider : NameValueCollectionValueProvider
{
public UnvalidatedQueryStringValueProvider(ControllerContext controllerContext)
: base(controllerContext.HttpContext.Request.Unvalidated().QueryString, CultureInfo.InvariantCulture)
{
}
}
Upvotes: 1