在fluentvalidation.net之前,我可以将自定义标签提供给像这样的适当标签:
[Display(Name="Blah")]
public string BlahBlahBlah { get; set; }
我可以通过几种方式消费:
@Html.LabelFor(m => m.BlahBlahBlah)
@Html.DisplayNameFor(m => m.BlahBlahBlah)
<label asp-for="BlahBlahBlah"></label>
现在,我想从我的模型中删除所有数据注释,然后移至流利的验证。在我的验证器中,我有一个:
RuleFor(o => o.BlahBlahBlah)
.NotEmpty()
.WithName("Blah");
但这不起作用。为什么?
WithName
fluentValidation中的方法仅用于调整验证错误消息,如果要替换c#属性名称为smth更加用户友好(请参阅覆盖默认属性名称以获取详细信息)。
所以答案是 - 您不能通常用Display
替换CC_2,而仅用于验证错误消息。
,如果它有帮助,我将一个小属性和助手扔在一起以使它更加动态。
intdisplayNameatTribute.cs
[AttributeUsage(AttributeTargets.Property)]
public class WithDisplayNameAttribute : Attribute
{
public WithDisplayNameAttribute(string displayName)
{
DisplayName = displayName;
}
/// <summary>
/// The preferred friendly name to display for this property during validation.
/// </summary>
public string DisplayName { get; set; }
}
intdisplaynamehelper.cs
internal static class WithDisplayNameHelper
{
public static IReadOnlyDictionary<string, string> Map { get; }
static WithDisplayNameHelper()
{
var core = typeof(WithDisplayNameHelper).Assembly;
var map = new Dictionary<string, string>();
foreach (var parentModelType in core.GetExportedTypes().Where(x => x.IsClass))
{
foreach (var prop in parentModelType.GetProperties())
{
var att = prop.GetCustomAttribute<WithDisplayNameAttribute>();
if (att == null) continue;
var key = GetKey(parentModelType, prop);
if (!map.ContainsKey(key))
{
map.Add(key, att.DisplayName);
}
}
}
Map = new ReadOnlyDictionary<string, string>(map);
}
/// <summary>
/// Gets the key to use for this property.
/// </summary>
/// <param name="parent">The parent class containing the property.</param>
/// <param name="prop">The property described by the display name.</param>
/// <returns></returns>
private static string GetKey(Type parent, PropertyInfo prop) => GetKey(parent, prop.Name);
/// <inheritdoc cref="GetKey(System.Type,System.Reflection.PropertyInfo)"/>
private static string GetKey(Type parent, string prop) => $"{parent.FullName}.{prop}";
/// <summary>
/// Retrieves the display name if one was set using the <see cref="WithDisplayNameAttribute"/>. Otherwise will return the given <paramref name="propertyName"/>.
/// </summary>
/// <param name="parent">The parent class containing the property.</param>
/// <param name="propertyName">The property name.</param>
/// <returns></returns>
public static string GetDisplayNameOrDefault(Type parent, string propertyName) =>
Map.TryGetValue(GetKey(parent, propertyName), out var value)
? value
: propertyName;
/// <summary>
/// Attempts to retrieve the display name if one was set using the <see cref="WithDisplayNameAttribute"/>.
/// </summary>
/// <inheritdoc cref="GetDisplayNameOrDefault"/>
/// <returns></returns>
public static bool TryGetDisplayName(Type parent, string propertyName, out string result) =>
Map.TryGetValue(GetKey(parent, propertyName), out result);
}
和扩展方法:
/// <summary>
/// Specifies a custom property name to use within the error message.
/// </summary>
/// <param name="rule">The current rule</param>
/// <returns></returns>
public static IRuleBuilderOptions<T, TProperty> WithDisplayName<T, TProperty>(
this IRuleBuilderOptions<T, TProperty> rule)
{
return rule.Configure(x =>
{
if (WithDisplayNameHelper.TryGetDisplayName(typeof(T), x.PropertyName, out var displayName))
x.DisplayName = new StaticStringSource(displayName);
});
}