我有一个相对简单的验证attribute,它需要一些服务才能完成ISVALID方法 - 基本上只是检索ID列表以将所选值与之相比。正如本文所建议的那样,我正在使用服务定位器模式在服务器端获取这些图案,这很好。
但是,我也想在客户端上执行相同的验证,但是请尝试,因为我可能找不到通过属性添加相同数据的方法,或者就此而言,将其设置在属性本身上足够早 - 使得属性可以掌握它 - 这样我就可以将ID添加到MergeAttribute调用中,从而在客户端端使用一些JavaScript访问它们。
这甚至可能吗?任何想法都是最有用的
上下文的简化代码...
验证:
public class InvalidIdAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var configService = validationContext.GetService<IProductService>();
var productIds = configService.GetIds()
var selectedId = (int)value;
var invalidId = productIds.SingleOrDefault(p => p.Invalid && p.Id == selectedId);
if (invalidId != null)
return new ValidationResult(FormatErrorMessage(invalidId.Name));
return ValidationResult.Success;
}
}
和attributeadapter
public class InvalidIdAttributeAdapter : AttributeAdapterBase<InvalidIdAttribute>
{
private readonly InvalidIdAttribute _attribute;
public InvalidIdAttributeAdapter(InvalidIdAttribute attribute, IStringLocalizer stringLocalizer)
: base(attribute, stringLocalizer)
{
_attribute = attribute;
}
public override void AddValidation(ClientModelValidationContext context)
{
//how do I get the productService in here?
var invalidIds = productService.GetIds().Where(p=>p.Invalid==true).Select(p=>p.Id);
var pipedIds = string.Join("|", invalidIds);
MergeAttribute(context.Attributes, "data-val", "true");
MergeAttribute(context.Attributes, "data-val-invalidid", GetErrorMessage(context));
MergeAttribute(context.Attributes, "data-val-invalidid-props", pipedIds);
}
public override string GetErrorMessage(ModelValidationContextBase validationContext)
{
return _attribute.FormatErrorMessage(validationContext.ModelMetadata.GetDisplayName());
}
}
适当的方法是仅依靠该服务作为属性适配器的一部分。因此,只需在其构造函数中添加其他依赖项:
public class InvalidIdAttributeAdapter : AttributeAdapterBase<InvalidIdAttribute>
{
private readonly InvalidIdAttribute _attribute;
private readonly IProductService _productService;
public InvalidIdAttributeAdapter(InvalidIdAttribute attribute, IStringLocalizer stringLocalizer, IProductService _productService)
: base(attribute, stringLocalizer)
{
_attribute = attribute;
_productService = productService;
}
public override void AddValidation(ClientModelValidationContext context)
{
var invalidIds = _productService.GetIds()…;
// …
}
}
如果要通过自定义属性适配器提供程序构造属性适配器,则必须将其依赖于服务,然后将其传递给属性适配器。由于属性适配器提供程序已注册并通过依赖项注入容器解决,因此您只需在其构造函数中添加其他依赖项。
请注意,如果您的IProductService
取决于范围的依赖关系,例如数据库上下文,然后您必须将属性适配器提供商注册为范围的依赖关系本身,而不是单身人士:
services.AddScoped<IValidationAttributeAdapterProvider, InvalidIdAttributeAdapterProvider>();