Passing data from one controller
Passing data from one controller to another in ASP.NET MVC
At times you need to pass data from an action method belonging to one
controller to an action method belonging to another controller. There are three
ways to accomplish this task. They are:
- Pass data as query string parameters
- Pass data in TempData dictionary
- Pass data as route parameters
Let's quickly see how each of these three approaches work.
Pass data as query string parameters
This approach is possibly the most primitive one and involves no special
consideration from your side. The action method sending the data can use
Redirect() method or RedirectToAction() method to transfer the control to the
receiving action method. The following code shows how this is done:
public ActionResult Index()
{
Customer data = new Customer()
{
CustomerID = 1,
CustomerName = "Abcd",
Country = "USA"
};
string url=string.Format("/home2/index?customerid={0}
&customername={1}&country={2}",
data.CustomerID,data.CustomerName,data.Country);
return Redirect(url);
}
The above code shows Index() action from Home1 controller. The Index action
method instantiates Customer object - the model class - that looks like this:
public class Customer
{
public int CustomerID { get; set; }
public string CustomerName { get; set; }
public string Country { get; set; }
}
It then forms a URL pointing to the Index() action from Home2 controller.
Notice how data from Customer object is transferred in the form of query string
parameters. In the above example there is no logic for generating model data but
in a more realistic case you may have such a logic in this method. And once the
data is generated you can pass it to the another controller using query string.
The Redirect() method then takes the control to the Index() action of Home2
controller.
The Index() action of Home2 can receive the data as shown below:
public ActionResult Index()
{
Customer data = new Customer();
data.CustomerID = int.Parse(Request.QueryString["CustomerID"]);
data.CustomerName = Request.QueryString["CustomerName"];
data.Country = Request.QueryString["Country"];
return View(data);
}
As you can see Request.QueryString collection is being used to read the
values passed in the query string. Once a Customer object is formed, it is
passed to the Index view.
This technique has an advantage that it is quite simple and requires no
additional configuration. However, it's bit crude technique and you should avoid
it if any of the other techniques can be used.
Pass data using TempData dictionary
In this technique you store the data to be passed in the TempData dictionary
in the sender action method. The receiving action method reads the data from the
TempData dictionary. You might be aware that TempData dictionary can hold data
till it is read and this can carry data across multiple requests. The following
code shows how this is done:
public ActionResult Index()
{
Customer data = new Customer()
{
CustomerID = 1,
CustomerName = "Abcd",
Country = "USA"
};
TempData["mydata"] = data;
return RedirectToAction("Index", "Home2");
}
As you can see Index() action instantiates a Customer object as before. This
time, however, it stores the Customer object in a TempData key named mydata. The
RedirectToAction() method is then used to take the control to the Index() action
of Home2 controller.
Inside the Index() of Home2, you can read the value as follows:
public ActionResult Index()
{
Customer data = TempData["mydata"] as Customer;
return View(data);
}
The above code reads the Customer object from TempData dictionary and passes
it to the Index view.
The TempData technique doesn't require any additional setup but it requires
that session state be enabled. Also, TempData is designed to store arbitrary
pieces of data. If you are planning to send model objects through TempData, that
may be a deviation from standard design practices.
Pass data as route parameters
In this technique you need to do an additional work of defining a route in
the system. For example, if you wish to pass the Customer data in the form of
route parameters you need to define a route like this:
routes.MapRoute(
name: "Default2",
url: "{controller}/{action}/
{customerid}/{customername}/{country}",
defaults: new { controller = "Home2", action = "Index" }
);
As shown above, the route includes {customerid}, {customername}, and
{country} route parameters and the route is mapped with Index() action of Home2
controller. Once the above configuration is done you can pass data from the
sender action as follows:
public ActionResult Index1()
{
Customer data = new Customer()
{
CustomerID = 1,
CustomerName = "Abcd",
Country = "USA"
};
return RedirectToAction("Index", "Home2", data);
}
Notice that, this time the Customer object is passed as the third parameter
of RedirectToAction() method. This way Customer data will be passed in the form
of route parameter values. To receive this data the receiver action method
should write something like this:
public ActionResult Index()
{
Customer data = new Customer();
UpdateModel(data);
return View(data);
}
// OR
public ActionResult Index(Customer data)
{
return View(data);
}
As shown above you can either use UpdateModel() method to transfer values
from the route to the Customer object or you can have a parameter to the Index()
action method.
This technique is quite clean and makes use of MVC specific parts (route and
route parameters). It doesn't have any dependency on session state as in the
case of TempData technique. On the other hand you need to create a route to deal
with the route parameters.
Note about query string and route parameters
Before I conclude this post, it would be interesting to see a small thing
about how RedirectToAction() deals with query string and route parameters.
Let's assume that your sender action is like this:
public ActionResult Index()
{
Customer data = new Customer()
{
CustomerID = 1,
CustomerName = "Abcd",
Country = "USA"
};
return RedirectToAction("Index", "Home2", data);
}
Notice that RedirectToAction() method passes Customer data object to Index()
of Home2 as the third parameter.
The interesting thing to note is - If you haven't defined any route to match
the data MVC sends it as query string. And if you have defined a route, it
passes the values as route parameters. You can confirm this by observing the
browser address bar once the Index() of Home2 renders the view. The following
figure shows the difference:
That also means in the query string technique discussed earlier, you could
have used exactly same code in the receiving action as in the case of route
parameter technique.
In addition to the three techniques discussed above you can also use Session
object but that's not discussed here separately since TempData technique anyway
depends on the session storage.
That's it for now. Keep coding!