我正在关注此示例:https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation并尝试实现自己的自定义属性进行验证。
现在,viewmodel有两个我希望从这个方法中访问的字段,因此它们可以使用" data-val"属性。我的问题是,我怎么能说出一个名为" Myprop"来自上下文?当我调试时,我可以查看context.ActionContext.ViewData.Model下的信息,但是当我使用Visual Studio&#34时,我无法获得其他信息。#34; quick watch"特征。自定义属性位于viewmodel上的属性上。
public void AddValidation(ClientModelValidationContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
MergeAttribute(context.Attributes, "data-val", "true");
MergeAttribute(context.Attributes, "data-val-classicmovie", GetErrorMessage());
var year = _year.ToString(CultureInfo.InvariantCulture);
MergeAttribute(context.Attributes, "data-val-classicmovie-year", year);
}
答案 0 :(得分:2)
我遇到了类似的问题。简短的回答是,你不能来自。您只能从那里访问元数据,而不是实际模型。原因是您的模型元数据和基于它的验证是在首次使用时完成的,然后进行缓存。因此,您永远无法通过属性修饰器根据模型更改要返回的验证规则。
如果您需要根据模型的实例/内容动态决定要呈现哪些客户端data-val-*
属性,则需要继承DefaultValidationHtmlAttributeProvider
,而不是使用属性,并覆盖AddValidationAttributes方法。这是迄今为止我发现的唯一方法。这是因为在此方法中,您可以访问ModelExplorer
public class CustomValidationHtmlAttributeProvider : DefaultValidationHtmlAttributeProvider
{
private readonly IModelMetadataProvider metadataProvider;
public CustomValidationHtmlAttributeProvider(IOptions<MvcViewOptions> optionsAccessor, IModelMetadataProvider metadataProvider, ClientValidatorCache clientValidatorCache)
: base(optionsAccessor, metadataProvider, clientValidatorCache)
{
this.metadataProvider = metadataProvider;
}
public override void AddValidationAttributes(ViewContext viewContext, ModelExplorer modelExplorer, IDictionary<string, string> attributes)
{
//base implimentation
base.AddValidationAttributes(viewContext, modelExplorer, attributes);
//re-create the validation context (since it's encapsulated inside of the base implimentation)
var context = new ClientModelValidationContext(viewContext, modelExplorer.Metadata, metadataProvider, attributes);
//Only proceed if it's the model you need to do custom logic for
if (!(modelExplorer.Container.Model is MyViewModelClass model) || !modelExplorer.Metadata.PropertyName == "Myprop") return;
//Do stuff!
var validationAttributeAdapterProvider = viewContext.HttpContext.RequestServices.GetRequiredService<IValidationAttributeAdapterProvider>();
if (model.Myprop)
{
var validationAdapter = (RequiredAttributeAdapter)validationAttributeAdapterProvider.GetAttributeAdapter(new RequiredAttribute(), null);
validationAdapter.Attribute.ErrorMessage = "You not enter right stuff!";
validationAdapter.AddValidation(context);
}
}
}
然后在ConfigureServices()
Startup
中注册此课程
public void ConfigureServices(IServiceCollection services)
{
//All your other DI stuff here
//register the new ValidationHtmlAttributeProvider
services.AddSingleton<ValidationHtmlAttributeProvider, PseudoAttributeValidationHtmlAttributeProvider>();
}
缺点是,如果你有多个模型你需要这样做,它真的很难实现。如果有人找到了更好的方法,我很乐意听到: - )