Предположим, у меня есть эта модель:
public class ViewModel
{
[Required]
public string UserInput { get; set; }
[Required]
public Guid EntityId { get; set; }
}
Теперь, когда пользовательский ввод неправильный, я хочу повторно отобразить ту же страницу, но с ошибками проверки (например, / Изменить). Однако, когда EntityId неверен, я хочу перенаправить на другую страницу (например, /Create).
Я могу сделать это вручную внутри каждого контроллера ...
if (!ModelState.IsValidField("EntityId")) { redirect }
//or
if (string.IsNullOrEmpty(data.EntityId)) { redirect }
но это немного скучно и нарушает СУХОЙ. Отображение нескольких объектов, вложенных моделей просмотра с объектами ... слишком громоздко. Мне бы лучше иметь что-то вроде ModelState.IsValidUserData и ModelState.IsValidCriticalData. Но такого нет.
Теперь EntityId на самом деле связан с помощью моего пользовательского связывателя модели, который знает , что он критически важен. Итак, есть такое решение:
- Обычные поля заполняют ModelState ошибками, как обычно.
- (a) Критические поля связываются с помощью пользовательского связывателя модели, который выдает специальное «CriticalModelErrorException». Действия контроллера имеют атрибут [HandleCrirticalError ("action", "controller ')] - который обрабатывает критические ошибки и перенаправляет на указанное действие.
- (b) Критические поля связываются с помощью пользовательского связывателя модели, который устанавливает свойство BaseController.CriticalModelErrors (очевидно, что все контроллеры получены из базового класса суперконтроллера). Каждое действие может свободно проверять ModelState.IsValid и base.CriticalModelErrors и вести себя свободно на этом основании.
- (c) Критические поля связываются с помощью пользовательского связывателя модели, который устанавливает ошибки состояния модели специального формата, например, AddModelError (name, "! CRITICAL! Text"; тогда у базового контроллера есть метод, который обнаруживает такие строки.
2a пример:
[HandleCriticalError("Create")] // uses the same controller
[HandleModelStateError("Edit")] // redisplays page with validation errors
public ActionResult Edit(ViewModel data)
{
// here we know both our data entities and user data are valid and safe
}
2b пример
public ActionResult Edit(ViewModel data)
{
if (!ModelState.IsValid)
return View(data);
if (base.CriticalModelErrors.Count > 0)
return RedirectToAction("Create");
// here we know both our data entities and user data are valid and safe
}
2c пример
protected bool HasCriticalErrors()
{
return ModelState.Any(x => x.Value.Errors.Any(x => x.ErrorMessage.StartsWith("!CRITICAL!")))
}
// then same as 2b
Теперь вопросы: как с этим справляются другие приложения и разработчики (вы и ваши приложения)? Какой из них вы бы предпочли? Есть ли недостатки или лучшие решения?