如何获得ModelState键/模型属性名称匹配?

问题描述

| 我有一个MVC3应用程序,正在使用EF4.1代码优先和POCO类。 我的问题涉及在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 />  
        //...
我的问题是: 如何避免使用硬编码的属性名称字符串\“ Expiry Date \”? 由于使用了viewmodel,因此期望ModelState键为\“ BusinessObject.ExpiryDate \”。我该如何匹配我的属性?如何添加前缀或删除自动添加的前缀? 注意,我当前使用validationResult.MemberNames.First())。 就我而言,我只希望在验证摘要显示一条消息,但是我想突出显示两个属性。也就是说,对于\“。validation-summary-errors \”仅显示一条消息,但在DOM中突出显示了\“。input-validation-error \”和\“。field-validation-error \”元素的两个字段。 谢谢,     

解决方法

属性中的硬编码属性名称可以不错,除了函数等之外。我建议您实现从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>