从ASP.NET MVC 3中的RequiredAttribute加入时,客户端验证不起作用?

时间:2011-01-20 16:21:43

标签: asp.net-mvc asp.net-mvc-3 data-annotations

我在ASP.NET MVC3中创建了一个这样的继承属性:

public sealed class RequiredFromResourceAttribute : RequiredAttribute
{
    public RequiredFromResourceAttribute(string errorResourceName, string errorResourceTypeName)
    {
        this.ErrorMessageResourceName = errorResourceName;
        this.ErrorMessageResourceType = Type.GetType(errorResourceTypeName);
    }
}

并像这样使用它:

[RequiredFromResource("Title", "Resources.Resource, MyProject.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")]
public string Title { get; set; }

它不起作用,MVC忽略了它。然后我创建一个更简单的类,它继承自RequiredAttribute,如下所示:

public class MyRequiredAttribute : RequiredAttribute
{
}

我就像我说的那样使用它。但它没有再起作用。

尽管如此,所有这些方式都完美地适用于“DisplayNameAtrribute”。

有什么问题?

3 个答案:

答案 0 :(得分:3)

这只是客户端验证,不适用于继承的属性。原因是当将服务器端属性映射到客户端验证行为时,MVC使用严格类型相等。

要解决此问题,您需要使用自定义属性来实现IClientValidatable

public class MyRequiredAttribute : IClientValidatable {
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) {
         yield return new ModelClientValidationRequiredRule();
    }
}

答案 1 :(得分:3)

您可以通过在Global.asax中添加以下代码来解决此问题:(找到答案here

DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredLocalizableAttribute), typeof(RequiredAttributeAdapter));

或者,使用marcind的解决方案,我发现ModelClientValidationRequiredRule的构造函数需要一条错误消息。这是一个更新版本,其中包含该字段的显示名称:

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        string msg = FormatErrorMessage(metadata.GetDisplayName());
        yield return new ModelClientValidationRequiredRule(msg);
    }

答案 2 :(得分:0)

在上面的基础上,使用默认资源字符串Resource.ValueRequired定义了LocalizedRequiredAttribute的完整属性,该字符串在我的资源中定义为 “ {0}字段为必填。”

public class LocalizedRequiredAttribute : RequiredAttribute, IClientValidatable 
{
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var msg = new ResourceManager(ErrorMessageResourceType).GetString(ErrorMessageResourceName);
        yield return new ModelClientValidationRequiredRule(string.Format(msg, metadata.DisplayName));
    }

    public LocalizedRequiredAttribute(string errorResourceName = null, string errorResourceTypeName = null)
    {
        this.ErrorMessageResourceName = string.IsNullOrEmpty(errorResourceName) ? nameof(Resource.ValueRequired) : errorResourceName;
        this.ErrorMessageResourceType = string.IsNullOrEmpty(errorResourceTypeName) ? typeof(Resource) : Type.GetType(errorResourceTypeName);
    }
}