Asp.net mvc 嵌套级别的DefaultModelBinder问题+;其他粘合剂

Asp.net mvc 嵌套级别的DefaultModelBinder问题+;其他粘合剂,asp.net-mvc,nested,modelbinders,defaultmodelbinder,Asp.net Mvc,Nested,Modelbinders,Defaultmodelbinder,我认为这是一种正常情况,需要将表单帖子绑定到“订单”模型。此模型有几个层次的信息: Order.Billing.FirstName Order.Billing.Address.City Order.Billing.Address.Country 使用DefaultModelBinder,如果我将表单发布到将此订单模型作为参数的操作,则以下字段JustWork(TM): 此字段不包括: <%=Html.TextBox("Billing.Address.Country")%>

我认为这是一种正常情况,需要将表单帖子绑定到“订单”模型。此模型有几个层次的信息:

Order.Billing.FirstName
Order.Billing.Address.City
Order.Billing.Address.Country
使用DefaultModelBinder,如果我将表单发布到将此订单模型作为参数的操作,则以下字段JustWork(TM):


此字段不包括:

<%=Html.TextBox("Billing.Address.Country")%>

我遇到的麻烦是乡村财产。在我们的例子中,Address.Country返回一个Country类实例(ISO2/3/Name/Code逻辑)。它不是一根弦。它在默认情况下不起作用也就不足为奇了

我的第一个想法是创建CountryModelBinder(继承DefaultModelBinder)和ModelBinders.Binders.Add,将其添加到Country类型中。当我这么做的时候,CountryModelBinder从来没有在上面的场景中被调用过

我的第二个想法是创建AddressModelBinder(继承DefaultModelBinder)并将其绑定到我们的地址类型。虽然它确实被调用,但是“Country”的SetProperty调用有一个空值,即使表单已经发布了一个名为“Billing.Address.Country”的字段

经过一些修补之后,似乎只有当模型是操作所需的顶级类时,模型绑定行为才会调用CreateModel,并且所有其他绑定都会为子属性调用其BindProperty/SetProperty

换句话说,如果我为订单、订单地址(账单)、地址和国家创建模型绑定器。对于接受订单的操作,仅调用OrderModelBinder.CreateModel。ORderAddress和Address.BindProperty/SetProperty在某些情况下被调用,有时SetProperty值参数在与其他字段属性映射匹配的名称中明确发布时为空

只需将代码添加到OrderModelBinder中,即可将Billing.Address.Country从Request.Form中拉出。但我有多个使用地址的模型,让所有的模型都使用地址,这似乎是不正确的


我错过了什么?在这种情况下,有没有办法让CountryModelBinder真正被调用?我认为,当Billing.Address.Country映射到地址绑定器的Country属性时,应该调用CountryModelBinder。

我已经尝试了您在这里所做的,似乎在MVC3上。如果我为该类型提供了一个模型绑定器,它确实可以工作

这只是一个概念证明,以表明它确实有效,甚至不应被视为接近生产级代码:

型号:

public class SimpleModel
    {
        public string Value { get; set; }
        public int Other { get; set; }
    }

    public class ComplexModel
    {
        public SimpleModel Complexity {get;set;}
        public string StrVal { get; set; }
    }
一些活页夹:

public class MBinder : IModelBinder
        {
            public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
            {
                if ( bindingContext.ModelType == typeof(SimpleModel))
                {
                    var simpleModel= new SimpleModel();
                    simpleModel.Other = 1;
                    simpleModel.Value = controllerContext.HttpContext.Request.Form["Complexity"];

                    return cm;
                }
                return null;
            }
        }
在全球asax中:

ModelBinders.Binders.Add(typeof (SimpleModel), new MBinder());
视图中的代码:

    @model ComplexModel

    @using ( Html.BeginForm() )
{ 
    <fieldset>
        @Html.LabelFor(x => x.Complexity)
        @Html.TextBoxFor(x => x.Complexity)
    </fieldset>

    <fieldset>
        @Html.LabelFor(x => x.StrVal)
        <br />
        @Html.EditorFor(x => x.StrVal)
    </fieldset>
    <input type="submit" />
}

顺便说一句,在MVC 3中,更好的选择是使用IModelBinderProvider接口,但我只是想展示一些有用的东西。

这可能会帮助您:我对嵌套模型结构也有同样的问题,在我看来,顶层和底层的属性都受到约束,但任何低于这个标准的东西似乎都会被忽视。这是模型绑定器的正常行为吗?这似乎是相当武断的行为。
    @model ComplexModel

    @using ( Html.BeginForm() )
{ 
    <fieldset>
        @Html.LabelFor(x => x.Complexity)
        @Html.TextBoxFor(x => x.Complexity)
    </fieldset>

    <fieldset>
        @Html.LabelFor(x => x.StrVal)
        <br />
        @Html.EditorFor(x => x.StrVal)
    </fieldset>
    <input type="submit" />
}
public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Index(ComplexModel model)
        {
            return RedirectToAction("Index");

        }