Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 如何在ModelBinder/UpdateModel方法中白名单/黑名单子对象字段?_Asp.net Mvc - Fatal编程技术网

Asp.net mvc 如何在ModelBinder/UpdateModel方法中白名单/黑名单子对象字段?

Asp.net mvc 如何在ModelBinder/UpdateModel方法中白名单/黑名单子对象字段?,asp.net-mvc,Asp.net Mvc,我有一个问题,关于如何让MVC控制器的UpdateModel/TryUpdateModel的白名单和黑名单特性处理子对象的各个属性。例如,假设我有一份调查问卷,收集有关填写表格的人及其公司的详细信息 我的[简化]表单字段将被命名,例如: YourName YourEmail Company.Name Company.Phone 现在在我的模型中,假设我不希望Company.ID或Company.ispremiummber被篡改,所以我想将它们从模型绑定中排除。我尝试了白名单、黑名单以及两者的组

我有一个问题,关于如何让MVC控制器的UpdateModel/TryUpdateModel的白名单和黑名单特性处理子对象的各个属性。例如,假设我有一份调查问卷,收集有关填写表格的人及其公司的详细信息

我的[简化]表单字段将被命名,例如:

YourName
YourEmail
Company.Name
Company.Phone
现在在我的模型中,假设我不希望Company.ID或Company.ispremiummber被篡改,所以我想将它们从模型绑定中排除。我尝试了白名单、黑名单以及两者的组合,以使其发挥作用。我没有取得任何成功。以下是我遇到的情况:

当我在我的白名单中明确包括我上面写的四个相同的字段名时,整个公司不受约束(即,问卷调查。公司为空),除非我也在我的白名单中包括“公司”。但这会产生不良影响,约束整个公司,而不仅仅是我想要的两个属性

因此,我尝试将Company.ID和Company.ispremiummber包含在黑名单中,但这似乎被白名单所压倒,并且我认为不会“事后”过滤掉这些属性

我知道还有其他方式来表达“可绑定性”,比如通过成员上的[Bind]属性,但这并不理想,因为我希望在其他情况下使用相同的模型类,并使用不同的绑定规则,例如允许管理员设置她想要的任何属性

我希望一个明显的答案是,我应该编写自己的模型绑定器,我已经开始尝试研究如何做到这一点,但我真的希望使用“开箱即用”的解决方案来解决(在我看来)似乎非常常见的场景。我正在考虑的另一个想法是制作我自己的ValueProvider字典,将其交给UpdateModel方法,但是,如果有更简单的方法,我宁愿避免这一点

谢谢你的帮助! -迈克


附录#1

以下是我在表格中显示的字段:

你的名字 你的电子邮件 公司名称 公司,电话 这是一顶黑帽子带给我的:

YourName=Joe+Smith&YourEmail=joe@example.com&Company.Name=ACME+Corp&Company.Phone=555-555-5555&Company.CreditLimit=10000000 (请确保注意末尾附加的额外参数!)

问题是:

正如我最初发布的,如果没有一些大的解决办法,似乎不可能(使用默认的模型绑定器)阻止设置CreditLimit——要么是整个公司,要么什么都没有。我错了吗


附录2

我现在非常确信我的简单目标是不可能“开箱即用”的。我的解决方案是遍历已发布的表单字段并构建我自己的ValueProvider字典,从而将我想要允许的字段白名单,并将其交给UpdateModel


附录#3


我还没有签出AutoMapper,但有了类似的东西,创建一些ViewModels/DTO来处理这种复杂的白名单的解决方案——再加上轻松附加我已经在域对象上使用的相同服务器端验证(FluentValidation)的能力——似乎是一个可行的解决方案。谢谢大家

我通过使操作接受两个对象(父对象和子对象)来解决这个问题

示例:
假设我们有以下模型:

 public class Employee
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public Company Comapany { get; set; }
    }
    public class Company
    {
        public int Phone { get; set; }
    }
您可以这样构建表单:

    <form action="Home/Create" method="post">
   <label for="Employee.Name">Name</label>
    <%=Html.TextBox("Employee.Name") %><br />
   <label for="Employee.Name">Age</label>    
    <%=Html.TextBox("Employee.Age") %><br />
   <label for="Employee.Name">Comapany Phone</label>    
    <%=Html.TextBox("Company.Phone") %><br />
    <input type="submit" value="Send" />
   </form>
我希望这对你有帮助

编辑:

public ActionResult Create(Employee employee,Company company)
{
   employee.Comapany = company;
   UpdateModel(employee,new[] {"Name","Email","Phone"});
   return View();
}

通常,最好的方法是创建视图模型,即专门为视图构建的模型。这些模型不是域对象。它们是数据传输对象,用于将数据从控制器动作传输到视图模板。您可以使用类似的工具轻松地从视图模型对象创建/更新域模型对象,或从域模型创建/更新视图模型对象。

您尝试过使用以下工具吗?:

公共操作结果创建([Bind(Exclude=“PropertyToExclude1,PropertyToExclude2”)]Employee员工) {

//这里是行动代码

}


或者使用Include而不是Exclude列出哪些字段可以绑定,哪些字段不能绑定

谢谢您的回复。然而,绑定模型并没有任何问题:我的问题是试图限制模型中绑定的内容。在您的示例中,似乎在不向UpdateModel方法提供白名单或黑名单(或其他等效项)的情况下,有人仍然可以通过将Company.IsPremiumMember注入他们的表单post来设置它。然后,解决方案是将要包含的属性列表传递给UpdateModel方法。我会更新我的回答。我在原来的帖子上加了一个附录。(特别是见最后一行。)这个问题看起来更像是公司财产上的“全有或全无”…这是一个小问题,但在上面的表单示例中,文本框id attibutes将使用下划线而不是句点呈现,因此需要相应地修改标记的标签。谢谢你,Marwan,我确实看到你的最新编辑在技术上完成了我想要的。然而,由于我有大约八到九个对象(都是公司的孩子),因此以这种方式解释所有这些对象似乎不是很有吸引力。在我的例子中,我提出的解决方案似乎只允许我处理一个白名单和一个“UpdateModel”调用,并且还可以避免事后“重新附加”所有对象。我还可以在剩下的页面上重新使用我自己的白名单技术!再次感谢!AutoMapper看起来是一个非常好的实用工具,它确实可以简化这一过程。我要去看看
    <form action="Home/Create" method="post">
   <label for="Employee.Name">Name</label>
    <%=Html.TextBox("Employee.Name") %><br />
   <label for="Employee.Name">Age</label>    
    <%=Html.TextBox("Employee.Age") %><br />
   <label for="Employee.Name">Comapany Phone</label>    
    <%=Html.TextBox("Company.Phone") %><br />
    <input type="submit" value="Send" />
   </form>
 public ActionResult Create(Employee employee,Company company)
        {
            employee.Comapany = company;
            UpdateModel(employee);
            return View();
        }
public ActionResult Create(Employee employee,Company company)
{
   employee.Comapany = company;
   UpdateModel(employee,new[] {"Name","Email","Phone"});
   return View();
}