ASP.NET MVC4一视图多模型

3
我有以下的类结构。
public BaseClass
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public ClassOne : BaseClass
{

}

public ClassTwo : BaseClass
{

}

我的控制器像这样。
public TestController : Controller
{
     public ActionResult ClassOne()
     {
          ClassOne model = new ClassOne();
          return View("Create",model);
     }

     public ActionResult ClassTwo()
     {
          ClassTwo model = new ClassTwo();
          return View("Create",model);
     }         

我的视图(“创建”)如下所示:

     @model MvcApplication.Models.BaseClass

     @using(Html.BeginForm("Post","Test",FormMethod.Post))
     {
            @Html.HiddenFor(model => mode.Id)
            @Html.TextBoxFor(model => model.Name)
            <input type="submit" value="Submit"/>
     }

我的Post Action对两个模型ClassOne和ClassTwo都是相同的。在执行Post操作时,我如何知道传递给Post Action的是哪个模型,是ClassOne还是ClassTwo。

     [HttpPost]
     public ActionResult Post(BaseClass model)
     {
          /* Code */
     }

你尝试过在控制器中使用 "is" 关键字吗?(例如,如果(model is ClassTwo)) - Pacman
1
我不认为这是可能的。当调用帖子操作时,模型绑定器将尝试绑定到方法的参数,并在此过程中实例化一个没有关于传递给视图呈现它时的原始类型的知识的“BaseClass”实例 - 在任何情况下,视图的模型类型都是“BaseClass”,所以我就是看不到了... - Quinton Bernhardt
就像我回答的那样。您应该编写自定义ModelBinder并在表单中存储实际类型名称,然后在模型绑定器中创建适当的类。 - Dmytro Rudenko
有不同的技巧。在这里看一下答案,以及操作员自己的解决方案https://dev59.com/mnjZa4cB1Zd3GeqPZxik#19450985 - Colin
6个回答

2

在文章中,只需要检查类型。可以通过if(model is ClassOne)或者if(model.GetType() == typeof(ClassOne))来实现。


这是行不通的。如果没有存储关于类型的额外信息,无论是在隐藏字段中还是从 ViewBag / ViewData 中,模型绑定器都无法推断出类型。对于它而言,它只能创建基础类型。 - John H

2
我不确定是否可以在不创建自己的ModelBinder的情况下实现。在这种情况下,您将始终在操作中获得BaseType类的实例。

1
我同意。当触发post操作时,模型绑定器将尝试绑定到方法的参数 - 在此过程中,它将实例化一个“BaseClass”的实例,并对渲染视图时传入的原始类型一无所知。 - Quinton Bernhardt
1
你成功实现模型绑定所需要的全部,就是当前模型类型的相关信息。例如,你可以将其存储在视图中作为隐藏字段,在你的模型绑定器中获取这个信息,并创建适当类型的属性并填充它。 - Dmytro Rudenko
1
这种技术可以在不创建ModelBinder的情况下实现。https://dev59.com/12w05IYBdhLWcg3weBru#7376583 - Colin

1
你可以使用 typeof()

if(model.GetType() == typeof(ClassOne)){
 // do something
}else {
 // do something else.
}

编辑:

感谢 @JoreanVannevel

如果(model 是 ClassOne){}


简写形式:if model is ClassOne - Jeroen Vannevel
@JeroenVannevel 同意..:-) - Aniket Inge
不可以。模型绑定器没有任何区分已构造类型和基类本身的方法。这与普通的多态性不同。 - John H

0

你的问题是操作无法判断哪个类型,因为视图对操作类型是松散的。 但我们可以在视图中获取类型并将其发送到操作

视图如下: @model MvcApplication.Models.BaseClass

 @using(Html.BeginForm("Post","Test",FormMethod.Post))
 {
        @Html.HiddenFor(model => mode.Id)
        @Html.TextBoxFor(model => model.Name)
        @Html.Hidden("type", model.GetType().Tostring())

        <input type="submit" value="Submit"/>
 }

像这样的操作:

[HttpPost]
 public ActionResult Post(BaseClass model)
 {
      /* Code */
      if(Request["type"] == typeof( ClassOne).Tostring())
      {
      } 
      if(Request["type"] == typeof( ClassTwo ).Tostring())
      {
      } 
 }

0
你可以检查对象的类型。
if(model.GetType() == typeof(ClassOne))
{
    // Do something
}

请参见上文。模型绑定器没有足够的信息来区分它构造的派生类型中的哪一个,除非提供额外的信息。 - John H

0

Jonah,

你应该为一个视图使用一个模型。现在你可以做两件事情:

第一件事,

你可以使用自定义模型绑定器,参见这里 http://www.codeproject.com/Articles/605595/ASP-NET-MVC-Custom-Model-Binder

或者(第二件事),

在Html.Beginform中也可以放置隐藏字段以标识类型(例如ClassOne为1,ClassTwo为2)。现在创建一个第三个类,它具有ClassTwo和ClassOne的不同属性,BaseClass的公共属性和一个额外的属性用于类型信息。(此处不使用任何类型验证)提交时使用新创建的类型,然后检查类型字段。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接