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 в своем классе модели.

Другие вопросы по тегам