问题 Asp.Net MVC 5仅从body绑定参数


我想防止通过url查询字符串将敏感数据发布到MVC 5应用程序。

在MVC中有一个 DefaultModelBinder。该 DefaultModelBinder 寻找 ActionMethod url查询字符串,正文和路由中的参数。但我的目标是仅从身体绑定参数  来自路由或查询字符串。

在Asp.Net WebApi中有这样一个概念。属性[FromBody]将完成工作: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

有适合MVC的东西吗?

我找到了 System.Web.ModelBinding.FormAttribute (https://msdn.microsoft.com/en-us/library/system.web.modelbinding.formattribute(v=vs.110).aspx)。但是,如果我装饰参数,它对模型绑定没有影响。


6525
2017-08-14 14:19


起源



答案:


默认情况下,binder在四个位置查找数据:表单数据,路由数据,查询字符串和任何上载的文件。

可以将绑定限制为单个数据源。要这样做你应该打电话给 的UpdateModel 方法传递,作为第二个参数,a FormValueProvider 对象(一个实现 IValueProvider)。

public ActionResult Products()
{
    IList<Products> products = new List<Products>();
    UpdateModel(products, new FormValueProvider(ControllerContext));
    return View(products);
}

完整的对象列表是(它们都接收ControllerContext作为contructor参数):

  • FormValueProvider:搜索正文中的数据(Request.Form)
  • RouteDataValueProvider:搜索路径中的数据(RouteData.Value)
  • QueryStringValueProvider:在查询字符串中搜索数据(Request.QueryString)
  • HttpFileCollectionValueProvider:搜索上传的文件(Request.Files)

5
2017-08-14 14:49



谢谢,这就是我要找的。我希望它可以通过属性来完成。但这也是一个很好的解决方案。顺便说一下我要用 TryUpdateModel()。 - Dennis K


答案:


默认情况下,binder在四个位置查找数据:表单数据,路由数据,查询字符串和任何上载的文件。

可以将绑定限制为单个数据源。要这样做你应该打电话给 的UpdateModel 方法传递,作为第二个参数,a FormValueProvider 对象(一个实现 IValueProvider)。

public ActionResult Products()
{
    IList<Products> products = new List<Products>();
    UpdateModel(products, new FormValueProvider(ControllerContext));
    return View(products);
}

完整的对象列表是(它们都接收ControllerContext作为contructor参数):

  • FormValueProvider:搜索正文中的数据(Request.Form)
  • RouteDataValueProvider:搜索路径中的数据(RouteData.Value)
  • QueryStringValueProvider:在查询字符串中搜索数据(Request.QueryString)
  • HttpFileCollectionValueProvider:搜索上传的文件(Request.Files)

5
2017-08-14 14:49



谢谢,这就是我要找的。我希望它可以通过属性来完成。但这也是一个很好的解决方案。顺便说一下我要用 TryUpdateModel()。 - Dennis K


另一种方式:创建一个 定制模型活页夹 用的 FormValueProvider。这样做的好处是您不必修改操作方法。

例:

[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;
    }
}

你的行动方法:

[HttpPost]
public ActionResult Person(Person person)
{
    return View(person);
}

即使您使用查询字符串发布,也可以 ShouldNotBind 属性将显示为“null”。


5
2017-08-14 15:00





为什么不使用表格呢? 提交时,您发布表单数据


0
2017-08-14 14:24



不知道你究竟是什么意思。 Asp.Net Web Forms不是另一种选择。 - Dennis K
msdn.microsoft.com/en-us/library/dd505244%28v=vs.118%29.aspx - Piotr Dory
w3schools.com/html/html_forms.asp - Piotr Dory
添加 - >查看。选择模板“编辑”。选择你的模特课。它将为您自动生成表单。那你就明白了 - Piotr Dory
好,我知道了。当然,这是我渲染表单的方式。每个“普通”用户都会在身体上发布数据。但任何人都可以在查询字符串中发送带参数的请求,MVC会绑定它们。这是我想要防止的情况。 - Dennis K