C# 具有子界面的ASP.NET MVC 4视图模型

C# 具有子界面的ASP.NET MVC 4视图模型,c#,asp.net,asp.net-mvc-4,asp.net-mvc-viewmodel,C#,Asp.net,Asp.net Mvc 4,Asp.net Mvc Viewmodel,有没有一种方法可以在没有自定义模型绑定的情况下处理此问题 public class MyViewModel { public string UserId { get; set; } public IJob Job { get; set; } } public interface IJob { public long Id { get; set; } public string CompanyName { get; set; } } public class FullTimeJ

有没有一种方法可以在没有自定义模型绑定的情况下处理此问题

public class MyViewModel {
  public string UserId { get; set; }
  public IJob Job { get; set; }
}

public interface IJob {
  public long Id { get; set; }
  public string CompanyName { get; set; }
}

public class FullTimeJob : IJob {
  // omitted for brevity
}

public class Internship : IJob {
  // omitted for brevity
}
我遇到的问题是,默认模型绑定器中出现了一个错误,因为它不知道要实例化IJob的哪个实现。创建MyViewModel时,我将FullTimeJob的一个实例设置到其Job属性中。我猜ASP.NET不能保留实现类型


最佳实践解决方案是什么?

视图只是UI和控制器之间的数据载体。因此,只需将Id和CompanyName属性添加到视图中即可。因为您只需要从UI获取Id和公司值。从用户界面获取数据时,无论是实习还是全职工作,这可能并不重要。当您处理从用户界面获取的数据时,这一点可能很重要,但不是View的责任。

一个选项,尽管不是特别优雅,但可能是以下选项:

public class MyViewModel {
    public string UserId { get; set; }
    public FulltimeJob FulltimeJob { get; set; }
    public InternJob InternJob { get; set; }

    public IJob Job { get { return FulltimeJob ?? InternJob; } }
}
这使您可以通过作业属性轻松访问共享属性,同时保持对任何特定于类的属性的访问


然后,您可以检查在POST controller方法中填充的属性,并采取相应的行动。

我希望能够维护对象层次结构,因此我绝对希望避免将作业相关字段直接放到视图模型中。如果我这样做,ViewModel不会给我买任何东西。是的,我是在自定义模型活页夹中这样做的,但我只是希望会有一个不那么自定义的答案。你可以让你的ViewModel像
类MyViewModel一样通用,其中t:IJob,new()
,在构造函数中你可以实例化你的自定义作业类型
Job=new t()但它仍然取决于具体的作业类型。我不认为您可以将数据发布到采用泛型类参数的控制器方法,因此如果您采用泛型方法,您可能需要显式类(例如
FulltimeJobModel:JobModel
)和其他控制器重载。这就是我试图告诉您的“但这仍然取决于具体的工作类型”这是一个解决方案的好主意,我知道你会怎么做,尽管问题是,每当我添加IJob的新实现时(我已经有6个),我必须修改这个类。如果您添加的这两个额外字段位于地图或集合中,这并不可怕,但它仍然感觉有点笨拙。我同意;我想这取决于这些类有多相似,以及您是否真的应该为它们共享视图和控制器方法。另一个(尽管相似)路线是将视图模型展平,只包括字段(所有作业类中所有字段的联合)以及作业类型,以便让您知道控制器中预期填充的字段。使用AutoMapper或Fasterflect简化/自动化属性映射,使之更容易。