Hier ist eine Lösung für mein Problem, bei der ich das integrierte erforderliche Attribut verwenden kann und trotzdem benutzerdefiniertes Verhalten erhalte. Dies ist nur ein Proof-of-Concept-Code.
Das Modell:
public class Page : IPageModel {
[Display(Name = "Seite", Prompt = "Seitenname angeben...")]
[Required(ErrorMessage = "Sie müssen einen Seitenname angeben")]
public PageReference PageReference { get; set; }
}
Der Modell-Binder:
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);
}
}
Der Modell-Binder-Anbieter:
public class InheritanceAwareModelBinderProvider : Dictionary, IModelBinderProvider {
public IModelBinder GetBinder(Type modelType) {
var binders = from binder in this
where binder.Key.IsAssignableFrom(modelType)
select binder.Value;
return binders.FirstOrDefault();
}
}
Und zuletzt die globale.asax-Registrierung:
var binderProvider = new InheritanceAwareModelBinderProvider {
{
typeof (IPageModel), new PageModelBinder() }
};
ModelBinderProviders.BinderProviders.Add(binderProvider);
Das Ergebnis: http://cl.ly/IjCS
Was halten Sie von dieser Lösung?