Это очень похоже на проблему, уже опубликованную здесь :. ASP.NET MVC :Сообщения проверки, установленные в TryUpdateModel, не отображают ValidationSummary
Я не уверен, что эта старая тема относится к более ранней версии MVC, но в MVC3 я испытываю некоторое странное поведение в том же духе.
У меня есть модельный класс под названием Trade. Он наследуется от IValidatableObject, поэтому реализует метод Validate. В рамках этого у нас есть некоторая проверка модели в целом (в отличие от аннотаций данных, которые обеспечивают проверку свойств ). Валидация выглядит следующим образом:
public IEnumerable Validate(ValidationContext validationContext)
{
var validationResults = new List();
if (this.EndDate < this.StartDate)
{
validationResults.Add(new ValidationResult("End date must be greater than start date"));
}
return validationResults;
}
У нас есть модель представления, помогающая отображать сделку. Содержит ссылку на торговую модель через свойство TradeModel. Таким образом, в основном модель представления представляет собой торговую модель, плюс некоторая дополнительная информация для заполнения раскрывающихся -списков вниз, таких как контрагенты и т. д.
Наш класс CSHTML содержит ValidationSummary с аргументом «true», что означает, что он будет отображать только ошибки модели.
Если я реализую свой метод контроллера HttpPost для создания новой сделки следующим образом...
[HttpPost]
public ActionResult Create(FormCollection collection)
{
var trade = new Trade();
if (this.TryUpdateModel(trade))
{
if (this.SaveChanges(this.ModelState, trade))
{
return this.RedirectToAction("Index");
}
}
return this.View(trade);
}
... когда я вхожу в сделку с StartDate > EndDate, я обнаруживаю, что TryUpdateModel возвращает false, и пользователь возвращается к своей сделке. Это кажется логичным. К сожалению, ValidationSummary не показывает никаких сообщений об ошибках.
Если я поставлю точку останова в методе Create и изучу ModelState, я увижу, что в словаре есть сообщение об ошибке. Это противоречит ключу «TradeModel», а не любому из свойств. Опять же, это кажется логичным.
Одна теория о том, почему это так,заключается в том, что ValidationSummary предполагает, что любые ошибки проверки по ключу, который не является String.Empty, должны быть ошибками проверки свойства, он игнорирует наши ошибки проверки, потому что у нас есть модель представления, которая содержит ссылку на модель, поэтому в результате ключ является «TradeModel ".
Что выбивает из колеи эту теорию, так это :, если я перепишу функцию Create контроллера следующим образом...
[HttpPost]
public ActionResult Create(Trade trade, FormCollection collection)
{
if (this.SaveChanges(this.ModelState, trade))
{
return this.RedirectToAction("Index");
}
return this.View(trade);
}
... и, следовательно, полагаться на то, что MVC выполняет привязку «автоматически», и повторно -запускать тот же тестовый сценарий, пользователю предоставляется предполагаемое сообщение об ошибке!
Если я добавлю точку останова и посмотрю на ModelState, я увижу идентичные сообщения об ошибках для тех же ключей, что и раньше, но на этот раз ValidationSummary их подхватывает!
Если я изменю проверку следующим образом, она будет работать с функцией Create контроллера, написанной любым способом:
public IEnumerable Validate(ValidationContext validationContext)
{
var validationResults = new List();
if (this.EndDate < this.StartDate)
{
validationResults.Add(new ValidationResult("End date must be greater than start date", new[] { "StartDate" }));
}
return validationResults;
}
Так что ясно, что это только проблема с ошибками проверки на уровне модели.
Любая помощь в этом будет принята с благодарностью! Есть причины (, которые я сейчас не буду рассматривать ), почему нам нужно создать экземпляр нашей модели представления вручную и вызвать привязку с помощью TryUpdateModel.
Заранее спасибо!
ОБНОВЛЕНИЕ
Похоже, что теория ValidationSummary, отображающая только ошибки с ключом в ModelState String.Empty, когда сказано исключить ошибки свойств, на самом деле верна. Я просмотрел исходный код, и он фактически использует ViewData.TemplateInfo.HtmlFieldPrefix для поиска ошибок проверки на уровне модели -. По умолчанию это String.Empty.
Таким образом, изменение этого значения на «TradeModel» кажется логичным, но это приводит к тому, что каждый HTML-идентификатор или имя имеют префикс, поэтому привязка не выполняется!
Если модель представления содержит ссылку на бизнес-модель, любые ошибки, добавленные в ModelState с помощью IValidatableObject, добавляются с ключом, включающим префикс, равный имени свойства бизнес-модели в модели представления (, в нашем случае «TradeModel» ). ],в результате получаются такие ключи, как "TradeModel.CounterpartyId" и т. д. Ошибки уровня модели -добавляются с ключом, равным имени свойства бизнес-модели модели представления ("TradeModel" ).
Таким образом, получается, что бизнес не может добавлять ошибки проверки уровня модели -, если модель представления построена таким образом.
Что меня озадачивает, так это то, почему это на самом деле работает в нашем «реальном» проекте, когда функция Create контроллера написана так, что она принимает объект модели представления Trade в качестве аргумента. Я, должно быть, пропустил это вчера, но, глядя на это сегодня, когда MVC связывается и запускается проверка, кажется, что добавляется дополнительный ключ в конец словаря со значением String.Empty. Он содержит дубликат ошибок, добавленных с помощью ключа TradeModel. Как и следовало ожидать, ValidationSummary подхватывает их!
Так почему же MVC делает это в нашем реальном проекте, а не в простом тестовом приложении?
Я видел, как проверка запускалась дважды, когда функция контроллера была написана так, чтобы использовать модель представления в качестве аргумента. Может быть, это каждый раз делает что-то немного другое?
ОБНОВЛЕНИЕ... СНОВА
Причина, по которой это работает в нашем реальном проекте, заключается в том, что в нашем базовом контроллере (скрыт некоторый код, от которого наследуются все остальные ), который копирует все ошибки, обнаруженные в состоянии модели, в новую запись с ключом String.Empty. Этот код вызывался только в одном из двух сценариев. Таким образом, реальной разницы между реальным и тестовым приложениями нет.
Теперь я понимаю, что происходит и почему ValidationSummary ведет себя так.