【问题标题】:ASP.NET MVC ViewModel inheritance issueASP.NET MVC ViewModel 继承问题
【发布时间】:2013-02-02 22:37:00
【问题描述】:

我有以下 ViewModel:

public class MyViewModel
{
  public BaseViewModel mySubViewModel;
}

public class ChildViewModel: BaseViewModel
{}

然后我创建一个 MyViewModel 模型,其中包含 ChildViewModel 类型的属性。在 View 中,它显示得很好。

然后我点击保存按钮以提交对我的模型的更改并调用以下控制器:

    [HttpPost]
    public ActionResult Edit(MyViewModel model)
    {
        return null;
    }

令我惊讶的是,属性 mySubViewModel 现在的类型是 BaseViewModel 而不是 ChildViewModel !我不知道这里发生了什么。我究竟做错了什么 ?

【问题讨论】:

    标签: asp.net-mvc-4 viewmodel


    【解决方案1】:

    令我惊讶的是,属性 mySubViewModel 现在是类型 BaseViewModel 而不是 ChildViewModel !我不知道发生了什么 在这。我做错了什么?

    你不应该对此感到惊讶。你没有做错什么。这是设计使然。默认模型绑定器看到您的控制器操作正在使用 MyViewModel 参数并尝试将 POST 请求的内容绑定到它。默认模型绑定器绝对无法知道您可能已经编写了一些派生类(例如 ChildViewModel 在您的情况下)并且您希望在此处实例化这些派生类。您已将这个具体的视图模型实例从 GET 操作传递到视图这一事实对 POST 操作没有影响。根据 HTTP 和默认模型绑定器看到的内容来考虑它。例如,可以从一些完全不同的客户端而不是从表单提交中调用此 POST 操作。例如,可能是一个 iPhone 应用程序对 POST 操作执行 HTTP 请求。看,现在它很有意义。默认模型绑定器只能看到 POST 请求的有效负载和您指定为操作参数的类型。这就是他所做的 => 它实例化此类型并从 POST 有效负载数据绑定其属性。

    因此,一种可能性是编写一个自定义模型绑定器,它将实例化您希望的视图模型的具体实例。我已经在this post 举例说明了这样一个自定义模型绑定器。在此示例中,我在表单中包含了一个隐藏字段,该字段将包含我们希望实例化的视图模型的具体类型,然后自定义模型绑定器只需使用此信息在运行时创建此类型。

    【讨论】:

    • 另一种方法是将MyViewModel 上的mySubViewModel 类型更改为ChildViewModel
    • 是的,这也可以。但我猜 OP 不知道要使用的确切运行时类型并且不希望它被硬编码,这就是他使用基本类型作为其操作的参数的原因。
    • 完全正确,我只知道运行时的类型。我今天没有时间查看您的链接,但是一旦我阅读了这篇文章,我一定会回复您。非常感谢您的帮助。
    • 其实我有时间看看你的链接。模型活页夹确实是我应该使用的。您在帖子中建议的代码只有一个问题。您将 modelType 参数传递给 CreateModel 方法,但从不使用此参数。代码中是否有错字?
    • 不,这根本不是错字。自定义模型绑定器使用此参数来了解它应该实例化的具体类型。查看模型绑定器中的以下行:var typeValue = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".ModelType");。注意后缀?如果没有这个隐藏值,模型绑定器将不知道它应该实例化哪个具体视图模型,这是您最初的问题。
    猜你喜欢
    • 2011-07-12
    • 1970-01-01
    • 1970-01-01
    • 2011-10-20
    • 2014-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    相关资源
    最近更新 更多