您应该考虑使用自己的metadata provider 扩展元模型框架,以在您的站点配置和模型元数据之间进行实际绑定。在元数据创建过程中,您实际上可以在属性模型元数据上将 required property 标志设置为 true。我无法确定这是否会导致内置编辑器模板生成属性,但我认为确实如此。在最坏的情况下,您实际上可以创建一个新的RequiredAttribute 并将其附加到该属性,这有点笨拙,但在某些情况下效果很好。
您也可以使用IMetadataAware 属性来执行此操作,尤其是如果Required 是您的用户可以自定义的唯一元数据方面,但实现实际上取决于您要执行的操作。
在您的特定情况下使用自定义 ModelMetadataProvider 的一个主要优点是您可以使用依赖注入(通过ModelMetadataProviders)将您的客户设置持久性机制纳入范围,而使用数据属性您只能编写一个隔离的创建元数据模型后立即运行的方法。
这是自定义模型元数据提供程序的示例实现,您只需将客户端设置更改为您想要使用的任何设置。
已更新但根本没有测试
public class ClientSettingsProvider
{
public ClientSettingsProvider(/* db info */) { /* init */ }
public bool IsPropertyRequired(string propertyIdentifier)
{
// check the property identifier here and return status
}
}
public ClientRequiredAttribute : Attribute
{
string _identifier;
public string Identifier { get { return _identifer; } }
public ClientRequiredAttribute(string identifier)
{ _identifier = identifier; }
}
public class RequiredModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
ClientSettings _clientSettings;
public RequiredModelMetadataProvider(ClientSettings clientSettings)
{
_clientSettings = clientSettings;
}
protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
{
// alternatively here is where you could 'inject' a RequiredAttribute into the attributes list
var clientRequiredAttribute = attributes.OfType<ClientRequiredAttribute>().SingleOrDefault();
if(clientRequiredAttribute != null && _clientSettings.IsPropertyRequired(clientRequiredAttribute.Identifier))
{
// By injecting the Required attribute here it will seem to
// the base provider we are extending as if the property was
// marked with [Required]. Your data validation attributes should
// be added, provide you are using the default editor templates in
// you view.
attributes = attributes.Union(new [] { new RequiredAttribute() });
}
var metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
// REMOVED, this is another way but I'm not 100% sure it will add your attributes
// Use whatever attributes you need here as parameters...
//if (_clientSettings.IsPropertyRequired(containerType, propertyName))
//{
// metadata.IsRequired = true;
//}
return metadata;
}
}
用法
public class MyModel
{
[ClientRequired("CompanyName")]
public string Company { get; set; }
}
public class MyOtherModel
{
[ClientRequired("CompanyName")]
public string Name { get; set; }
public string Address { get; set; }
}
这两种模型都会根据您的客户端设置提供商验证字符串“CompanyName”。