2011-05-18 43 views
6

使用ASP.NET MVC,我有一個模型,我附加的屬性,以便我可以使用MVC模型綁定驗證,但到這不會違反MVC的規則,你在哪裏放屬於視圖的項目放入模型中?我希望自己不要過於聰明,但我對其他人的看法感到好奇。ASP.NET MVC模型驗證打破了MVC規則?

public class Payments 
{ 
    [DataType(DataType.Text)] 
    [DisplayFormat(NullDisplayText="")] 
    [Display(Name="Payment Id")] 
    [Required(ErrorMessage="Required")] 
    public int PaymentId { get; set; } //todo: make this into a dropdown 

    [DataType(DataType.Text)] 
    [Display(Name="Bill Name")] 
    [Required(ErrorMessage = "Required")] 
    public string PaymentName { get; set; } 

    [DataType(DataType.Date)] 
    [Display(Name="Date to Post Payment")] 
    [Required(ErrorMessage = "Required")] 
    public DateTime PaymentDate { get; set; } 

    [DataType(DataType.Currency)] 
    [Range(0, 922337203685477.5807)] 
    [Required(ErrorMessage = "Required")] 
    public double PaymentAmount { get; set; } 
} 

回答

10

是。這就是爲什麼你應該使用ViewModels。

+0

我不明白在MVC上下文中的單詞「ViewModel」。我理解「MVC」來模擬模型視圖控制器。我理解「MVVM」代表Model-View-ViewModel。所以,如果我們談論MVC,那麼ViewModel爲什麼被討論? – 2014-03-05 18:10:09

+0

是的,這個答案是不正確的,也違反了MVC ...... Model!= Entity – 2014-03-05 18:23:09

+0

它的重要性在於裁縫對技術堆棧背景的回答和討論。模型和ViewModels在討論ASP.NET MVC時意味着什麼,但在閱讀Martin Fowler時不是。 MVC的最初概念幾乎與幾乎所有語言在網絡上使用的實際實現完全不同。 – jfar 2014-03-05 19:26:00

10

您可以但不必將這些驗證屬性放入模型中。

但最好使用視圖模型:

代替
public class PaymentsViewModel 
{ 
    [DataType(DataType.Text)] 
    [DisplayFormat(NullDisplayText="")] 
    [Display(Name="Payment Id")] 
    [Required(ErrorMessage="Required")] 
    public int PaymentId { get; set; } //todo: make this into a dropdown 

    [DataType(DataType.Text)] 
    [Display(Name="Bill Name")] 
    [Required(ErrorMessage = "Required")] 
    public string PaymentName { get; set; } 

    [DataType(DataType.Date)] 
    [Display(Name="Date to Post Payment")] 
    [Required(ErrorMessage = "Required")] 
    public DateTime PaymentDate { get; set; } 

    [DataType(DataType.Currency)] 
    [Range(0, 922337203685477.5807)] 
    [Required(ErrorMessage = "Required")] 
    public double PaymentAmount { get; set; } 
} 

而且在你看來,:

@model YourProject.Models.Payments 

你使用:

@model YourProject.Models.PaymentsViewModel 

進行驗證。

+0

放置ViewModel類的最佳位置在哪裏?假設你有兩個解決方案:MyProject.UI和MyProject.Models,Payment類是MyProjects.Models.Payment。將ViewModel放入MyProject.UI.Models.PaymentViewModel或MyProject.Models.PaymentViewModel會更好嗎? – 2011-05-18 20:22:36

+1

@WeekendWarrior:實際上把它放在哪裏並不重要。我喜歡製作2個文件夾:Models和ViewModels並將它們放在那裏。 – Matthias 2011-05-18 21:31:34

+0

你的模型會是什麼樣子?這裏似乎更像語義論證,儘管公認是一個簡單的例子。 – nicodemus13 2011-05-26 09:05:40

1

它是否違反嚴格意義上的MVC,是的,可能。有沒有什麼時候違反這個規定?當然。但是,有一些機制可以幫助你解決問題,並將問題分開。

您可以在視圖中使用持久化域對象並對它們進行驗證,但是當視圖開始變得複雜時,ViewModels成爲必需。對於死者簡單的域模型或僅查看視圖(不編輯/創建),我有時會做傻事了一下,並將它們發送到視圖作爲複合對象的一部分:

class MyViewModel 
{ 
    public MyDomainModel DomainObj; 
    public int OtherViewInfo; 
} 

然而,創建和編輯情景,ViewModels好得多。它們允許您完全控制發送到視圖的數據並從視圖中獲取

如果您使用的是EF 4.1和CodeFirst,那麼您會最終在域和ViewModel之間重複一些屬性和屬性。這是不可避免的,但可以讓您靈活地對視圖進行特定的不同驗證。

我發現它是有用的保護的一個額外層控制器實際保存的情況下,域對象時,我錯過了在視圖中的某些驗證:

public class MyController : Controller 
{ 
    [HttpPost] 
    public ActionResult Edit(int id, MyViewModel model) 
    { 
     try 
     { 
      ...Do stuff, check ModelState.IsValid... 
      _context.SaveChanges() 
     } 
     catch (DbEntityValidationException dbEx) 
     { 
      // Catch any validation errors on the domain that weren't duplicated 
      // in the viewmodel 
      ModelState.AddModelError("Form", dbEx); 
     } 

     return View(model); 
    } 
} 

下一個要問的問題就是如何您可以在域模型和ViewModel之間進行映射。有一些策略和工具 - AutoMapperValueInjecter(是的,拼寫錯誤)。就我個人而言,我一直在使用ValueInjecter,儘管如果你設置了一個映射層,你可以嘗試兩者。我發現這兩種方法都不能在100%的情況下工作,或者至少我能弄清楚如何做我需要的東西,但是地圖服務可以很容易地定義自定義的從左到右的地圖。