How to redirect a POST request to a url maintaining model values in MVC

余生颓废 提交于 2019-12-04 10:27:28

There are a couple of possibilities to implement the Redirect-After-Post pattern (which is what you are after here and which is a very good pattern IMHO) in ASP.NET MVC:

  1. Use TempData. In the POST action store the model inside TempData and redirect:

    TempData["model"] = model;
    return RedirectToAction("Search");
    

    and then inside the Search action check for TempData existence to fetch the model:

    PeopleGroupSearchModel model = TempData["model"] as PeopleGroupSearchModel;
    

    The drawback of this approach is that TempData is persisted only for a single redirect meaning that if the user hits F5 while on the Search GET action you are screwed. This could be alleviated by using Session instead. But of course Session introduces another problems of scalability. So I am not fan of this approach.

  2. Pass all properties on the request:

    return RedirectToAction("Search", new {
        prop1 = model.Prop1,
        prop2 = model.Prop2, 
        ....
    });
    

    Now when redirected to the Search GET action the Default model binder will be able to reconstruct the model. An obvious drawback of this approach is that if your model has many properties and even worse properties of complex types this could quickly become a cumbersome solution. You could probably serialize the model using some text format such as JSON as a query string parameter. Of course query string parameters are limited between different browsers so this could also be a no-no.

  3. Persist the model in some data storage and retrieve an unique id so that it can later be retrieved from this storage:

    int id = Persist(model);
    return RedirectToAction("Search", new { id = id });
    

    And then in the GET action retrieve the model from this very same persistence storage using the id. I like this approach and use it most of the time. If persisting to the aforementioned datastore is expensive you could use caching.

Mathias F

You can put the values you need to keep into ControllerContext.RouteData.Values

    public ActionResult TestRedirect()
    {
        RouteValueDictionary routeValues = ControllerContext.RouteData.Values;
        routeValues.Add("Key1","value1");
        routeValues.Add("Key2","value2");

        return RedirectToAction("TargetRedirect", routeValues);
    }

If you need something more generic you could loop through the postet form elements.

EDIT

It would look something like the top rated answer here: How do you persist querystring values in asp.net mvc?

This is probably a violation of MVC priciples, but once I stopped fighting the framework and just thought about what I was trying to do in HTTP-land, this simple solution works for me:

[HttpPost]
public ActionResult Search(PeopleGroupColumn filterField,
                           Operator filterOperator,
                           string filterValue)
{
    var collection =
        HttpUtility.ParseQueryString(Request.QueryString.ToString());
    collection.Set(filterField.ToString(), filterValue);
    collection.Set(filterField.ToString() + "_op", filterOperator.ToString());
    return new RedirectResult(
        Request.Url.AbsolutePath + "?" + collection.ToString());
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!