In the RedirectToAction
below, I'd like to pass a viewmodel
. How do I pass the model to the redirect?
I set a breakpoint to check the values of model to verify the model is created correctly. It is correct but the resulting view does not contain the values found in the model properties.
// // model created up here... // return RedirectToAction("actionName", "controllerName", model);
ASP.NET MVC 4 RC
When a Button is clicked, the Model object is populated with values and passed to the RedirectToAction method along with the name of the Controller and its Action method in ASP.Net MVC Razor.
Adding a Model Class In the MVC application in Visual Studio, and right-click on the Model folder, select Add -> and click on Class... It will open the Add New Item dialog box. In the Add New Item dialog box, enter the class name Student and click Add. This will add a new Student class in model folder.
RedirectToAction
returns a 302 response to the client browser and thus the browser will make a new GET request to the url in the location header value of the response came to the browser.
If you are trying to pass a simple lean-flat view model to the second action method, you can use this overload of the RedirectToAction
method.
protected internal RedirectToRouteResult RedirectToAction( string actionName, string controllerName, object routeValues )
The RedirectToAction
will convert the object passed(routeValues) to a query string and append that to the url(generated from the first 2 parameters we passed) and will embed the resulting url in the location header of the response.
Let's assume your view model is like this
public class StoreVm { public int StoreId { get; set; } public string Name { get; set; } public string Code { set; get; } }
And you in your first action method, you can pass an object of this to the RedirectToAction
method like this
var m = new Store { StoreId =101, Name = "Kroger", Code = "KRO"}; return RedirectToAction("Details","Store", m);
This code will send a 302 response to the browser with location header value as
Store/Details?StoreId=101&Name=Kroger&Code=KRO
Assuming your Details
action method's parameter is of type StoreVm
, the querystring param values will be properly mapped to the properties of the parameter.
public ActionResult Details(StoreVm model) { // model.Name & model.Id will have values mapped from the request querystring // to do : Return something. }
The above will work for passing small flat-lean view model. But if you want to pass a complex object, you should try to follow the PRG pattern.
PRG stands for POST - REDIRECT - GET. With this approach, you will issue a redirect response with a unique id in the querystring, using which the second GET action method can query the resource again and return something to the view.
int newStoreId=101; return RedirectToAction("Details", "Store", new { storeId=newStoreId} );
This will create the url Store/Details?storeId=101
and in your Details GET
action, using the storeId passed in, you will get/build the StoreVm
object from somewhere (from a service or querying the database etc)
public ActionResult Details(string storeId) { // from the storeId value, get the entity/object/resource var store = yourRepo.GetStore(storeId); if(store!=null) { // Map the the view model var storeVm = new StoreVm { Id=storeId, Name=store.Name,Code=store.Code}; return View(storeVm); } return View("StoreNotFound"); // view to render when we get invalid store id }
Following the PRG pattern is a better solution to handle this use case. But if you don't want to do that and really want to pass some complex data across Stateless HTTP requests, you may use some temporary storage mechanism like TempData
TempData["NewCustomer"] = model; return RedirectToAction("Index", "Users");
And read it in your GET
Action method again.
public ActionResult Index() { var model=TempData["NewCustomer"] as Customer return View(model); }
TempData
uses Session
object behind the scene to store the data. But once the data is read the data is terminated.
Rachel has written a nice blog post explaining when to use TempData /ViewData. Worth to read.
In Asp.Net core, you cannot pass complex types in TempData. You can pass simple types like string
, int
, Guid
etc.
If you absolutely want to pass a complex type object via TempData, you have 2 options.
1) Serialize your object to a string and pass that.
Here is a sample using Json.NET to serialize the object to a string
var s = Newtonsoft.Json.JsonConvert.SerializeObject(createUserVm); TempData["newuser"] = s; return RedirectToAction("Index", "Users");
Now in your Index
action method, read this value from the TempData and deserialize it to your CreateUserViewModel
class object.
public IActionResult Index() { if (TempData["newuser"] is string s) { var newUser = JsonConvert.DeserializeObject<CreateUserViewModel>(s); // use newUser object now as needed } // to do : return something }
2) Set a dictionary of simple types to TempData
var d = new Dictionary<string, string> { ["FullName"] = rvm.FullName, ["Email"] = rvm.Email; }; TempData["MyModelDict"] = d; return RedirectToAction("Index", "Users");
and read it later
public IActionResult Index() { if (TempData["MyModelDict"] is Dictionary<string,string> dict) { var name = dict["Name"]; var email = dict["Email"]; } // to do : return something }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With