Asp.Net MVC 5 bind parameter exclusively from body

天涯浪子 提交于 2019-11-27 16:18:56

问题


I want to prevent posting sensitive data via url query string to a MVC 5 application.

In MVC there is a DefaultModelBinder. The DefaultModelBinder looks for the ActionMethod parameters in the url query string, the body and the route. But my target is to bind the parameters exclusively from the body and not from route or query string.

In Asp.Net WebApi there is such a concept. The Attribute [FromBody] will do the job: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

Is there something suitable for MVC?

I´ve found the System.Web.ModelBinding.FormAttribute (https://msdn.microsoft.com/en-us/library/system.web.modelbinding.formattribute(v=vs.110).aspx). However, if I decorate the parameter, it has no effect to the model binding.


回答1:


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):

  • FormValueProvider: search for data in the body (Request.Form)
  • RouteDataValueProvider: search for data in the route (RouteData.Value)
  • QueryStringValueProvider: search for data in the query string (Request.QueryString)
  • HttpFileCollectionValueProvider: search for uploaded files (Request.Files)



回答2:


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".




回答3:


Why not use form's then? On submit you post form data



来源:https://stackoverflow.com/questions/32012288/asp-net-mvc-5-bind-parameter-exclusively-from-body

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!