我使用Automapper或手动映射,它不起作用。
ReleaseViewModel的所有数据必须是Release中的第一个,因为它在数据访问层中填充了它。 90%的模特都是这样的。为什么要复制一切的开销呢?
KISS原则和过度工程怎么样?
当然,每个工具都适合其适当的任务,但我经常读到,在asp.net mvc中不使用ViewModel是NO-GO。
在哪里划线?当我们从模型中区分到50%,75%或99%时,我应该使用ViewModels吗?
我有一个模型发布:
public class Release
{
public int Id { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public DateTime CreatedAt { get; set; }
public int FailedTestsCount { get; set; }
public int SucceededTestsCount { get; set; }
public int SumTestsCount
{
get
{
return SucceededTestsCount + FailedTestsCount;
}
}
public int SumTestingTime { get; set; }
}
viewmodel ReleaseViewModel:
public class ReleaseViewModel
{
[HiddenInput(DisplayValue = false)]
public int Id { get; set; }
[Required(ErrorMessage = "Name must not be empty.")]
[StringLength(30, ErrorMessage = "Enter max. 30 chars for a name.")]
[Remote("ReleaseExists", "Release", ErrorMessage = "This name already exists.")]
public string Name { get; set; }
public string Author { get; set; }
public DateTime CreatedAt { get; set; }
public int FailedTestsCount { get; set; }
public int SucceededTestsCount { get; set; }
public int SumTestsCount
{
get
{
return SucceededTestsCount + FailedTestsCount;
}
}
public int SumTestingTime { get; set; }
}
答案 0 :(得分:5)
ViewModel
适用于 VIEW 。大部分时间它与您的实体模型类似。但并非总是如此。
看看你的例子。在ViewModel
中,您拥有Remote
属性和一些验证属性。因此,您可以添加此远程名称检查,以便为用户提供更好的用户体验。它特定于View。
您需要Viewmodel的另一个场景是适用于涉及多个模型的屏幕。例如:您有一个User
实体和一个Project
实体,并且您希望提供一个可以将项目添加到用户的屏幕。所以在这种情况下,您可以创建一个viewmodel来处理
public class ProjectToUserVM
{
public int UserId { set;get;}
public string UserName { set;get;} // i want to display only name of user!
public int ProjectID { set;get;}
public IEnumerable<SelectListItem> Projects { set;get}
}
不要将ViewModel用于所有模型实体。当您的VIEW确实需要时创建它。我在一些视图中直接使用我的Model实体对象而不创建一个viewmodel,因为它们完全相同。例如:国家/州/市(查找表数据。无添加/编辑)
答案 1 :(得分:2)
为什么要复制一切的开销?
首先,你可能会认为我正在复制代码,但事实是你不是,如果你这样做,你就会认真对待设计问题
我发现有一个原则,当你不遵循它时,它确实是万恶之源:SRP(单一责任原则)
也许是因为你还没有找到问题,或者你可能已经修补了你的代码。 您的域对象的责任与向用户呈现数据的责任完全不同。
MVC中的模型应该是一个表示视图需要呈现的所有数据的类,而不是。您需要使用域中的数据填充此模型。 (或在CQRS架构中,来自您的查询服务)
如果你遵循CQRS架构(至少是基础知识,你不需要实现事件来源,也不需要使用服务总线来将命令与你的查询分开),这对你来说更明确,查询对象与命令对象(来自您的域的操作)完全不同
我认为你误解了KISS原则,虽然它说的是过度设计代码或YAGNI,但这并不意味着你必须重用应用程序中的所有内容
相信我,我学会了这个坏方法=(,唯一应该重用的代码是基础设施代码,在谈论域代码时,最好始终遵循SRP
答案 2 :(得分:1)
我的ViewModel只需包装一个Model,并在90%的时间内委托给它。当我需要针对特定视图用例更改模型的行为时,它们只有自己的行为。拥有VM确实可以更容易地添加仅用于显示目的的行为,特别是如果该行为会干扰您的持久性模型(例如,添加不想要持久化的属性)。
值得注意的是,很有可能使用像Castle或SpringFramework.net这样的IoC工具动态生成默认转发行为,减少手动编写所需的代码量。这相当大地降低了“复制成本”,所以它没有最初看起来那么糟糕。
答案 3 :(得分:0)
我是Shyju所说的第二件事,特别是关于“何时需要它”的部分。
如果你有一个非常简单的项目,你的EntityModel类与ViewModel类位于同一个库中,你可能不需要单独的ViewModel dto并且可以放弃它们。我不认为任何智能人会告诉你“你做错了,因为你正在使用实体类来查看你的视图模型,dumass。”我们不知道您的应用程序的上下文是什么。在你的情况下,这可能是完全合适的。
我们中的一些人在非Web程序集中定义EntityModels - 只是一个编译成DLL的普通类库 - 用于大型项目。在这种情况下,我们经常需要将特殊属性应用于视图,例如示例问题中的RemoteAttribute和HiddenInputAttribute。但是,在不使用单独的viewmodel dto层的情况下执行此操作意味着我们必须将对System.Web.Mvc.dll的引用添加到EntityModel库,而实际上该库与Web无关“
请记住,当您在Web项目中重用EntityModel类(即将它们用作存储模型和演示模型)时,您正在创建项目的Web方面与您的业务方面之间更紧密的耦合。项目。如果你可以因为成本/预算,时间,目标受众,范围或其他限制而证明这一点,那就去做吧,而忽视你的评论家,因为他们没有像你那样看到那么大的画面。
答案 4 :(得分:0)
如果您的Release类实现了INotifyPropertyChanged以及视图所需的所有其他内容(验证,命令......),那么您不必使用viewmodel。但如果不是......