我在MVC3编程中尝试自己。在查看示例应用程序的过程中,我经常会看到模型,视图和控制器之外的ViewModel等内容。
我的问题:使用它们是否有意义?如果是:如何和模型和ViewModel之间的差异?
非常感谢!
编辑: 谢谢你的回答:
这意味着如果我有一个模型用户:
public string Username {get;set;}
public string mail{get;set;}
public string password{get;set;}
public string gender {get;set;}
And some methods like:
public int instertUserToDb()
{
...
}
public bool UserAllreadyExists()
{
...
}
public bool UpdateUserDatas()
{
...
}
Viewmodel不包含与数据库的任何连接?我需要创建一个ViewModel:NewUser,UpdateUser,UserDetails?
将所有内容(如插入,选择等)放入模型并将ViewModel用作视图的模板是否正确?有没有人知道互联网上的好例子?
非常感谢!
答案 0 :(得分:8)
不仅有意义,ViewModels是唯一应该在MVC中使用的。它们提供了许多好处,其中主要是静态类型和编译时间检查。 ViewData和ViewBag依赖于丑陋的字符串和动态属性名称,这些名称很难维护且容易出错。在asp.net MVC中,M代表ViewModel
s,而不是域模型。模型是业务,域实体,它封装了业务逻辑,旨在在域内工作。尽管使用了演示技术,模型保持不变,无论是Windows应用程序,Silverlight,ASP.NET MVC还是其他。相比之下,asp.net MVC中的ViewModels是专为在MVC框架内工作而设计的类,它们特定于控制器并查看特定数据,并允许更轻松地在域模型和控制器之间进行迭代。例如,在域(模型)中设计用户实体时
public class User
{
public string UserName { get; set; }
public string Password { get; set; }
}
为您的应用程序设计登录控制器时 - UserViewModel
public class UserViewModel
{
public string UserName { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
public string LoginHelpText { get; set; }
}
这不是现实生活中的例子,但在设计视图模型和设计领域模型时,您应该看到主要区别。如您所见,ViewModel是模式控制器和特定于操作的,并且包含用于更好的表示和用户迭代的数据,而域模型被设计为在域内工作而不关心表示 - 域模型不需要第二个ConfirmPassword字段例如。为了更好地将ViewModel用于域模型,您可以查看AutoMapper和其他社区工具。
ViewModels不应包含数据库的数据访问逻辑,也不应包含业务逻辑。在这种情况下,Models也不应包含对数据库的访问权限。为此,您应该创建存储库。
public interface IUserRepository
{
int Create(User user);
bool UserAlreadyExists(string userName);
bool UpdateUserDatas(User user);
}
//than the implementation
public class UserRepository
{
// Implementation of user repository.
}
//controller
public class UserController
{
IUserRepository _userRepository;
public UserController(IUserRepository userRepository)
{
_userRepository = userRepository ?? new UserRepository();// better to write this using Dependency Injection. Search google for Ninject, StructureMap, Unity, etc
}
public ActionResult Create(UserViewModel user)
{
if (ModelState.IsValid)
{
User domainUser = new User()
{
UserName = user.UserName // etc. written for simplicity, Use Automapper instead
};
_userRepository.Create(domainUser);// create user via repository
return RedirectToAction("Index");
}
return View(user);
}
}
阅读steven sanderson的书籍pro asp.net mvc 3了解详情
答案 1 :(得分:2)
模型是域对象。最佳实践是使用视图模型而不是域对象,因为有时表示逻辑与域模型不同。看到这个 When do I use View Models, Partials, Templates and handle child bindings with MVC 3
答案 2 :(得分:2)
让我们举一个关于博客应用的例子。这是您的博客模型;
public class Blog {
public int BlogID {get;set;}
public string Title {get;set;}
public DateTime PublishDate {get;set;}
public string Content {get;set;}
}
这是你的评论模型;
public class Comment {
public int CommentID {get;set;}
public int BlogID {get;set;}
public string CommentContent {get;set;}
public DateTime CommentDate {get;set;}
public bool IsApproved {get;set;}
}
以下是您的ViewModel;
public class BlogViewModel {
public Blog Blog {get;set;}
public IEnumerable<Comment> Comments {get;set;}
}
当您为 BlogViewModel 类创建一个strogly类型的视图时,您可以按如下方式使用您的视图;
@model MyApp.BlogViewModel
<h2>@Model.Blog.Title</h2>
<p>
@Model.Blog.Content
</p>
<div id="comments">
<ul>
@foreach(var item in Model.Comments) {
<li>@item.CommentContent</li>
}
</ul>
</div>
要使该视图健康,您的控制器需要将BlogViewModel对象传递给视图,如下所示;
public ActionResult Blog(int id) {
//this is just an example here.
//you need to put your logic here to get single Blog model
var blogModel = myBlogRepo.GetSingleBlog(id);
//this is just an example here.
//you need to put your logic here to get IQueryable<Comment> model
var commentsModel = myCommentRepo.GetAllCommnetsForBlog(id);
BlogViewModel model = new BlogViewModel();
model.Blog = blogModel;
model.Comments = commentsModel;
return View(model);
}
这种情况是使用ViewModel最合理的情况。希望它有所帮助。
答案 3 :(得分:0)
ViewModel允许您的视图处理所需数据的类型化表示。此外,如果视图需要特殊计算(例如聚合多个子元素),它可能会触发您在视图中看不到的一些事件,例如,如果object-grape是延迟加载的,则查询数据库等。 ..在Service / Controller / Whatever层中构建ViewModel可以避免这些问题
如果您发现ViewModel很难创建,我建议您使用Automapper之类的工具来帮助您将Model对象映射到ViewModel对象。
简而言之,是的,Asp.Net MVC和ViewModels携手并进:)
答案 4 :(得分:0)
在我看来,MVVM存在的真正原因是:在某些技术中使用ViewModel,例如WPF,它与模型的视图互操作性有限。由于ViewModel是作为中间体创建的,以使模型对View更友好。
例如:在Model中你有一个简单的变量,但是在View中(对于WPF视图在大多数情况下由XAML表示)你需要一个依赖属性。 ViewModel作业是将Model变量公开为依赖属性。
如果你有可能在Model和View之间绑定数据,那么ViewModel会失去它的用处。
答案 5 :(得分:0)
我通常有3层课程。首先是ApplicationName.Domain,它包含POCO对象。这些是ORM用于持久化它们的实体(通常在数据库中)。第二组类驻留在MVC应用程序模型文件夹中。这是使用控制器内的AutoMapper映射的。然后第三组类在MVC应用程序ViewModels文件夹中。最后一个用于将@model传递给视图。
解释结构。
但是,当需要将一些非常复杂的数据传递给视图时,会使用ViewModels类。按照上面的例子,我会使用UserViewModel,如下所示:
公共类UserViewModel { public UserModel User {get;组; } public IEnumerable {get;组; } public int? SelectedRoleId {get;组; } }
在控制器中编译视图模型。角色集合不是实际的POCO对象,而是模型,因为您可以使用
自动映射这些对象var roles = _roleService.GetAll();
AutoMapper.Mapper.Map<IEnumerable<Role>, IEnumerable<RoleModel>>(roles);
无论如何,简而言之,Models和ViewModels背后的想法是你可以构建你的整个应用程序,而不必担心持久性(对象存储),并在以后担心它。
答案 6 :(得分:0)
您使用与演示相关的内容装饰您的域对象。例如:分页和类别
ProductsListViewModel productsListViewModel = new ProductsListViewModel {
Products = _repository.GetAll(),
PagingInfo = new PagingInfo {
CurrentPage = page,
ItemsPerPage = PageSize,
TotalItems = _repository.GetAll().Count()
},
CurrentCategory = category
};
答案 7 :(得分:-1)
MVC中的M不代表查看模型,它代表模型。模型可以是一个ViewModel,但它也可能是一个域模型。
我所做的是我总是使用域模型,特别是对于简单的crud操作。然后,当需要额外的表示逻辑时,我将添加一个包含表示逻辑的ViewModel。恕我直言,这符合YAGNI原则。只需确保您的域模型不包含任何表示逻辑,并从中继续。