2013-01-23 60 views
0

環境:
我使用MVC4,剃刀2和FluentValidation.MVC4(3.4.6.0)。傳播孩子錯誤的父在FluentValidation

場景:
我有一個特定的網頁,其中也有它的子視圖模型如下一個複雜的視圖模型:

public class ProfileViewModel 
{ 
    public string FirstName {get; set;} 
    public PhoneNumberViewModel Primary {get; set;} 
    // ... other stuff ... // 
} 

public class PhoneNumberViewModel 
{ 
    public string AreaCode { get; set; } 
    public string Exchange { get; set; } 
    public string Suffix { get; set; } 
    public string Extension { get; set; } 
} 

此配置文件可以編輯和調回進行更新。我已經創建了兩個Fluent驗證器,如下所示:

public class ProfileViewModelValidator : AbstractValidator<ProfileViewModel> 
{ 
    public ProfileViewModelValidator() 
    { 
     RuleFor(m => m.FirstName).NotEmpty().WithMessage("Please enter a First Name,"); 
     RuleFor(m => m.Primary).SetValidator(new PhoneNumberViewModelValidator()).WithMessage("Hello StackOverflow!"); 
     // ... other validation ... // 
    } 
} 

public class PhoneNumberViewModelValidator : AbstractValidator<PhoneNumberViewModel> 
{ 
    public PhoneNumberViewModelValidator() 
    { 
     RuleFor(m => m.AreaCode).NotEmpty(); 
    }  
} 

然後,當然,我有意見來顯示一切。

資料查看片段:

... 
@Html.TextBoxFor(m => m.FirstName) 
@Html.EditorFor(m => m.PrimaryPhoneNumber) 
... 

電話號碼編輯模板段:

... 
@Html.ValidationLabelFor(m => m, "Primary Phone:") 
@Html.TextBoxFor(m => m.AreaCode) 
@Html.TextBoxFor(m => m.Exchange) 
@Html.TextBoxFor(m => m.Suffix) 
@Html.TextBoxFor(m => m.Extension) 
@Html.ValidationMessageFor(m => m) 
... 

如果是相關的,我有事情設置以便它自動線了驗證與各種對象。實際上我甚至不需要上面的.SetValidator() ......無論如何因爲連線都可以驗證一切。

目的:
如果我不輸入名字,我得到了由ValidationMessageFor創建的區域上方提供的錯誤信息。但是,如果子PhoneNumberViewModel的任何元素未通過驗證,我什麼也得不到。文本框突出顯示紅色,這太棒了,但我沒有收到我在.WithMessage()中提供的消息,表明我的孩子屬性無效。

目前我通過在我的控制器中額外的工作來實現它......它在子對象上查找錯誤,然後向父對象添加錯誤。這種方法聞起來真的很糟糕。它將驗證相關的問題放在控制器中,我只是不想讓它們在那裏。更何況,它最終還是有大量的字符串索引來挖掘模型狀態,而且這只是......粗暴。

有沒有簡單的方法來定義ProfileViewModelValidator的驗證規則,如果孩子未能驗證,會爲ProfileViewModel添加錯誤?和/或它應該工作,但我做錯了什麼?我已經搜索和搜索,但我找不到滿意的解決方案。

謝謝你的時間!

回答

0

我發現了一個與我的問題中包含的臭味不同的解決方案。這也不是很理想,但我認爲我更喜歡上面提供的解決方案。也許別人會同意,所以它可能是有用的,直到一個更清晰的答案出現。

我添加了一個屬性,返回整個電話號碼作爲格式化字符串PhoneNumberViewModel

public string FullNumber 
{ 
    get { return string.Format("{0}{1}{2}{3}", AreaCode, Exchange, Suffix, Extension); } 
} 

然後就可以在另外申請驗證規則此屬性,以你的規則對每個組件屬性。如果您只將.WithMessage()應用於FullNumber屬性,則最終將得到您期望的驗證消息(並且只會出現一次),並且如果出現故障,則會爲每個單獨的框高亮顯示文本框。

這種方法的主要缺點是最終會重複您的驗證規則。您分別驗證每個組件,然後必須驗證組合的屬性,這也基本上是您已完成驗證的組合。您將代碼翻倍,並將處理量加倍。你也會增加一倍可能出錯的地方。

在我的情況下,我使用正則表達式,所以它不是太糟糕...我更喜歡它將錯誤傳播代碼嵌入到控制器中。但它仍然不理想 - 希望有更好的解決方案出現。

+0

我已經等了一個星期才接受我自己的不理想的解決方案。最終,我懷疑最好的解決方案是取消自動驗證連線,並始終手動設置驗證。可悲的是,這不是我的選擇。 – Mir

相關問題