关于asp.net mvc:bind属性包含和排除具有复杂类型的嵌套对象的属性

bind attribute include and exclude property with complex type nested objects

好吧,这很奇怪。 我不能在ASP.NET MVC上将BindAttributeIncludeExclude属性与复杂类型的嵌套对象一起使用。

这是我所做的:

模型:

1
2
3
4
5
6
7
8
9
10
public class FooViewModel {

    public Enquiry Enquiry { get; set; }
}

public class Enquiry {

    public int EnquiryId { get; set; }
    public string Latitude { get; set; }
}

HTTP POST操作:

1
2
3
4
5
6
7
[ActionName("Foo"), HttpPost]
public ActionResult Foo_post(
    [Bind(Include ="Enquiry.EnquiryId")]
    FooViewModel foo) {

    return View(foo);
}

视图:

1
2
3
4
5
6
7
@using (Html.BeginForm()) {

    @Html.TextBoxFor(m => m.Enquiry.EnquiryId)
    @Html.TextBoxFor(m => m.Enquiry.Latitude)

    <input type="submit" value="push" />
}

根本不起作用。 如果我为Enquiry类定义了BindAttribute,请问是否可以使它工作:

如何在复杂的嵌套对象上使用[Bind(Include =")]属性?


是的,您可以像这样使它工作:

1
2
3
4
5
6
[Bind(Include ="EnquiryId")]
public class Enquiry
{
    public int EnquiryId { get; set; }
    public string Latitude { get; set; }
}

和你的动作:

1
2
3
4
5
[ActionName("Foo"), HttpPost]
public ActionResult Foo_post(FooViewModel foo)
{
    return View(foo);
}

这将在绑定中仅包含EnquiryId,而将Latitude保留为空。

话虽这么说,但我不建议您使用Bind属性。我的建议是使用视图模型。在这些视图模型内,您仅包含对该特定视图有意义的属性。

因此,只需重新调整您的视图模型即可:

1
2
3
4
5
6
7
8
9
public class FooViewModel
{
    public EnquiryViewModel Enquiry { get; set; }
}

public class EnquiryViewModel
{
    public int EnquiryId { get; set; }
}

你去。不再需要担心绑定。


恕我直言,有一个更好的方法来做到这一点。

本质上,如果视图模型中有多个模型,则后视图控制器的签名将包含相同的模型,而不是视图模型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class FooViewModel {
    public Bar BarV { get; set; }
    public Enquiry EnquiryV { get; set; }
    public int ThisNumber { get; set; }
}

public class Bar {
    public int BarId { get; set; }
}

public class Enquiry {
    public int EnquiryId { get; set; }
    public string Latitude { get; set; }
}

控制器中的后动作将如下所示。

1
2
3
4
5
6
7
8
9
10
[ActionName("Foo"), HttpPost]
public ActionResult Foo_post(
    [Bind(Include ="EnquiryId")]
    Enquiry EnquiryV,
    [Bind(Include ="BarId"])]
    Bar BarV,
    int ThisNumber
{
    return View(new FooViewModel { Bar = BarV, Enquiry = EnquiryV, ThisNumber = ThisNumber });
}

一直这样看来

1
2
3
4
5
6
7
8
9
@using (Html.BeginForm()) {

    @Html.TextBoxFor(m => m.EnquiryV.EnquiryId)
    @Html.TextBoxFor(m => m.EnquiryV.Latitude)
    @Html.TextBoxFor(m => m.BarV.BarId)
    @Html.TextBoxFor(m => m.ThisNumber)

    <input type="submit" value="push" />
}

请注意,此表单仍会回传纬度(您的设置方式),但是由于该表单未包含在对发布操作进行查询的"绑定包含"字符串中,因此该操作将不接受结果中的新值查询。我建议禁用纬度,或者不要将其设置为表单元素,以防止其他发布数据。

在任何其他情况下,都可以使用bind,但是由于某种原因,它不喜欢复杂模型的点表示法。

附带说明一下,我不会将bind属性直接放在类上,因为它会引起其他问题,例如代码复制,并且不能解决某些情况下您可能需要使用不同的绑定的情况。

(为了清楚起见,我修改了变量名。我也知道您的问题是过时的,但是在我自己寻找答案时,这是我偶然发现的第一个SO,然后尝试使用自己的解决方案并发布了我的解决方案。我希望它可以帮助其他人寻求解决同一问题的方法。)