Redirecting is very common operation in web programming, especially when you want to follow Post/Redirect/Get pattern. I strongly recommend to use this pattern because it’s very simple, avoids double-posting and tends to better separation of concerns. And how to implement this pattern in ASP.NET MVC? It’s very easy – just call RedirectToAction or RedirectToRoute method at the end of your action method that processes POST data.
When you are redirecting to another action then you often want to pass some data into target action, i.e. „Product has been successfully added.“ message. How to do this? Let’s dive into RedirectToAction and RedirectToRoute Controllers action methods. Result of all these methods is always instance of RedirectToRouteResult class. The most important member of this class is Values property which is instance of RouteValueDictionary. And it’s descendant of Dictionary<string, object> class.
So we can say that result of RedirectToAction and RedirectToRoute Controllers action methods is list of key-value pairs (keys are strings, values are objects) that will be used for URL construction using routing information (more accurately using GetVirtualPath method of Route class). When we are using default routing then we should specify „controller“ and „action“ keys. And this is exactly that what RedirectToAction does! It only adds these two values into RouteValueDictionary! It’s possible not to specify controller – then current will be used.
In addition to „controller“ and „action“ you can specify any values you want and they will be probably encoded into query string of generated URL. And these additional parameters is the right place for our „Product has been successfully added.“ message.
var values = new System.Web.Routing.RouteValueDictionary();
values.Add("message", "Product has been successfully added.");
return RedirectToAction("MyAction", "MyController", values);
You can see that there is lot of code…so we can use one small trick that is heavily used in ASP.NET MVC:
return RedirectToAction("MyAction", "MyController", new { message = "Product has been successfully added." });
Here we are using another overloaded version of RedirectToAction method that has object parameter instead of RouteValueDictionary parameter. Then properties of object will be used as keys and property values as values. This could be easily done in following manner (you don’t have to code this – it’s already done):
public void AddValues(object values)
{
if (values != null)
{
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(values))
{
this.Add(descriptor.Name, descriptor.GetValue(values));
}
}
}
Due to this small trick we can easily specify additional parameters that will be passed into target action where they can be used in any manner – so we can specify „message“ action method parameter, read this value using ValueProvider.GetValue(„message“), use this value in model-binding etc.
This solution works well almost everywhere because it depends on URL only. But there is one drawback – somebody can change URL to display another message. So there is better solution in ASP.NET MVC – TempData. TempData is the same collection as ViewData but TempData serves to passing data between two following requests. And this is what we want! But where are data stored? This can be configured via Controller.TempDataProvider property which has type ITempDataProvider. There are two main implementations of this interface – SessionTempDataProvider (standard) and CookieTempDataProvider (it’s suitable if we don’t want to enable sessions).
If we want to use some other temp-data-provider than SessionTempDataProvider then overrided Initialize method of Controller is very good place where we should assign instance of favorited temp-data-provider into TempDataProvider property.
So there are more possibilities how to pass data when redirecting. If you can use session then I recommend to use default SessionTempDataProvider. If you cannot use session but can use cookies then use CookieTempDataProvider. And if you cannot use session nor cookies then you can pass data in URL as I showed.
Hope it helps…
Can we pass objects rather than strings in RedirectToAction method.
something like this:
RedirectToAction(„actionSample“, new {Controller=“controllerName“, data=MyNewObject });
so that i can retrieve data from „MyNewObject“ in „actionSample“ action as following:
public ActionResults actionSample(MyClass data)
{
// data should now contains all values of „MyNewObject“
}
To se mi líbíTo se mi líbí