これは、組み込みの必須属性を使用してもカスタム動作を取得できるという私の問題に対する1つの解決策です。これは、概念コードの証明にすぎません。
モデル:
public class Page : IPageModel {
[Display(Name = "Page", Prompt = "Specify page name...")]
[Required(ErrorMessage = "You must specify a page name")]
public PageReference PageReference { get; set; }
}
モデル バインダー:
public class PageModelBinder : DefaultModelBinder {
protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext) {
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(bindingContext.ModelType)) {
var attributes = property.Attributes;
if (attributes.Count == 0) continue;
foreach (var attribute in attributes) {
if (attribute.GetType().BaseType == typeof(ValidationAttribute) && property.PropertyType == typeof(PageReference)) {
var pageReference = bindingContext.ModelType.GetProperty(property.Name).GetValue(bindingContext.Model, null) as PageReference;
Type attrType = attribute.GetType();
if (attrType == typeof (RequiredAttribute) && string.IsNullOrEmpty(pageReference.Name)) {
bindingContext.ModelState.AddModelError(property.Name,
((RequiredAttribute) attribute).ErrorMessage);
}
}
}
}
base.OnModelUpdated(controllerContext, bindingContext);
}
}
モデル バインダー プロバイダー:
public class InheritanceAwareModelBinderProvider : Dictionary<Type, IModelBinder>, IModelBinderProvider {
public IModelBinder GetBinder(Type modelType) {
var binders = from binder in this
where binder.Key.IsAssignableFrom(modelType)
select binder.Value;
return binders.FirstOrDefault();
}
}
最後に、global.asax の登録を行います。
var binderProvider = new InheritanceAwareModelBinderProvider {
{
typeof (IPageModel), new PageModelBinder() }
};
ModelBinderProviders.BinderProviders.Add(binderProvider);
結果: http://cl.ly/IjCS
では、このソリューションについてどう思いますか?