I want to prevent posting sensitive data via url query string to a MVC 5 application.
In MVC there is a DefaultModelBinder
. The DefaultModelBinder
Another way: create a custom model binder that uses FormValueProvider. The advantage of this is that you don't have to modify the action method.
Example:
[ModelBinder(typeof(PersonBinder))]
public class Person
{
[DisplayName("Social Security Number")]
public int SSN { get; set; }
[HiddenInput(DisplayValue = false)]
public string ShouldNotBind { get; set; }
}
public class PersonBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
bindingContext.ValueProvider = new FormValueProvider(controllerContext);
Person model = (Person)bindingContext.Model ?? new Person();
model.SSN = Convert.ToInt16(GetValue(bindingContext, "SSN"));
return model;
}
private string GetValue(ModelBindingContext context, string name)
{
ValueProviderResult result = context.ValueProvider.GetValue(name);
if (result == null || result.AttemptedValue == "")
{
return "<Not Specified>";
}
return result.AttemptedValue;
}
}
And your action method:
[HttpPost]
public ActionResult Person(Person person)
{
return View(person);
}
Even if you post with a querystring, the ShouldNotBind
property will show as "null".
Why not use form's then? On submit you post form data
By default, the binder looks for data in four places: form data, route data, the query string, and any uploaded files.
It is possible to restrict the binding to a single source of data. To do so you should call the UpdateModel method passing, as the second parameter, a FormValueProvider object( an implementation of IValueProvider).
public ActionResult Products()
{
IList<Products> products = new List<Products>();
UpdateModel(products, new FormValueProvider(ControllerContext));
return View(products);
}
The complete list of objects is (they all receive the ControllerContext as the contructor parameter):