ASP.NET MVC 3 - выберите, какое свойство модели проверяет каждая кнопка отправки
У меня есть представление с тремя кнопками отправки. Первая кнопка должна проверять некоторые поля, вторая кнопка должна проверять другие поля, третья кнопка ничего не проверяет. Как я могу сделать это как на стороне клиента (ненавязчиво), так и на стороне сервера?
2 ответа
Лично мне всегда нравилась и использовалась библиотека FluentValidation.NET во всех моих проектах. Мало того, что он очень мощный с точки зрения выражения правил проверки, но эта библиотека имеет отличную интеграцию с ASP.NET MVC. Поэтому я попытаюсь предоставить пример решения этой проблемы, используя его (пока только проверка на стороне сервера, позже мы можем поговорить о ненавязчивой проверке на стороне клиента, если хотите).
Поэтому запустите новый проект ASP.NET MVC 3, используя шаблон по умолчанию, и установите FluentValidation.MVC3
Пакет NuGet (текущая стабильная версия 2.0.0.0).
Тогда давайте определим модель представления:
public class MyViewModel
{
public string Field1 { get; set; }
public string Field2 { get; set; }
}
Теперь мы можем предположить, что если button1
нажата Field1
требуется, и если button2
нажата Field2
требуется, и если button3
нажата ни одна из них не требуется. Вымышленный сценарий, но довольно близкий к вашим требованиям.
Теперь давайте определим два разных беглых валидатора для этой модели, соответствующих каждому button1
а также button2
:
public class MyModelValidator1 : AbstractValidator<MyViewModel>
{
public MyModelValidator1()
{
RuleFor(x => x.Field1)
.NotEmpty();
}
}
public class MyModelValidator2 : AbstractValidator<MyViewModel>
{
public MyModelValidator2()
{
RuleFor(x => x.Field2)
.NotEmpty();
}
}
Теперь, потому что только во время выполнения мы знаем, какая кнопка нажата, нам нужно применить правильный валидатор на основе значения в запросе. Итак, давайте напишем собственную фабрику поставщиков валидаторов:
public class MyFactory : IValidatorFactory
{
private readonly Func<HttpContextBase> _contextProvider;
public MyFactory(Func<HttpContextBase> contextProvider)
{
_contextProvider = contextProvider;
}
public IValidator GetValidator(Type type)
{
if (type == typeof(MyViewModel))
{
var context = _contextProvider();
if (!string.IsNullOrEmpty(context.Request["button1"]))
{
return new MyModelValidator1();
}
if (!string.IsNullOrEmpty(context.Request["button2"]))
{
return new MyModelValidator2();
}
}
return null;
}
public IValidator<T> GetValidator<T>()
{
return (IValidator<T>)GetValidator(typeof(T));
}
}
и зарегистрируйте его в Application_Start
:
ModelValidatorProviders.Providers.Add(
new FluentValidationModelValidatorProvider(
new MyFactory(() => new HttpContextWrapper(HttpContext.Current))
)
);
и это почти все. Теперь то, что осталось, тривиально.
Контроллер:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel();
return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
return Content("Thanks for submitting", "text/plain");
}
}
и вид:
@model MyViewModel
@using (Html.BeginForm())
{
<div>
@Html.LabelFor(x => x.Field1)
@Html.EditorFor(x => x.Field1)
@Html.ValidationMessageFor(x => x.Field1)
</div>
<div>
@Html.LabelFor(x => x.Field2)
@Html.EditorFor(x => x.Field2)
@Html.ValidationMessageFor(x => x.Field2)
</div>
<input type="submit" value="Submit with button 1" name="button1" />
<input type="submit" value="Submit with button 2" name="button2" />
<input type="submit" value="Submit with button 3" name="button3" />
}
Скорее всего, с большим количеством ручного использования, особенно если вы хотите, чтобы он был ненавязчивым. Вам нужно будет создать что-то вроде <input data-validationgroup="group1"...
и затем на действии щелчка, чтобы ваш код JavaScript подтвердил то, что вы хотите. Я полагаю, что jQuery Validate имеет некоторую поддержку наборов правил, но вам придется это выяснить.
Вам нужно будет выполнить аналогичную последовательность на стороне сервера и создать классы / блоки / методы проверки типа набора правил, которые вы интерпретируете действие отправки для соответствующего набора правил. Я бы посмотрел на библиотеку, как FluentValidation для этой части.
Для достижения того, чего вы хотите, очень маловероятно, что вы сможете достичь этого, используя атрибуты DataAnnotations в своем классе модели.