我认为这是一种有点正常的情况,我需要将表单帖子绑定到“订单”模型。这个模型有几个层次的信息:
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类型。虽然它被调用,但SetProperty对“Country”的调用具有空值,即使表单已发布名为“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映射到Address binder的Country属性时,应该调用CountryModelBinder。
答案 0 :(得分: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中BTW更好的选择是使用IModelBinderProvider接口,但我只是想展示一些可行的东西。