2012-04-29 62 views
0

我想解决如何将包含多个对象类型的列表的模型绑定到ASP.NET MVC 3中的回发操作我已经得到了确定以下类别列表的车辆类型:ASP.NET MVC 3 - 将模型绑定到包含不同类型的List <>

public enum VehicleType 
{ 
    Car, 
    Plane. 
    Boat 
} 

public class BaseVehicle 
{ 
    public VehicleType VehicleType { get; set; } 
    public string Name { get; set; } 
    public int Passengers { get; set; } 
} 

public class Plane : BaseVehicle 
{ 
    public int WingSpan { get; set; } 
    // -- etc -- 
} 

// Properties omitted 
public class Car : BaseVehicle {} 
public class Boat : BaseVehicle {} 

public class VehiclesViewModel 
{ 
    public string Notes { get; set; } 
    public List<BaseVehicle> Vehicles { get; set; } 
} 

以上课程由这些视图显示:

<!-- VehiclesView.cshtml - loaded by the controller --> 
@model Mvc3Test.Models.VehiclesViewModel 
<h2>Vehicles</h2> 
@Html.EditorFor(m => m.Notes) 
<hr /> 
@Html.EditorFor(m => m.Vehicles) 

<!-- BaseVehicle.cshtml --> 
@model BaseVehicle 
@using Mvc3Test.Data 
@Html.HiddenFor(m => m.VehicleType) 
@{ 
    if (Model.VehicleType == VehicleType.Car) 
    { 
     Html.RenderPartial("Car", (Car)Model); 
    } 
    else if (Model.VehicleType == VehicleType.Plane) 
    { 
     Html.RenderPartial("Plane", (Plane)Model); 
    } 
    // etc.. 
} 

<-- Plane.cshtml --> 
@model Mvc3Test.Data.Plane 
<h2>Plane</h2> 
<p>Name: @Html.EditorFor(m => m.Name)</p> 
<p>Passengers: @Html.EditorFor(m => m.Passengers)</p> 
<p>Wingspan: @Html.EditorFor(m => m.WingSpan) metres</p> 

<!-- Car.cshtml omitted --> 

我不知道它上面是最好的处理显示的方法(特别是视图中的if语句),但它现在可行。问题是如何绑定回视图模型类。我试过用Html.TextBox()替换Html.TextBorFor(),所以我可以添加绑定前缀(“Vehicles.Car”等),但似乎没有获得默认模型绑定器来确定在html中表示什么样的类,因此可以实例化正确的类型。

我想我必须编写一个自定义模型绑定器来解决这个问题 - 这是正确的使用方法还是存在另一种我错过的方法?

感谢所有帮助

+1

我觉得http://stackoverflow.com/questions/6484972/viewmodel-with-listbaseclass-and-editor-templates应该帮助你。 – DMulligan

+1

@AFinkelstein听起来像是我的重复。 –

+0

是的 - 这是一个重复 - 对不起 - 我没有遇到过其他问题.. – Nick

回答

2

的所有

 
if (Model.VehicleType == VehicleType.Car) 
    { 
     Html.RenderPartial("Car", (Car)Model); 
    } 
    else if (Model.VehicleType == VehicleType.Plane) 
    { 
     Html.RenderPartial("Plane", (Plane)Model); 
    } 

首先可与EditorFor.Works就好被省略。

至于绑定回来 - 国际海事组织的最佳途径是创建自定义模型绑定。

例子:

 
public class DerivedTypeModelBinder : DefaultModelBinder 
    { 
     public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
     { 
      var typeName = GetVehicleType(bindingContext); 
      if (typeName != null) 
      { 
       var modelType = Type.GetType(typeName); 
       var targetTypeInstance = Activator.CreateInstance(modelType); 
       bindingContext = new ModelBindingContext 
            { 
             ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => targetTypeInstance, modelType), 
             ModelState = bindingContext.ModelState, 
             FallbackToEmptyPrefix = bindingContext.FallbackToEmptyPrefix, 
             ModelName = bindingContext.FallbackToEmptyPrefix ? string.Empty : bindingContext.ModelName, 
             ValueProvider = bindingContext.ValueProvider, 
            }; 
      } 
      return base.BindModel(controllerContext, bindingContext); 
     } 
     private string GetVehicleType(ModelBindingContext bindingContext) 
     { 
      var valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + "." + "VehicleType"); 
      if (valueResult == null && bindingContext.FallbackToEmptyPrefix) 
      { 
       valueResult = bindingContext.ValueProvider.GetValue("VehicleType"); 
      } 
      return valueResult == null ? null : valueResult.AttemptedValue; 
     } 
    } 
+0

sry,将始终更新之前post =) –