2011-07-13 38 views
2

我想在MVC3編程我自己。在查看示例應用程序的過程中,我經常看到諸如ViewModel之外的其他模型,視圖和控制器。是否有意義使用ViewModel

我的問題:使用它們有意義嗎?如果是的話:Model和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() 
{ 
... 
} 

視圖模型不包含對DATABSE有聯繫嗎?我需要創建一個ViewModel:NewUser,UpdateUser,UserDetails?

將插入,選擇等所有東西放入模型並將視圖模型用作視圖的模板就是正確的嗎?有沒有人知道互聯網的一個很好的例子?

非常感謝!

+0

的可能的複製[爲什麼要使用的ViewModels?](https://stackoverflow.com/questions/14423056/why-do-we-use-viewmodels) – Liam

回答

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; } 
} 

這不是現實生活中的例子,但你應該看到主設計視圖模型與設計領域模型時的差異。正如你所看到的,ViewModels是模式控制器和操作特定的,並且包含用於更好的表示和用戶迭代的數據,而域模型被設計爲在域內工作並且不關心表示 - 域模型不需要例如第二ConfirmPassword字段。爲了更好地將ViewModel與域模型一起使用,您可以查看AutoMapper和其他社區工具。

ViewModels不應包含數據庫的數據訪問邏輯,也不應包含業務邏輯。在情況下,模型也不應該包含對數據庫的訪問。爲此,您應該創建存儲庫。

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); 
    } 
} 

讀史蒂芬·桑德森的書親asp.net的MVC 3的全部細節

+0

謝謝,我我更新了我的問題。 Perhabs你看看它,檢查我是否理解正確。 – HW90

+0

查看我的更新回答 – archil

+0

您確定要使用Automapper從UserViewModel自動創建用戶? accorfgin to jimmy bogard「我不能爲了我的生活理解爲什麼我想將DTO直接倒入模型對象。」http://lostechies.com/jimmybogard/2009/09/18/the -case-for-two-way-mapping-in-automapper/....這是仍然混淆了我aboiut automapper ...它似乎並不意味着這個 – ignaciofuentes

0

一個ViewModel允許你的視圖工作在它需要的數據的類型表示。此外,如果視圖需要特殊計算(例如聚合大量子元素),它可能會觸發一些您不希望在視圖中看到的事件,例如查詢數據庫,如果對象葡萄是懶惰加載的等等。 ..在服務/控制器/任何層建立一個ViewModel允許你避免這些問題

如果你發現ViewModels麻煩創建,我建議使用一些工具,如Automapper來幫助你映射模型對象到ViewModel對象。

因此,在短期,是的,Asp.Net MVC和的ViewModels沿着手攜手:)

-1

MVC中的M不主張查看型號,它代表的模型。模型可以是是一個ViewModel,但它也可能是一個域模型。

我所做的是我總是使用域模型,特別是對於簡單的crud操作。然後,當需要額外的表示邏輯時,我將添加一個包含表示邏輯的ViewModel。恕我直言,這遵守YAGNI原則。只要確保你的域模型不包含任何表示邏輯,並從中去。

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;} 
    } 

當你創建一個strogly類型的視圖來BlogViewModel類,你可以用你的觀點如下:

@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最合理的情況。希望它有幫助。

+1

爲什麼IQueryable如果你正在做一個GetAllComments? –

+0

@Bart thx!改變:) – tugberk

0

在我看來,爲什麼MVVM存在的真正原因是:ViewModel需要在像WPF這樣的一些技術中使用,這些技術與Model具有有限的View互操作性。由於該ViewModel被創建爲一箇中間體,以便使該模型對視圖更友好。

作爲示例:在模型中,您有一個簡單的變量,但在視圖中(對於WPF視圖在大多數情況下由XAML表示),您需要一個依賴項屬性。 ViewModel作業是將Model變量作爲依賴項屬性公開。

如果您有可能將數據綁定到模型和視圖之間,ViewModel將失去它的實用性。

0

我通常有3層類。首先是保存POCO對象的ApplicationName.Domain。這些是ORM用來堅持它們的實體(通常在數據庫中)。第二組類位於MVC應用程序Models文件夾中。這是使用控制器內的AutoMapper映射的。然後,第三組類位於MVC應用程序ViewModels文件夾中。這些最後一個用於將@model傳遞給視圖。

解釋結構。

  • POCO對象不應該知道關於表示的任何內容。他們應該知道數據規則。我使用RequiredAttribute或StringLengthAttribute等屬性來裝飾POCO對象。
  • MVC應用程序中的模型應該知道每個屬性的顯示方式。我自動映射來自POCO類的模型,並使用DisplayAttribute等類似屬性對它們進行裝飾。
  • 因爲用戶界面也需要了解驗證,以便顯示驗證錯誤,您必須在POCO和模型之間共享數據規則屬性。你可以通過使用Meta類來做到這一點。因此,例如,POCO類User和Model類UserModel都共享一個MetaClass屬性,並鏈接到UserMetaData。這是你可以爲MVC應用程序和數據庫層驗證實現完全相同的規則。
  • 但是,當需要將一些非常複雜的數據傳遞給視圖時,會使用ViewModels類。根據上面的例子,我會擁有UserViewModel,如下所示:

    public class UserViewModel {User:UserModel User {get;組; } public IEnumerable {get;組; } public int? SelectedRoleId {get;組; } }

在控制器內編譯視圖模型。角色的集合是不實際的POCO的對象,而是模型,因爲你可以使用

var roles = _roleService.GetAll(); 
AutoMapper.Mapper.Map<IEnumerable<Role>, IEnumerable<RoleModel>>(roles); 

不管怎樣,總之自動映射的,模型和的ViewModels背後的想法是,你可以在無需擔心持續構建一個完整的應用程序(對象存儲)並在後面擔心。

0

你裝飾你的域對象與演示相關的東西。例如:尋呼和類別

ProductsListViewModel productsListViewModel = new ProductsListViewModel { 
     Products = _repository.GetAll(), 
     PagingInfo = new PagingInfo { 
      CurrentPage = page, 
      ItemsPerPage = PageSize, 
      TotalItems = _repository.GetAll().Count() 
     }, 
     CurrentCategory = category 
    }; 
相關問題