我编写了一个基类和一些派生自它的类。
我想在一个ActionResult中使用这些类,但如果我试图将PSBase转换为PS1,我会收到一个System.InvalidCastException类型PSBase无法转换为PS1。
类:
public class PSBase
{
public int stationId { get; set; }
public string name { get; set; }
}
public class PS1 : PSBase
{
public string reference { get; set; }
}
public class PS2 : PSBase
{
}
的ActionResult:
[HttpPost]
public ActionResult ProductionStep(PSBase ps)
{
if (ModelState.IsValid)
{
var product = db.Product.FirstOrDefault(.........);
switch (ps.stationId )
{
case 1:
{
product.Reference = ((PS1)ps).reference;
db.SaveChanges();
break;
}
}
}
return View();
}
因为我不希望每个类都有自己的ActionResult(多次重复相同的代码)我想把所有这些都放到一个ActionResult中。任何想法如何实现这个?
答案 0 :(得分:1)
如果没有自定义的ModelBinder,你要做的事情将永远无法工作(即便如此,我也不建议实施它将是一个巨大的混乱),对不起。
只有当您将模型从Controller传递给View时,它才会记住它最初的类型(包括继承等),因为此时您仍然在页面的服务器端,而您只是传递一个对象。
一旦您输入视图并提交表单,它就会创建一些POST请求,其中body包含基于输入名称的值列表。
在您的情况下,如果您有一个基于PS1的表单并使用所有字段作为输入,您会得到类似的结果:
POST:
stationId = some value
name = some value
reference = some value
(没有提到原始类型,控制器,方法等)
现在,MVC所做的是它检查你在方法的标题中使用了什么参数(在你的情况下是ProductionStep(PSBase ps))。
基于参数,它称为模型绑定器。默认模型绑定器的作用是它创建该类的新实例(在您的情况下为PSBase)并通过反射通过该类的所有属性并尝试从POST主体获取它们。
如果POST主体中有一些额外的值,则会忘记这些值。
除非您为此默认MVC实现编写自定义模型绑定器,否则无法帮助您。
我建议创建两个单独的方法,每个方法都接受不同的PSBase实现。
如果您想了解有关模型粘合剂的更多信息,请查看http://msdn.microsoft.com/en-us/magazine/hh781022.aspx
编辑:
通过创建两个单独的方法,我的意思是这样的:
[HttpPost]
public ActionResult ProductionStepA(PS1 ps)
{
if (ModelState.IsValid)
{
}
return View();
}
[HttpPost]
public ActionResult ProductionStepB(PS2 ps)
{
if (ModelState.IsValid)
{
}
return View();
}
然后你必须通过不同的表单动作在视图中区分它们。