验证消息中的自定义元数据

时间:2011-08-05 16:01:38

标签: asp.net-mvc validation asp.net-mvc-2

我实现了一个扩展AssociatedMetaDataProvider的自定义元数据提供程序。该课程的最初目的是获取一个属性名称并将其转换为Pascal套接字。

我有新要求为网站中所有必填字段的标签添加可视指示符('*'字符)。我可以通过将以下代码添加到自定义元数据提供程序来进行此更改:

        PropertyInfo property = containerType.GetProperty(propertyName);
        if (property.GetCustomAttributes(typeof(RequiredAttribute), true).Any())
            metadata.DisplayName = "* " + metadata.DisplayName;

此代码“有效”,因为它为所有标签添加了'*'字符。但是,它还有一个副作用,即在所有验证消息中添加'*'字符(例如Html.ValidationMessageFor(x => x.FirstName)使用的那些。在这种情况下,我希望标签为'* First Name'并且错误消息为'The First Name字段是必需的。'而不是'The * First Name字段是必需的。'。

有没有办法提供添加'*'字符作为标签元数据的一部分,而不会影响验证消息中使用的属性名称?或者,有没有办法在构建验证消息时提供自定义元数据?

3 个答案:

答案 0 :(得分:1)

在花了一些时间思考这个问题之后,我设法找到了似乎有用的东西。然而,我并不喜欢这个解决方案:

        foreach (ValidationAttribute validationAttribute in attributes.Where(x => x is ValidationAttribute))
        {
            if (String.IsNullOrEmpty(validationAttribute.ErrorMessage))
            {
                validationAttribute.ErrorMessage = validationAttribute.FormatErrorMessage(formattedPropertyName);
            }
        }

此代码与问题中的代码同时运行(作为自定义元数据提供程序中CreateMetadata方法的一部分)。它适用于我测试过的所有情况,但它并没有真正向验证提供程序提供元数据,而是使用Pascal套件版本的属性名称格式化错误字符串。这适用于大多数正常验证消息的设置方式。它在验证属性上显式设置错误消息这一事实似乎不正确。

然而,我不知道这可以作为全球解决方案。这个解决方案“有效”,但我希望有更好的解决方案。

答案 1 :(得分:0)

我现在在手机上,所以没有反射器或IDE的好处,但是我不认为你可以在不改变验证器的情况下做到这一点,因为他们的行为是使用错误消息的格式字符串,传入您在此处修改的相同显示名称。我可能错了(我喜欢你的方法)。

然而,我已经完成了你所做的事情,通过编写自定义编辑器模板,这也将html的控制权交给了Web开发人员。使用元数据方法,您可以将星号(例如,它自己的类)用于着色目的。

使用模板更好,如果使用剃刀,您可以使用布局模板,以便所有字段类型都可以使用标准的标签/输入方法。

使用Html.LabelFor,如果需要当前模型,则后跟可选块提供了我认为的很大的灵活性,我宁愿通过元数据解决方案,因为它也不会干扰验证消息。

就像我说的那样,在我最初的怀疑中,我可能是错的:)

答案 2 :(得分:0)

我知道这是一个7年的问题,但我已经遇到了同样的问题一段时间,在我看来,这里提供的解决方案不起作用。

嗯,它有效但我所翻译的所有信息都将消失。

以下是我为ASP.NET MVC Core 2所做的工作:

public class CustomDisplayMetadataProvider : IDisplayMetadataProvider
{
    public void CreateDisplayMetadata(DisplayMetadataProviderContext context)
    {
        if(context.Attributes.OfType<RequiredAttribute>().FirstOrDefault()?.GetType() == typeof(RequiredAttribute))
        {
            var displayName = context.Attributes.OfType<DisplayNameAttribute>().FirstOrDefault()?.DisplayName ?? context.Key.Name;
            context.DisplayMetadata.DisplayName = () =>
            {
                if(new System.Diagnostics.StackTrace(0).GetFrames().Any(f => f.GetMethod().Name == "Validate"))
                {
                    return displayName;
                }
                else
                {
                    return displayName + " *";
                }
            };
        }
    }
}

我们的想法是验证DisplayName是否通过Validate方法调用,这样我们就不会收到错误消息,自定义消息提供程序仍然有效。

这也不是一个理想的解决方案,但到目前为止一直在努力。