ActionResult将参数基类转换为派生类

本文关键字:派生 转换 基类 参数 ActionResult | 更新日期: 2023-09-27 18:09:30

我已经写了一个基类和一些从它派生的类。

我想在一个ActionResult中使用这些类,但如果我试图将PSBase转换为PS1,我将获得一个System。不能将PSBase类型转换为PS1的InvalidCastException。

类:

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。有什么想法我可以实现这一点吗?

ActionResult将参数基类转换为派生类

如果没有自定义ModelBinder,您要做的事情将永远无法工作(即使这样,我也不建议实现它将是一个巨大的混乱),对不起。

只有当你将一个模型从控制器传递到视图时,它才会记住它最初是什么类型(包括继承等),因为在那一点上你仍然在页面的服务器端,你只是传递一个对象。

一旦你进入一个视图并提交一个表单,它就会创建一些POST请求,其主体包含基于输入名称的值列表。

在您的情况下,如果您有一个基于PS1的表单并使用所有字段作为输入,您将得到如下内容:

POST:
stationId = some value
name = some value
reference = some value

(未提及原始类型、控制器、方法等)

现在,MVC做的是检查你在方法的头(在你的情况下ProductionStep(PSBase ps))中使用的参数。

根据参数调用模型绑定器。默认模型绑定器所做的是创建该类的新实例(在您的示例中为PSBase),并通过反射遍历该类的所有属性,并尝试从POST主体获取它们。

如果POST主体中有一些额外的值,这些值将被遗忘。

除非你为这个默认MVC实现编写一个自定义模型绑定器,否则它无法帮助你。

我建议创建两个独立的方法,其中一个接受不同的PSBase实现。

如果你想了解更多关于Model binder的信息,请查看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();
}

那么你必须在视图中通过不同的表单动作来区分它们