I'm new to ASP.NET MVC. After working with traditional ASP.NET model for so long, it's taking some time for me to get to understand this model.
I am going through NerdDinner to understand how things work.
So, I have an object that needs to be passed through couple of views. Similar to the article NerdDinner Step 6: ViewData and ViewModel.
I retain the data from Get to Post for the first time, then I put it in TempData and pass it to another action (AnotherAction). Once I get my data on Get I cannot retain it on Post.
Here's my code:
public class DinnerFormViewModel
{
public Dinner Dinner { get; private set; }
public DinnerFormViewModel(Dinner dinner)
{
Dinner = dinner;
}
}
public class DinnersController : Controller
{
public ActionResult Action()
{
Dinner dinner = new Dinner();
return View(new DinnerFormViewModel(dinner));
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Action(Dinner dinner, FormCollection collection)
{
try
{
// Some code
TempData["Dinner"] = dinner;
return RedirectToAction("AnotherAction");
}
catch
{
return View();
}
}
public ActionResult AnotherAction()
{
Dinner dinner = (Dinner)TempData["Dinner"]; // Got my dinner object
return View(new DinnerFormViewModel(dinner));
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AnotherAction(Dinner dinner, FormCollection collection)
{
// Lost my dinner object, dinner comes in as null
}
}
According to this blog post TempData is only around for 1 single request after its set.
Here is a quote from the post:
If you set TempData and your action then returns a ViewResult, then the next request, whatever it happens to be (an AJAX request, another page the user opened in a different tab, etc.), is going to see the TempData value you set, and no other request will see it.
So given the code that I'm seeing, you can get the dinner from TempData on the get from AnotherAction
which is the first request after you set it on Action
. However looking at the code and not seeing the code for view for AnotherAction
it is unclear how you are passing the data to the post for AnotherAction
. The dinner instance is not going to be in TempData for that request because it's the second request after you set it in TempData. And if you do not have the proper form tags set on the AntoherAction
view the framework will not have the proper form values to instantiate a dinner object in the post.
So either you'll have to reset TempData with the dinner instance it the first AnotherAction
call and then retrieve the dinner out of TempData in the post AnotherAction
, or you can follow the advice of dm and use hidden fields in your view.
IMO, you should use DMs way of doing this and avoid using TempData.
Edit Added example of reseting the TempData in AnotherAction to get access to it in the post.
Model:
public class Dinner
{
public string Name{get;set;}
}
public class DinnerFormViewModel
{
public Dinner Dinner {get;private set;}
public DinnerFormViewModel( Dinner dinner )
{
Dinner = dinner;
}
}
Controller:
public class DinnersController : Controller
{
public ActionResult Action()
{
Dinner dinner = new Dinner();
return View( new DinnerFormViewModel( dinner ) );
}
[AcceptVerbs( HttpVerbs.Post )]
public ActionResult Action( Dinner dinner, FormCollection collection )
{
try
{
// Some code
TempData[ "Dinner" ] = dinner;
return RedirectToAction( "AnotherAction" );
}
catch
{
return View();
}
}
public ActionResult AnotherAction()
{
Dinner dinner = ( Dinner )TempData[ "Dinner" ]; // Got my dinner object
TempData[ "Dinner" ] = dinner; // Reset the dinner object in temp data
return View( new DinnerFormViewModel( dinner ) );
}
[AcceptVerbs( HttpVerbs.Post )]
public ActionResult AnotherAction( Dinner dinnerFromPostedFormValues, FormCollection collection )
{
//dinnerFromPostedFormValues is null
var dinnerFromTempData = TempData[ "Dinner" ] as Dinner; // Got my dinner object
return View( "Action", new DinnerFormViewModel( dinnerFromTempData ) );
}
}
Action View:
<h2>Action</h2>
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Fields</legend>
<p>
Name: <%= Html.TextBox("Name", Model.Dinner.Name ) %>
</p>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
AnotherAction View:
<h2>AnotherAction</h2>
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Fields</legend>
<p>
Name:
<%= Html.Encode(Model.Dinner.Name) %>
</p>
<p>
<input type="submit" value="Do Something" />
</p>
</fieldset>
<% } %>