2012-12-22 48 views
7

有没有办法处理这个没有自定义模型绑定?ASP.NET MVC 4 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 FullTimeJob : IJob { 
    // omitted for brevity 
} 

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

我遇到的问题是我得到默认模型绑定错误,因为它不理解实例化哪个实现IJob的。当我创建MyViewModel时,我将FullTimeJob的一个实例设置到它的Job属性中。我猜ASP.NET不能保留实现类型?

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

回答

1

视图只是UI和控制器之间的数据载体。所以你可以简单地将Id和CompanyName属性添加到你的视图中。因为你想要做的就是从UI获取Id和公司价值。从UI获取数据时,无论是实习还是全职工作都不重要。处理从UI获得的数据可能很重要,但这不是View的责任。

+0

我希望能够维护对象层次结构,所以我绝对想*避免*将作业相关的字段直接放到视图模型上。如果我这样做,ViewModel不会给我买东西。 –

+0

是的,我在一个自定义模型绑定中做了这个,但我只是希望有一个不太自定义的答案。 –

+0

你可以让你的ViewModel类似于'class MyViewModel 其中T:IJob,new()',并且在构造函数中你可以实例化你自定义的作业类型Job = new T();'但它仍然取决于具体的Job类型。 –

0

一种选择,虽然不是特别优雅,可能是以下几点:

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控制器方法中填充并采取相应措施。

+0

这对于解决方案来说是一个很好的想法,而且我知道你要去哪里,尽管问题出在我添加IJob的新实现(我已经有6个),我不得不修改这个类。如果你添加的这两个额外的字段在地图或集合中,这并不是很糟糕,但它仍然感觉有点笨拙。 –

+0

我同意;我想这归结于这些类的相似程度,以及您是否真的应该为它们共享视图和控制器方法。另一种(虽然相似)的路线是平坦化视图模型,只包括字段(来自所有工作类的所有字段的联合)以及JobType,以便让您知道控制器中可以填充哪些字段。使用AutoMapper或Fasterflect来简化/自动化属性映射,使其更容易一些。 –