tags:

views:

3929

answers:

4

How can I return the result of a different action or move the user to a different action if there is an error in my ModelState without losing my ModelState information?

The scenario is; Delete action accepts a POST from a DELETE form rendered by my Index Action/View. If there is an error in the Delete I want to move the user back to the Index Action/View and show the errors that are stored by the Delete action in the ViewData.ModelState. How can this be done in ASP.NET MVC?

[AcceptVerbs(HttpVerbs.Post | HttpVerbs.Delete)]
public ActionResult Delete([ModelBinder(typeof(RdfUriBinder))] RdfUri graphUri)
{
    if (!ModelState.IsValid)
        return Index(); //this needs to be replaced with something that works :)

    return RedirectToAction("Index");
}
A: 

Maybe try

return View("Index");

instead of

return Index();
Ty
That doesn't work, as it doesn't execute the logic in the Index Action. All it does is try to render the current model using the Index view.
spoon16
Don't you just want to show the model errors on the same view that you posted from? What are you doing in the Index action that needs to be executed when there are model errors? I just return View("ViewName", model) when there are errors and it works fine.
Ty
No, I want to redirect to the Index action bind the view to the data generated by that action as well as the ModelState that was defined by the failed Delete action.
spoon16
+14  A: 

Store your view data in TempData and retrieve it from there in your Index action, if it exists.

   ...
   if (!ModelState.IsValid)
       TempData["ViewData"] = ViewData;

   RedirectToAction( "Index" );
}

 public ActionResult Index()
 {
     if (TempData["ViewData"] != null)
     {
         ViewData = (ViewDataDictionary)TempData["ViewData"];
     }

     ...
 }

[EDIT] I checked the on-line source for MVC and it appears that the ViewData in the Controller is settable, so it is probably easiest just to transfer all of the ViewData, including the ModelState, to the Index action.

tvanfosson
ViewData.ModelState does not have a setter.
spoon16
ok. copy instead of set. didn't have access to VS to check it from home.
tvanfosson
you'll need to check the syntax of the copy function -- again, no VS at home.
tvanfosson
That works... Thanks! Wish there was a cleaner way to do this... maybe this is clean, but it seems like a common task that should be part of a RedirectToAction override or something.
spoon16
You could refactor it away to actionfilters, as suggested here (see bullet 13): http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx
Tomas Lycken
+6  A: 

Please note that tvanfosson's solution will not always work, though in most cases it should be just fine.

The problem with that particular solution is that if you already have any ViewData or ModelState you end up overwriting it all with the previous request's state. For example, the new request might have some model state errors related to invalid parameters being passed to the action, but those would end up being hidden because they are overwritten.

Another situation where it might not work as expected is if you had an Action Filter that initialized some ViewData or ModelState errors. Again, they would be overwritten by that code.

We're looking at some solutions for ASP.NET MVC that would allow you to more easily merge the state from the two requests, so stay tuned for that.

Thanks, Eilon

Eilon
+6  A: 

Use Action Filters (PRG pattern) (as easy as using attributes)

see item 13 -> link.

Also mentioned here.

bob
Best answer for this problem IMO.
Jean-Francois