2011-03-08 43 views
2

我剛剛閱讀了關於MVC3的新的CompareAttribute,你可以應用到模型的屬性來定義它應該匹配的另一個屬性 - 經典用例確認電子郵件地址已被正確輸入,或者有一個密碼和ConfirmPassword字段。我遇到了一個問題,試圖在我自己的項目中實現它。CompareAttribute和比較一個複雜類型的屬性

我們已經有了一個相當標準的用戶對象,除其他事項外,具有以下屬性:

public class User { 
    .... 
    [Required, RegularExpression(RegularExpressions.Email, ErrorMessage = "Please supply a valid email address")] 
    public string EmailAddress 

    [Required] 
    public string Password 
    .... 
} 

我再結合用戶和一對夫婦,我們需要到一個視圖模型等對象:

public class SignUpViewModel { 
    .... 
    public User user { get; set; } 
    .... 
} 

其中,傳遞到用戶界面中的形式的情況下,允許向ModelBinder的當用戶提交表單運行SignUpViewModel爲User對象的數據註釋驗證以及其它目的和原始類型。當這一切都「剛剛起作用」時,我感到非常高興,因爲這意味着我們可以在一個地方定義驗證,並且不需要太多的工作來堅持數據庫或將UI模型映射到域模型等。

注意到的是,Html.EditorFor(型號=> model.User.Password)發射一個與設置爲「user.password的」這個名字,添加以下到SignUpViewModel:

[Required, Compare("User.Password")] 
public string ConfirmPassword { get; set; } 

但提交表單現在觸發驗證錯誤沿着「無法找到名爲User.Password的屬性」行。我希望它會遵循相同的慣例,但它不會顯示:(

我真的不想將ConfirmPassword放入用戶對象中,因爲ConfirmPassword純粹是一個UI關注,並且它似乎是錯誤的在這樣的領域對象中,我也不想將SignUpViewModel中的各種對象展平,因爲它開始感覺像重複定義驗證規則的地方,而且我們試圖將我們的代碼保持爲DRY可能的。

有沒有人碰到一種方式來獲得CompareAttribute與對同胞的性能比較對象,而不是同級性質的工作,因爲它會出現在屬性期望?

回答

2

刪除SignUpViewModel上的User屬性,並將User域對象的必要屬性放在SignUpViewModel上。

你說你希望分離你的擔憂,並將視圖模型中的域對象作爲屬性,這是一個不讓你的擔憂分開的例子。

這看起來似乎可能會導致您編寫更多代碼,但請查看諸如Automapper之類的解決方案以自動將域對象屬性映射爲查看模型屬性。

+0

感謝您給我的建築清晰度 - 您絕對正確的是,我通過將域對象通過ViewModel傳遞給窗體來混合關注點。 – jonsidnell

1

儘管從架構的角度來看,smartcaveman的響應非常好,但它並未解決無法在某些父模型(複雜模型)中包含的模型中利用MVC3中CompareAttribute的客戶端驗證的原始問題。我知道一些情況,可以從幾個父容器模型中重用一些可重用的[sub]模型,並且在子模型中使用CompareAttribute。 MVC3中的服務器端驗證可以正常工作(當客戶端禁用javascript時),但是Microsoft提供的JavaScript中存在一箇中斷客戶端驗證的錯誤。請按照下面的鏈接,該決議:

MVC3 CompareAttribute Client-side Bug (stackoverflow)

0

我最近就遇到了這個問題,我自己;這是我如何解決它。

[Compare("OriginalPassword")] 
public string ConfirmPassword { get; set; } 

public string OriginalPassword 
{ 
    get 
    { 
     return User.Password; 
    } 
}