modelmetadata IsRequired 未获取 FluentValidation 创建的规则验证
modelmetadata IsRequired not get rules validation created by FluentValidation
我有一个 class 用于通过 Fluent 创建自定义验证器:
public partial class RegisterValidator : BaseLarValidator<RegisterModel>
{
public RegisterValidator(IDbContext dbContext)
{
RuleFor(x => x.UserName).NotEmpty().WithMessage("Username obbligatorio");
}
}
实现 RegisterValidator 验证器的 class 模型:
[Validator(typeof(RegisterValidator))]
public class RegisterModel
{
public string UserName { get; set; }
}
最后是一个 htmlhelper class 用于覆盖 @Html.LabelFor(...) in @Html.RequiredLabelFor(...):
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
public static MvcHtmlString RequiredLabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes = null, string id = "", bool generatedId = false)
{
return LabelHelper(html, ModelMetadata.FromLambdaExpression(expression, html.ViewData), ExpressionHelper.GetExpressionText(expression), htmlAttributes, id, generatedId);
}
internal static MvcHtmlString LabelHelper(HtmlHelper html, ModelMetadata metadata, string htmlFieldName, object htmlAttributes, string id, bool generatedId)
{
string labelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
if (String.IsNullOrEmpty(labelText))
{
return MvcHtmlString.Empty;
}
var sb = new StringBuilder();
sb.Append(labelText);
if (metadata.IsRequired)
sb.Append("<span class=\"required\"> *</span>");
var tag = new TagBuilder("label");
foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(htmlAttributes))
{
tag.MergeAttribute(prop.Name.Replace('_', '-'), prop.GetValue(htmlAttributes).ToString(), true);
}
if (!string.IsNullOrWhiteSpace(id))
{
tag.Attributes.Add("id", id);
}
else if (generatedId)
{
tag.Attributes.Add("id", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName) + "_Label");
}
tag.Attributes.Add("for", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName));
tag.InnerHtml = sb.ToString();
return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
}
问题是 LabelHelper 函数中的 "metadata.IsRequired" 始终 return 为假,但对于 "UserName" 属性 应该 return 为真...
我认为发生这种情况是因为 metadata.IsRequired 无法识别 RegisterValidator class...
中的“.NotEmpty()”
**
does anyone know how to solve the problem, doing so on the HtmlHelper
I can see if the property is "NotEmpty ()", or by another solution?
**
试试 NotNull:
RuleFor(x => x.UserName).NotNull().NotEmpty().WithMessage("Username obbligatorio");
您也可以尝试使用更简单的 DataAnnotations。
示例:
[Required]
string UserName {get; set;}
添加以下标记助手,然后您无需在代码中的任何地方进行更改。就用DI的力量
[HtmlTargetElement("label", Attributes = ForAttributeName)]
public class LabelRequiredTagHelper : LabelTagHelper
{
private readonly IValidatorFactory _factory;
private const string ForAttributeName = "asp-for";
public LabelRequiredTagHelper(IHtmlGenerator generator, IValidatorFactory factory) : base(generator)
{
_factory = factory;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
await base.ProcessAsync(context, output);
var validator = _factory.GetValidator(For.Metadata.ContainerType);
var description = validator.CreateDescriptor();
var propertyValidators = description.GetValidatorsForMember(For.Metadata.PropertyName);
if (For.Metadata.IsRequired || propertyValidators.Any(p => p is NotNullValidator || p is NotEmptyValidator))
{
var sup = new TagBuilder("sup");
sup.InnerHtml.Append("*");
output.Content.AppendHtml(sup);
}
}
}
我有一个 class 用于通过 Fluent 创建自定义验证器:
public partial class RegisterValidator : BaseLarValidator<RegisterModel>
{
public RegisterValidator(IDbContext dbContext)
{
RuleFor(x => x.UserName).NotEmpty().WithMessage("Username obbligatorio");
}
}
实现 RegisterValidator 验证器的 class 模型:
[Validator(typeof(RegisterValidator))]
public class RegisterModel
{
public string UserName { get; set; }
}
最后是一个 htmlhelper class 用于覆盖 @Html.LabelFor(...) in @Html.RequiredLabelFor(...):
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
public static MvcHtmlString RequiredLabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes = null, string id = "", bool generatedId = false)
{
return LabelHelper(html, ModelMetadata.FromLambdaExpression(expression, html.ViewData), ExpressionHelper.GetExpressionText(expression), htmlAttributes, id, generatedId);
}
internal static MvcHtmlString LabelHelper(HtmlHelper html, ModelMetadata metadata, string htmlFieldName, object htmlAttributes, string id, bool generatedId)
{
string labelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
if (String.IsNullOrEmpty(labelText))
{
return MvcHtmlString.Empty;
}
var sb = new StringBuilder();
sb.Append(labelText);
if (metadata.IsRequired)
sb.Append("<span class=\"required\"> *</span>");
var tag = new TagBuilder("label");
foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(htmlAttributes))
{
tag.MergeAttribute(prop.Name.Replace('_', '-'), prop.GetValue(htmlAttributes).ToString(), true);
}
if (!string.IsNullOrWhiteSpace(id))
{
tag.Attributes.Add("id", id);
}
else if (generatedId)
{
tag.Attributes.Add("id", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName) + "_Label");
}
tag.Attributes.Add("for", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName));
tag.InnerHtml = sb.ToString();
return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
}
问题是 LabelHelper 函数中的 "metadata.IsRequired" 始终 return 为假,但对于 "UserName" 属性 应该 return 为真... 我认为发生这种情况是因为 metadata.IsRequired 无法识别 RegisterValidator class...
中的“.NotEmpty()”**
does anyone know how to solve the problem, doing so on the HtmlHelper I can see if the property is "NotEmpty ()", or by another solution?
**
试试 NotNull:
RuleFor(x => x.UserName).NotNull().NotEmpty().WithMessage("Username obbligatorio");
您也可以尝试使用更简单的 DataAnnotations。
示例:
[Required]
string UserName {get; set;}
添加以下标记助手,然后您无需在代码中的任何地方进行更改。就用DI的力量
[HtmlTargetElement("label", Attributes = ForAttributeName)]
public class LabelRequiredTagHelper : LabelTagHelper
{
private readonly IValidatorFactory _factory;
private const string ForAttributeName = "asp-for";
public LabelRequiredTagHelper(IHtmlGenerator generator, IValidatorFactory factory) : base(generator)
{
_factory = factory;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
await base.ProcessAsync(context, output);
var validator = _factory.GetValidator(For.Metadata.ContainerType);
var description = validator.CreateDescriptor();
var propertyValidators = description.GetValidatorsForMember(For.Metadata.PropertyName);
if (For.Metadata.IsRequired || propertyValidators.Any(p => p is NotNullValidator || p is NotEmptyValidator))
{
var sup = new TagBuilder("sup");
sup.InnerHtml.Append("*");
output.Content.AppendHtml(sup);
}
}
}