asp.net MVC模型绑定错误“无法创建接口实例”
本文关键字:创建 接口 实例 MVC net 模型 绑定 错误 asp | 更新日期: 2023-09-27 18:16:16
我有一个ViewModel,它有一个接口作为属性。当我提交页面时,我得到了"Cannot create a instance of Interface"的错误。
ViewModel是这样的:
public class PlanoPagamentoViewModel
{
//some properties
public IPlanoPagamentosParcelas PlanoPagamentosParcelas { get; set; }
}
有两个类实现这个接口。相应的ViewModels动态地加载一个PartialView,这取决于所选择的选项。
public class PlanoPagamentoCartaoViewModel : IPlanoPagamentosParcelas
{
//some properties
}
public class PlanoPagamentoCrediarioViewModel : IPlanoPagamentosParcelas
{
//some properties
}
我做了一个研究,我发现需要创建一个自定义模型绑定,我这样做了:
public class PlanoPagamentoParcelasBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
var type = typeof(PlanoPagamentoCartaoViewModel);
var model = Activator.CreateInstance(type);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, type);
return model;
}
}
在Global中添加这个新的自定义绑定。asax, Application_Start方法:
ModelBinders.Binders.Add(typeof(IPlanoPagamentosParcelas), new PlanoPagamentoParcelasBinder());
它适用于PlanoPagamentoCartaoViewModel
,但我需要为PlanoPagamentoCrediarioViewModel
有另一个自定义绑定,但我不能只是添加一个新的modelbinder . binder . add与相同的键(IPlanoPagamentosParcelas
),因为已经有一个键与此类型。
那么,有没有其他的方法来为实现相同接口的ViewModels创建自定义模型绑定?
我相信解决办法如下:
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
var typeValueProvider = bindingContext.ValueProvider.GetValue("Type");
var type = (int)typeValueProvider.ConvertTo(typeof(int));
Type instanceType = null;
switch (type)
{
case 1:
instanceType = typeof(PlanoPagamentoCartaoViewModel );
break;
case 2:
instanceType = typeof(PlanoPagamentoCrediarioViewModel );
break;
}
if (!typeof(IPlanoPagamentosParcelas).IsAssignableFrom(instanceType))
{
throw new InvalidOperationException("Bad Type");
}
var model = Activator.CreateInstance(instanceType);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, instanceType);
return model;
}
在上面的代码var typeValueProvider = bindingContext.ValueProvider.GetValue("Type");
Type
将决定实例化哪个具体类。我已经测试了这个解决方案,它对我很有效。它可以改进为更具可扩展性(删除开关为其他东西可能),但我只是试图使它工作。
这里是我基于我的问题(也许你可以从那里得到更多的信息)多态模型绑定,下面是我创建的代码来模拟这个场景(只是在有疑问的情况下):
模型:
public class NewVehicleViewModel
{
public string Type { get; set; }
public VehicleViewModel Vehicle { get; set; }
}
public interface VehicleViewModel
{
string Name { get; set; }
string Color { get; set; }
}
public class CarViewModel : VehicleViewModel
{
public string Color { get; set; }
public string Name { get; set; }
public string Brand { get; set; }
}
public class TankViewModel : VehicleViewModel
{
public string Color { get; set; }
public string Name { get; set; }
public string Weapon { get; set; }
}
粘合剂:
public class VehicleBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
var typeValueProvider = bindingContext.ValueProvider.GetValue("Type");
var type = (int)typeValueProvider.ConvertTo(typeof(int));
Type instanceType = null;
switch (type)
{
case 1:
instanceType = typeof(CarViewModel);
break;
case 2:
instanceType = typeof(TankViewModel);
break;
}
if (!typeof(VehicleViewModel).IsAssignableFrom(instanceType))
{
throw new InvalidOperationException("Bad Type");
}
var model = Activator.CreateInstance(instanceType);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, instanceType);
return model;
}
}
控制器:
public class VehiclesController : Controller
{
// GET: Vehicles
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Create(NewVehicleViewModel vm)
{
return View();
}
}
全球。ASAX:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ModelBinders.Binders.Add(typeof(VehicleViewModel), new VehicleBinder());
}
视图(Index.cshtml):
@{
ViewBag.Title = "New Vehicle";
}
@using (Html.BeginForm("Create", "Vehicles"))
{
<label>Type</label>
<input name="type" type="text" />
<label >Name</label>
<input name="Vehicle.Name" type="text"/>
<label>Color</label>
<input name="Vehicle.Color" type="text" />
<label>Weapon</label>
<input name="Vehicle.Weapon" type="text" />
<label>Brand</label>
<input name="Vehicle.Brand" type="text" />
<input type="submit" />
}
问候。