asp.net-mvc - 如何让 ModelState 键/模型属性名称匹配?

标签 asp.net-mvc validation data-annotations

我有一个 MVC3 应用程序,我正在使用 EF4.1 Code First 和 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);
        }
    }

我的 View 模型是这样的:

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

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

我的 View 看起来有点像这样:

   <%@ 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. 如何避免硬编码的属性名称字符串“Expiry Date”?

  2. 由于 ViewModel,期望 ModelState 键为“BusinessObject.ExpiryDate”。我如何让我的属性匹配?如何添加前缀或删除自动添加的前缀?

  3. 请注意,我目前使用 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>

关于asp.net-mvc - 如何让 ModelState 键/模型属性名称匹配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6065874/

相关文章:

asp.net-mvc - 更改 ASP.NET MVC 默认文件夹结构

asp.net-mvc - MvcBuildViews true 导致 "'/temp' is not a valid IIS application"错误

algorithm - 验证美国社会安全号码 (SSN) 的新规则

javascript - 如何向这个验证函数添加一个字符?

asp.net-mvc-3 - 无法在 MVC3 HTML Helper 中获取自定义属性值

c# - MVC3通过ModelState添加和显示消息

asp.net-mvc - 将多个项目解决方案部署到azure

asp.net-mvc - 带参数的 ASP.NET MVC 3 客户端验证

c# - 将数据注释应用于 MVC 中 View 模型的子属性?

asp.net-mvc - MVC 数据安全