3

我为我的模型中的复杂类型创建了一些定制绑定器。我的模型由具有自己单独活页夹的对象组成。我希望基础对象执行其肮脏的工作,然后通过传递给标准ModelBinder路由来填充它封装的复杂对象。我该怎么做呢?如何从自定义ModelBinder中调用UpdateModel? (MVC)

为了便于说明,我创建了一个非常简单的示例。

说我的模型包含这些对象。

public class Person 
{ 
    public string Name {get; set;} 
    public PhoneNumber PhoneNumber {get; set;} 
} 

public class PhoneNumber 
{ 
    public string AreaCode {get; set;} 
    public string LocalNumber {get; set;} 
} 

而且我对这些模型中的每一个都有以下绑定器。并不是PersonBinder需要填充PhoneNumber,但不想复制PhoneNumber文件夹中的代码。它如何委托回到标准的Binder路由?

public class PersonBinder: IModelBinder 
{ 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext  bindingContext) 
    { 
     Person person = new Person(); 
     person.Name = bindingContext.ValueProvider.GetValue(String.Format("{0}.{1}", bindingContext.ModelName, "Name")).AttemptedValue 

     // This is where I'd like to have the PhoneNumber object use binding from another customer ModelBinder. 
     // Of course the bindingContext.ModelName should be updated to its current value + "PhoneNumber" 
     person.PhoneNumber = ???; // I don't want to explicitly call the PhoneNumberBinder it should go through standard Binding routing. (ie. ModelBinders.Binders[typeof(PhoneNumber)] = new PhoneNumberBinder();) 

     return person;  
    } 
} 

public class PhoneNumberBinder: IModelBinder 
{ 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext  bindingContext) 
    { 
     PhoneNumber phoneNumber = new PhoneNumber(); 
     phoneNumber.AreaCode = bindingContext.ValueProvider.GetValue(String.Format("{0}.{1}", bindingContext.ModelName, "AreaCode")).AttemptedValue 
     phoneNumber.LocalNumber = bindingContext.ValueProvider.GetValue(String.Format("{0}.{1}", bindingContext.ModelName, "LocalNumber")).AttemptedValue 

     return phoneNumber; 
    } 
} 

当然,我已经在Global.asax.cs文件中注册了我的ModelBinders。

protected void Application_Start() 
{ 
    AreaRegistration.RegisterAllAreas(); 

    RegisterRoutes(RouteTable.Routes); 

    ModelBinders.Binders[typeof(Person)] = new PersonBinder(); 
    ModelBinders.Binders[typeof(PhoneNumber)] = new PhoneNumberBinder(); 
} 

感谢,

贾斯汀

回答

2

那么我设法想出一个解决方案。请随时评论其有效性。

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
{ 
    Person person = new Person(); 
    person.Name = bindingContext.ValueProvider.GetValue("Name").AttemptedValue 

    if (bindingContext.ModelName == String.Empty) 
    { 
     bindingContext.ModelName = "PhoneNumber"; 
    } 
    else 
    { 
     bindingContext.ModelName = bindingContext.ModelName + ".PhoneNumber"; 
    } 

    PhoneNumber phoneNumber = new PhoneNumber(); 
    bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => phoneNumber, phoneNumber.GetType()); 

    IModelBinder binder = ModelBinders.Binders[typeof(PhoneNumber)]; 
    if (binder == null) 
    { 
      binder = ModelBinders.Binders.DefaultBinder; 
    } 

    person.PhoneNumber = binder.BindModel(controllerContext, bindingContext) as PhoneNumber; 

    return person;       
} 

这里是我所做的一个总结。

  1. 查找使用全局可访问ModelBinders.Binders收集的模型绑定器(退回到默认值,如果一个未注册)
  2. 的模型,我结合创建ModelMetadataProvider。
  3. 将bindingContext的ModelName属性设置为我试图填充的模型属性(“PhoneNumber”)。
0

而不是写粘结剂你可以用户AutoMapper和处理在操作复杂的模型构建。

+0

感谢您的建议,但我不认为AutoMapper是我的工具。看起来像一个解决方法。我确信活页夹应该原生支持这个功能。 – Justin 2010-07-06 20:13:15

相关问题