Есть способ сделать это, не требуя шаблонного кода в верхней части каждого действия контроллера.
Вам нужно будет заменить связыватель модели по умолчанию на один из ваших:
protected void Application_Start()
{
// ...
ModelBinderProviders.BinderProviders.Clear();
ModelBinderProviders.BinderProviders.Add(new CustomModelBinderProvider());
// ...
}
Ваш поставщик связывателей моделей выглядит следующим образом:
public class CustomModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(Type modelType)
{
return new CustomModelBinder();
}
}
Теперь создайте настраиваемый связыватель модели, который фактически вызывает проверку.Вот где тяжелая работа проделана:
public class CustomModelBinder : DefaultModelBinder
{
protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
base.OnModelUpdated(controllerContext, bindingContext);
ForceModelValidation(bindingContext);
}
private static void ForceModelValidation(ModelBindingContext bindingContext)
{
var model = bindingContext.Model as IValidatableObject;
if (model == null) return;
var modelState = bindingContext.ModelState;
var errors = model.Validate(new ValidationContext(model, null, null));
foreach (var error in errors)
{
foreach (var memberName in error.MemberNames)
{
// Only add errors that haven't already been added.
// (This can happen if the model's Validate(...) method is called more than once, which will happen when
// there are no property-level validation failures.)
var memberNameClone = memberName;
var idx = modelState.Keys.IndexOf(k => k == memberNameClone);
if (idx < 0) continue;
if (modelState.Values.ToArray()[idx].Errors.Any()) continue;
modelState.AddModelError(memberName, error.ErrorMessage);
}
}
}
}
Вам также понадобится метод расширения IndexOf.Это дешевая реализация, но она будет работать:
public static int IndexOf<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
if (source == null) throw new ArgumentNullException("source");
if (predicate == null) throw new ArgumentNullException("predicate");
var i = 0;
foreach (var item in source)
{
if (predicate(item)) return i;
i++;
}
return -1;
}