0

我写了一个基类和一些派生自它的类。

我想在一个 ActionResult 中使用这些类,但如果我试图将 PSBase 转换为 PS1,我会得到一个 PSBase 类型无法转换为 PS1 的 System.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
{
}

行动结果:

    [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 中。有什么想法可以实现吗?

4

1 回答 1

2

如果没有自定义 ModelBinder,您尝试做的事情将永远无法工作(即使那样,我也不建议实施它会造成巨大的混乱),抱歉。

只有当您将模型从 Controller 传递到 View 时,它才会记住它最初的类型(包括继承等),因为此时您仍然在页面的服务器端,并且您只是在传递一个对象。

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

在您的情况下,如果您有一个基于 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();
}

那么您必须通过不同的表单操作在视图中区分它们。

于 2013-04-17T11:51:49.023 回答