I have a two step form process where the first set of data is stored in session.
[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
}
Controller
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)
returns false, saying VideoClip and VideoThumnail are required, despite mapping them from the seesionModel to the viewModel. I have added a breakpoint and checked they are not null.
It looks like there is some underlying functionality I am not aware of regarding how ModelState and ValidateModel() work , I just don't know what.
UPDATE
I wouldn't say I have resolved the issue but figured out a workaround that isn't that pretty, By going into the ModelState it is possible to set the ModelValue using SetModelValue()
then manually remove the error from the model state and then call TryValidateModel()
- you might not even have to add the values just remove the error I have not tried. Here is my work around.
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);
}
During the model binding the DefaultModelBinder
validates your action parameters.
So when the execution hits your public ActionResult TvCreate(TvNewsVideoVM modelVM)
method
the ModelState
is already containing the validation errors.
When you call TryValidateModel
it doesn't clear the ModelState
so the validation errors remain there that is why it returns false. So you need to clear the ModelState
collection if you want to redo the validation later manually:
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))
{
...
}
}