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

发布于 2024-10-13 04:57:19 字数 846 浏览 8 评论 0原文

我在 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”。

问题是什么?

I created an inherited attribute like this in ASP.NET MVC3:

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

And use it like this:

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

It didn't work and the MVC ignored it. Then I create a simpler class which just inherited from RequiredAttribute like this:

public class MyRequiredAttribute : RequiredAttribute
{
}

I use it like that I said. But it didn't work again.

Although, all these ways work on "DisplayNameAtrribute" perfectly.

What is the problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

苄①跕圉湢 2024-10-20 04:57:19

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

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);
    }

You can fix this by adding the following code in Global.asax: (found the answer here)

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

Alternatively, using marcind's solution, I found that the constructor for ModelClientValidationRequiredRule requires an error message. Here is an updated version that includes the display name for the field:

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        string msg = FormatErrorMessage(metadata.GetDisplayName());
        yield return new ModelClientValidationRequiredRule(msg);
    }
池予 2024-10-20 04:57:19

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

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

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

It's only client-side validation that does not work with inherited attributes. The reason for that is that MVC uses strict type equality when mapping server-side attributes to client validation behaviors.

To work around this you will need your custom attribute to implement IClientValidatable:

public class MyRequiredAttribute : IClientValidatable {
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) {
         yield return new ModelClientValidationRequiredRule();
    }
}
合约呢 2024-10-20 04:57:19

基于上述内容,LocalizedRequiredAttribute 的完整属性使用 Resource.ValueRequired 的默认资源字符串,该字符串在我的资源中定义为
“{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);
    }
}

Building on the above, the complete attribute for LocalizedRequiredAttribute using a default resource string of Resource.ValueRequired which is defined in my resources as
"The {0} field is required."

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文