MVC ValidationSummary игнорирует ошибки проверки на уровне модели при связывании с использованием TryUpdateModel

Это очень похоже на проблему, уже опубликованную здесь :. 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 ведет себя так.

6
задан Community 23 May 2017 в 12:08
поделиться