2011-01-10 98 views
15

使用此方法查看MVC中的模型:http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/06/29/how-we-do-mvc-view-models.aspx如何保持DRY驗證?

在我的腦海中留下了一個未解答的問題。所以現在是時候讓它清理了。

如果我使用自動映射器將域屬性映射到dto,那麼我明白當dto映射到保存的域實體時,我的域層可以返回一組驗證規則。

但是,我沒有看到DRY獲取客戶端驗證的方式,並將錯誤添加到模型狀態,以便它們對應於視圖模型上的正確屬性。

乾杯

+1

好點。我在最後幾個問題上這樣做是爲了嘗試和解決這個問題。 – nick 2011-01-10 11:54:32

回答

11

,我發現了一些有趣的反應一個相關的問題:我一直在思考這個

Mapping Validation Attributes From Domain Entity to DTO

,並在某種程度上,它是類似的情況,我們有服務器端和客戶端驗證。 (例如,使用NHibernate Validator和jQuery.validate)。

現在人們普遍認爲應該有一套完整的服務器端驗證,並且添加客戶端驗證是您可以選擇的選項,以便使您的應用程序更加用戶友好。它曾經是你必須手動實現你的客戶端驗證,但是由於可用性的好處,你接受了重複工作。

我認爲我們在這裏處理的內容非常相似。您的應該已在您的域圖層中進行驗證。您不能依賴消費應用程序來始終自行添加驗證。

然後,您可以在應用程序中爲DTO /視圖模型添加驗證選項。您這樣做是因爲它更有助於處理視圖中的驗證錯誤,而不是讓它們通過可能引發異常或提供不太有用的錯誤消息的域。問題是,從領域的角度來看,你並不依賴於這一點。您仍然對自己的系統充滿信心,因爲您知道是否有任何不良數據能夠通過,您的模型會抓住它。

現在客戶機/服務器的情況是一個非問題,因爲已經做了很多工作來自動化它,從服務器端代碼生成客戶端代碼(例如,ASP.Net MVC中的ModelValidatorProvider)。我相信隨着越來越多的人開始使用視圖模型/ DTO,我們將開始看到類似的解決方案,將域驗證自動映射到DTO上(it's already happening with AutoMapper)。因此,在短期

,我(務實而不是理想;))的回答是:

接受違反DRY的現在,在這兩個地方做驗證,並嘗試有助於實現這一目標將其自動化項目在將來

2

一種常見的方法是把所有的驗證您的視圖模型,通常是通過使用數據的註釋。 MVC允許您從數據註釋中自動生成客戶端(javascript)驗證。漂亮幹。

您控制器發佈的操作將採用viewmodel並檢查IsValid屬性。這樣一來,你在客戶端和服務器使用相同的代碼驗證(或應該,我說在數據註解的情況下屬性):剛通過使控制器操作發生在

[HttpPost] 
public ActionResult ResetPassword(ResetPasswordViewModel viewModel) 
{ 
    if (ModelState.IsValid) 
    { 
    // convert to dto/entity and pass to next layer 
    // redirect to success page 
    return RedirectToAction("ResetPasswordSuccess"); 
    } 
    // display original view which will display error messages 
    return View(); 
} 

我想補充的是viewModel作爲參數,默認的MVC模型綁定器會自動驗證您的視圖模型,並將任何錯誤添加到ModelState錯誤集合中,用於在視圖中顯示錯誤。

+2

對我來說,要麼不幹,因爲我必須在模型和虛擬機上進行驗證 - 否則它不允許我在模型中執行我的業務規則,因爲我只向虛擬機添加驗證。 – nick 2011-01-10 14:51:54

+0

我想你基本上是說你做出了設計決定,你的域只會被你的web應用程序佔用,並且你的web應用程序的開發者應該總是使用視圖模型而不是域實體來執行CRUD操作? – 2011-01-11 10:18:46

+0

即,您接受域模型是可惡的數據,因爲您知道您的開發人員不會以這種方式使用它嗎? – 2011-01-11 10:23:46

5

我更喜歡將Model作爲ViewModel的屬性以及其他特定於視圖的字段。這樣它就可以在綁定期間通過MVC驗證,並且我可以在不通過MVC綁定時在後端驗證它。通過這種方式,客戶端驗證由MVC提供,我得到的清潔模型的驗證對象不直接綁定到視圖。

public class MyViewModel 
{ 
    public MyModel MyModel {get;set;} 
    public bool IsSomethingAllowed {get;set;} 
} 

public class MyModel 
{ 
    public int Id {get;set;} 
    [Required] 
    public string Name {get;set;} 
}