FluentValidation.NET 等效于 [Display(Name)]
Posted
技术标签:
【中文标题】FluentValidation.NET 等效于 [Display(Name)]【英文标题】:FluentValidation.NET equivalent to [Display(Name)] 【发布时间】:2017-05-12 03:11:15 【问题描述】:在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");
但这不起作用。为什么?
【问题讨论】:
【参考方案1】:FluentValidation 中的WithName
方法仅用于调整验证错误消息,如果您想替换 C# 属性名称以更加用户友好(请参阅
Overriding the Default Property Name 了解详细信息)。
所以答案是 - 一般情况下,您不能将 Display
替换为 WithName()
,仅用于验证错误消息。
【讨论】:
有没有办法使用 Fluent Validation 添加显示? 不,这个库只用于验证。 这是令人沮丧的信息。现在我希望这个库被称为“Fluent Annotation”! 我想摆脱Display
属性的唯一简单选择是直接在Razor 中指定显示文本,其中一个重载为LabelFor
。另一种方法是编写您的自定义 MyLabelFor
扩展方法,您可以在其中从任何您想要的来源获取文本。【参考方案2】:
如果有帮助,我将一个小属性和助手放在一起,以使其更具动态性。
WithDisplayNameAttribute.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;
WithDisplayNameHelper.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);
);
【讨论】:
以上是关于FluentValidation.NET 等效于 [Display(Name)]的主要内容,如果未能解决你的问题,请参考以下文章