The problem: How to update ModelState in posting+validation scenario.
I\'ve got a simple form:
<%= Html.ValidationSummary() %>
<% using(Html
am I doing something extremely uncommon or am I missing something?
I think this is pretty rare. I think MVC is assuming validation errors are a yes/no affair, and in this case you're using a validation error as a means to give general user feedback.
I think MVC also seems happiest when POSTs either fail due to validation errors, or perform an action and redirect or render something completely different. Outside for model validation errors, it's pretty rare to re-render the same input.
I've been using MVC for about a year now and just ran into this in another context, where after a POST I wanted to render a fresh form as the response.
[HttpPost]
public ActionResult Upload(DocumentView data) {
if(!ModelState.IsValid) return View(data);
ProcessUpload(data);
return View(new DocumentView());
}
MVC is rendering the ModelState
from data
, not my new object. Very surprising.
If the former, then how could I implement such functionality in a better way
I know this post is fairly old but it's a problem I've had before and I just thought of a simple solution that I like - just clear the ModelState after you've got the posted values.
UpdateModel(viewModel);
ModelState.Clear();
viewModel.SomeProperty = "a new value";
return View(viewModel);
and the view has to use the (possibly modified) view model object rather than the ModelState.
Maybe this is really obvious. It seems so in hindsight!
You could accept a form collection as a parameter instead of your model object in your controller, like this : public ActionResult Index(FormCollection Form)
.
Therefor default model binder will not update the model state, and you'll get the behaviour you want.
Edit : Or you can just update the ModelStateDictionary to reflect your changes to the model.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(M m)
{
if (m.Value != "a")
{
ModelState["m.Value"].Value = new ValueProviderResult("a", m.Name,
CultureInfo.CurrentCulture);
ModelState.AddModelError("m.Value", "should be \"a\"");
m.Value = "a";
return View(m);
}
return View("About");
}
Note : I'm not sure if this is the best way. But it seems to work and it should be the behaviour you want.