Проблемы ASP.NET MVC TryValidateModel() при изменении модели

У меня есть двухэтапный процесс формы, в котором первый набор данных хранится в сеансе.

[IsMp4File]
[Required(ErrorMessage = "* Please select a video to upload")]
public HttpPostedFileBase VideoClip { get; set; }

[Required(ErrorMessage = "* Please select a thumbmail image")]
public HttpPostedFileBase VideoThumbnail{ get;  set; }

public string VideoFileName { get { return VideoClip.FileName; } }

public NewsWizardStep CurrentStep { get; set; }

...

public enum NewsWizardStep : int
{
  One = 1,
  Two = 2,
  Three = 3,
  Four = 4,
  Five = 5,
  Six = 6
}

Контроллер

public ActionResult TvCreate(TvNewsVideoVM modelVM)
{
   if (modelVM.CurrentStep == NewsWizardStep.Two)
   {
     var sessionModel = ((TvNewsVideoVM)Session["TvModelVM"]);

     modelVM.VideoClip = sessionModel.VideoClip;
     modelVM.VideoThumbnail = sessionModel.VideoThumbnail;
   }

   if (TryValidateModel(modelVM))
   {
     ...
   }
}

TryValidateModel(modelVM) возвращает false, говоря, что требуются VideoClip и VideoThumnail, несмотря на то, что они отображаются из seesionModel в viewModel. Я добавил точку останова и проверил, что они не равны нулю.

Похоже, что есть некоторые базовые функции, о которых я не знаю, как работают ModelState и ValidateModel(), я просто не знаю, что.

ОБНОВЛЕНИЕ

Я бы не сказал, что решил проблему, но нашел обходной путь, который не так уж хорош. Перейдя в ModelState, можно установить ModelValue с помощью SetModelValue(), затем вручную удалить ошибку из состояния модели, а затем вызвать TryValidateModel() - возможно, вам даже не придется добавлять значения, просто удалите ошибку, которую я не пробовал. Вот моя работа вокруг.

if (modelVM.CurrentStep == NewsWizardStep.Two)
{
  var sessionModel = ((MtTvNewsVideoVM)Session["MtTvModelVM"]);

  modelVM.VideoClip = sessionModel.VideoClip;
  modelVM.VideoThumbnail = sessionModel.VideoThumbnail;

  ModelState.SetModelValue("VideoClip", new  ValueProviderResult(sessionModel.VideoThumbnail, sessionModel.VideoFileName, CultureInfo.CurrentCulture));
                ModelState.SetModelValue("VideoThumbnail", new ValueProviderResult(sessionModel.VideoClip, sessionModel.VideoFileName, CultureInfo.CurrentCulture));

  ModelState["VideoClip"].Errors.RemoveAt(0);
  ModelState["VideoThumbnail"].Errors.RemoveAt(0);
}

person SimonGates    schedule 20.12.2011    source источник


Ответы (1)


Во время привязки модели DefaultModelBinder проверяет ваши параметры действия. Поэтому, когда выполнение достигает вашего метода public ActionResult TvCreate(TvNewsVideoVM modelVM), ModelState уже содержит ошибки проверки.
Когда вы вызываете TryValidateModel, он не очищает ModelState, поэтому ошибки проверки остаются там, поэтому он возвращает false . Поэтому вам нужно очистить коллекцию ModelState, если вы хотите повторить проверку позже вручную:

public ActionResult TvCreate(TvNewsVideoVM modelVM)
{
   ModelState.Clear();

   if (modelVM.CurrentStep == NewsWizardStep.Two)
   {
     var sessionModel = ((TvNewsVideoVM)Session["TvModelVM"]);

     modelVM.VideoClip = sessionModel.VideoClip;
     modelVM.VideoThumbnail = sessionModel.VideoThumbnail;
   }

   if (TryValidateModel(modelVM))
   {
     ...
   }
}
person nemesv    schedule 20.12.2011
comment
Так лучше, спасибо - я не понимаю, почему метод TryValidateModel() сначала не вызывает метод Clear(), а затем пытается проверить модель. - person SimonGates; 21.12.2011
comment
если вас интересует только ручная проверка, вы можете пропустить начальную магию проверки, украсив метод Controller с помощью ‹ValidateInput(False)› - person bkwdesign; 07.10.2013
comment
Это ValidateInput false является ключом здесь. Он сохранит значения в ModelState, но просто пропустит автоматическую проверку. ModelState.Clear хорош, но он удалит эти значения. - person Richard Housham; 27.11.2018
comment
Подождите, подождите, похоже, это не так - не уверен, что ValidateInput делает с ModelState - person Richard Housham; 27.11.2018
comment
Это спасло меня от поиска, я даже не думал об этом, прежде чем он достигнет моих методов. - person kabuto178; 11.10.2020