7

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

Order.Billing.FirstName
Order.Billing.Address.City
Order.Billing.Address.Country

使用 DefaultModelBinder,如果我将表单发布到以该 Order 模型作为参数的操作,则以下字段 JustWork(TM):

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

该字段不:

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

我的皱纹与乡村财产有关。在我们的例子中,Address.Country 返回一个 Country 类实例(ISO2/3/Name/Code 逻辑)。它不是一个字符串。默认情况下它不起作用也就不足为奇了。

我的第一个想法是创建一个 CountryModelBinder(继承 DefaultModelBinder)和 ModelBinders.Binders。将其添加到 Country 的类型中。当我这样做时, CountryModelBinder 永远不会在上面的场景中被调用。

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

经过一番修改后,模型绑定行为似乎仅在模型是操作所需的顶级类时才调用 CreateModel,并且所有其他绑定器都为子属性调用了它们的 BindPropery/SetProperty。

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

只需向 OrderModelBinder 添加代码即可将 Billing.Address.Country 从 Request.Form 中拉出,这很容易。但是我有多个使用 Address 的模型,并且让所有模型都这样做似乎坏了。

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

4

1 回答 1

0

我已经尝试过您在此处所做的事情,显然在 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" />
}

控制器:

public ActionResult Index()
        {
            return View();
        }

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

        }

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

于 2011-02-28T18:27:50.283 回答