我实现了一个扩展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字段是必需的。'。
有没有办法提供添加'*'字符作为标签元数据的一部分,而不会影响验证消息中使用的属性名称?或者,有没有办法在构建验证消息时提供自定义元数据?
答案 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方法调用,这样我们就不会收到错误消息,自定义消息提供程序仍然有效。
这也不是一个理想的解决方案,但到目前为止一直在努力。