Вы можете достичь того, что вы хотите, с одним классом и немного латерального мышления.
Сначала создайте свой класс с запрошенной проверкой. Затем создайте пользовательский ModelValidatorProvider, унаследованный от DataAnnotationsModelValidatorProvider
, например:
public class MyMetadataValidatorProvider : DataAnnotationsModelValidatorProvider
{
protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
{
var vals = base.GetValidators(metadata, context, attributes);
// check to see if any keys have been inserted
if (context.Controller.ViewData.Keys.Count > 0)
{
// check if we have a key named "NoValidate" with a value of true
// do not return the validtors if we do
if ((bool)context.Controller.ViewData.FirstOrDefault(k => k.Key == "NoValidate").Value)
{
// we do not want to return our validators, return an empty list
return new List<ModelValidator>();
}
}
else
{
// check if the form has a key named "NoValidate" with a value of true
// do not return the validtors if we do
if (context.HttpContext.Request.Form["NoValidate"].ToLowerInvariant() == "true")
{
// we do not want to return our validators, return an empty list
return new List<ModelValidator>();
}
}
// we want to return our validators
return vals;
}
}
Далее зарегистрируйте пользовательский ModelValidatorProvider в Application_Start
в Global.asax.cs, например:
ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add(new MyMetadataValidatorProvider());
Затем добавьте к вашему представлению следующее (это будет определять, будут ли возвращаться валидаторы при отправке формы в формате POST):
@Html.Hidden("NoValidate", ViewData.FirstOrDefault(k => k.Key == "NoValidate").Value)
Наконец, добавьте действия, подобные следующим:
public ActionResult Index()
{
var model = new MyModel();
// this will set validation to appear
ViewData.Add("NoValidate", false);
// this will suppress validation
ViewData.Add("NoValidate", true);
return View(model);
}
[HttpPost]
public ActionResult Index(MyModel model)
{
// we DO want validation, so let's test for it in addition
// to testing if the ModelState is valid
if (Request.Form["NoValidate"].ToLowerInvariant() != "true" && ModelState.IsValid)
{
ModelState.Clear();
var newmodel = new MyModel();
ViewData.Add("NoValidate", true);
return View(newmodel);
}
ViewData.Add("NoValidate", false);
return View(model);
}
Обратите внимание, что вы можете контролировать, будет ли проверка появляться в вашем действии GET, установив ключ NoValidate в ViewData, как вы хотите. На POST валидация определяется значением формы для NoValidate.
ВАЖНОЕ ПРИМЕЧАНИЕ: В вашем действии, которое требует проверки, вам нужно добавить тест, чтобы подтвердить, что в Форме нет ключа NoValidate или его значение не равно True
, чтобы обеспечить что пользователь не может избежать проверки.
UPDATE
Сначала у меня была валидация, появляющаяся только тогда, когда выполнялись определенные условия. Предполагалось, что это была ПЛОХАЯ ИДЕЯ, поэтому теперь проверка будет подавлена только при соблюдении условий.