2011-05-19 106 views
3

我有一個MVC3應用程序,我使用EF4.1 Code First和POCO Classes。如何獲取ModelState鍵/模型屬性名稱以匹配?

我的問題涉及在我的POCO類中刪除硬編碼的「PropertyNames」,並且在ModelState中使用適當的值預固定它,以便驗證消息正確顯示。

我在我的POCO類中有一個看起來像這樣的方法。 您會注意到我也在使用「DataAnnotations.Validator」代碼來重新使用數據註釋驗證。

public class TaxCode : ModelBusinessObjectBase 
{ 
    //... 

    [Required] 
    [DataType(DataType.Date)] 
    [DisplayName("Effective Date")]   
    public DateTime EffectiveDate 
    { 
     get { return _effectiveDate; } 
     set { _effectiveDate = value; } 
    }  

    [Required] 
    [DataType(DataType.Date)] 
    [DisplayName("Expiry Date")]   
    public DateTime ExpiryDate 
    { 
     get { return _expiryDate; } 
     set { _expiryDate = value; } 
    }  

    //... 

    public override IEnumerable<ValidationResult> GetValidationResults() 
    { 
     //---- data annotation validation ---- 
     ValidationContext validationContext = new ValidationContext(this, null, null); 
     IList<ValidationResult> dataAnnotationValidationResults = new List<ValidationResult>(); 
     bool isValid = Validator.TryValidateObject(this, validationContext, dataAnnotationValidationResults, true); 


     foreach (ValidationResult dataAnnotationValidationResult in dataAnnotationValidationResults) 
      yield return new ValidationResult(dataAnnotationValidationResult.ErrorMessage, dataAnnotationValidationResult.MemberNames); 

     //---- custom business rule validation ---- 
     // expiry date must be greater than effective date 
     if (ExpiryDate <= EffectiveDate) 
     { 
      yield return new ValidationResult("Expiry Date must be after Effective Date", new [] {"EffectiveDate", "ExpiryDate"}); 
     } 

     yield break; 
    } 

在我的服務層,我最終會調用是這樣的:

public bool TryValidate(TaxCode domainObject) 
    { 
     if (!domainObject.IsValid) 
     { 
      _validationDictionary.AddValidationResults(domainObject.GetValidationResults()); 
      isValid = false; 
     } 
     return isValid; 
    } 

,並使用 「ModelStateWrapper」,代碼做到這一點:

public virtual void AddValidationResults(IEnumerable<ValidationResult> validationResults) 
    { 

     foreach (ValidationResult validationResult in validationResults) 
     { 
      _modelState.AddModelError(validationResult.MemberNames.First(), validationResult.ErrorMessage); 
     } 
    } 

我的視圖模型是這個:

public class TaxCodeViewModel : IPersistantBusinessObjectViewModel<TaxCode> 
{ 
    public TaxCodeViewModel() 
    { 
    } 

    public TaxCodeViewModel(TaxCode domainObj) 
    { 
     this.BusinessObject = domainObj; 
    } 
} 

和我的視圖看起來有點像這樣:

<%@ Control Language="C#" AutoEventWireup="true"    Inherits="System.Web.Mvc.ViewUserControl<TaxCodeViewModel>" %> 

    //... 

    <% using (Html.BeginForm()) {%> 

     <%:Html.ValidationSummary(false, "Unable to save. Please correct the errors and try again.")%> 


     //... 

     <div class="editor-label"> 
      <%:Html.LabelFor(model => model.BusinessObject.EffectiveDate)%> 
     </div> 
     <div class="editor-field"> 
      <%: Html.EditorFor(model => model.BusinessObject.EffectiveDate)%> 
      <%: Html.ValidationMessageFor(model => model.BusinessObject.EffectiveDate)%> 
     </div> 
     <br /> 
     <div class="editor-label"> 
      <%: Html.LabelFor(model => model.BusinessObject.ExpiryDate)%> 
     </div> 
     <div class="editor-field"> 
      <%: Html.EditorFor(model => model.BusinessObject.ExpiryDate)%> 
      <%: Html.ValidationMessageFor(model => model.BusinessObject.ExpiryDate)%> 
     </div> 
     <br /> 
     //... 

我的問題是:

  1. 如何避免硬編碼的屬性名稱字符串「到期日」?

  2. 由於ViewModel,期望ModelState鍵爲「BusinessObject.ExpiryDate」。我如何讓我的房產匹配?如何添加前綴或刪除自動添加的前綴?

  3. 注意我目前使用validationResult.MemberNames.First())。 就我而言,我只想在驗證摘要中輸入一條消息,但我希望突出顯示這兩個屬性。即對於「.validation-summary-errors」只有一個消息,但是爲DOM中的「.input-validation-error」和「.field-validation-error」元素突出顯示了這兩個字段。

謝謝你,在屬性

回答

0

硬編碼的屬性名稱不壞,除了功能,etc.I建議您實現從CompareAttribute繼承新的類,所以大部分上面的代碼將消失,您的硬盤編碼依賴問題將得到解決。

爲了突出顯示問題,您可以使用java腳本,或實現一些有用的函數來檢查模型是否在某些字段上有錯誤並返回一些css類名稱。就像休閒一樣。

<div class="editor-field <%: Html.HasValidationMessage(model => model.BusinessObject.ExpiryDate)%>"> 
      <%: Html.EditorFor(model => model.BusinessObject.ExpiryDate)%> 
      <%: Html.ValidationMessageFor(model => model.BusinessObject.ExpiryDate)%> 
</div> 
+0

感謝您的信息...我喜歡突出顯示的解決方案。我將不得不看看「CompareAttribute」,看看我能否得到這個工作。 – Raymond 2011-07-07 17:08:32

+0

我可以建議不同的解決方案來突出顯示,因爲我的驗證是在服務器端使用ajax調用執行的,所返回的JSON結果包含有關無效HTML元素和驗證消息的信息。我可以設置突出顯示使用jQuery。 – 2011-07-07 19:12:09