2

TempData in MVC 1.0

by volkanuzun 19. March 2010 23:40

    TempData is an interesting structure in MVC 1.0, and could be a little problematic if you don’t know the internals of it while using, so in MVC 2.0 TempData structure is changed. Today I want to analyze MVC 1.0’s TempData structure.

TempData is used to store information that will be consumed only once. A good example could be some information/error messages that will be passed to the view, and if the user refreshes the page, the message will be gone. For example:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Save(Order order)
{
    if(order.Validate()==false)
    {
        TempData["Msg"]="There are problems with order, please fix'em";
        return RedirectToAction("ValidationError");
    }
    //... some save to database action 
   TempData["Msg"]="Your order will be shipped ASAP";
  return RedirectToAction("OrderComplete");
}

As you can see in the code above, we are passing a message to one of the actions informing about the status of the order. If the user refreshes the page, TempData[“Msg”] will be cleared and the message will be gone. How does MVC 1.0 accomplish this? Basically, it stores the the value in the session, and after the roundtrip it deletes the value, but more technically:
If you open the MVC source code, and go to the Controller.cs file line 100, you will see that the controller has a member called TempDataProvider which is by default a SessionStateTempDataProvider. This provider implements an interface that has the below signature:

public interface ITempDataProvider {
  Dictionary<string, object> LoadTempData(ControllerContext controllerContext);
  void SaveTempData(ControllerContext controllerContext, 
IDictionary<string, object> values); }

So basically its job is to load or save a dictionary, and the SessionStateTempDataProvider is using the Session to load or save the dictionary. This dictionary is storing your temp values. 
Let’s check what SessionStateTempDataProvider LoadTempData does. The first thing the provider does is to get the dictionary from the controllercontext’s session. If the session does not return a value for the dictionary (in case you haven’t used the TempData in your code , then the session value is empty), then a new Dictionary<string,object> is instantiated and returned back to the caller.
If the session value has a value for the dictionary, then it is taken from the session, the session value is cleared, and dictionary is returned. After this point, there is no value for the dictionary in the session, so it is caller’s job to save the dictionary back to the session.
Here is the code from the mvc source code:

public virtual IDictionary<string, object> LoadTempData(ControllerContext 
controllerContext)
{ HttpContextBase httpContext = controllerContext.HttpContext; if (httpContext.Session == null) { throw new InvalidOperationException
(MvcResources.SessionStateTempDataProvider_SessionStateDisabled); } Dictionary<string, object> tempDataDictionary =
httpContext.Session[TempDataSessionStateKey] as Dictionary<string, object>; if (tempDataDictionary != null) { // If we got it from Session, remove it so that no other request gets it httpContext.Session.Remove(TempDataSessionStateKey); return tempDataDictionary; } else{ return new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); } }


SaveTempData is an easy operation, just take the passed the Dictionary and save it to the controllercontext’s session.  So far what we have seen is just a provider that stores a dictionary to the session, and reads a dictionary from the session. How does the controller use this provider to store and load the temp values? If you open the ControllerBase.cs file and go to line 21, you will see that the ControllerBase has a public property TempData of TempDataDictionary type. One of the problem is happening in this area. This dictionary has a Load and Save public functions, that uses SessionStateTempDataProvider (by default), to save and load the values. In order to do that, it uses 2 HashSets, one for the initial keys (the values that come back with the post back), the other HashSet is either for the keys that are newly added to the Dictionary or modified keys from the initial keys. By this way, the dictionary keeps track of who is added, who is supposed to be removed, who is updated.

The controller executes ExecuteCore() to invoke the action. The first line in this function is TempData.Load. This is where the controller asks the TempData dictionary to load the dictionary, and TempData dictionary uses SessionStateTempDataProvider to load the dictionary from the session. The last line of the ExecuteCore is TempData.Save which simply takes the dictionary back from the controller, uses SessionStateTempDataProvider and saves it to the session. Do not forget that the unmodified values are removed from the dictionary when the Save method is called.

What are the problems with this structure?
First of all TempData by default stores the dictionary in a session, and once it is read, it cleans the session. What if the user opens a new tab right before your TempData value is read by page? Session is shared between the tabs of the same browser, so TempData may lose the data in the session. The same problem may occur when there is an ajax call to the controller, or there is a redirecttoaction. Because of these problems MVC 2.0 has fixed some issues with TempData and we will look into the source for MVC 2.0 in a later posting.

Tags:

MVC

Comments

pingback
condosencinitas.com
5/10/2010 6:16:49 PM #

Pingback from condosencinitas.com

san diego car insurance

pingback
13.ja3ra.com
5/20/2010 10:21:38 AM #

Pingback from 13.ja3ra.com

Tsx Sale Dealers Acura Mdx, 2006 Acura Mdx Msrp

Comments are closed

Powered by BlogEngine.NET 1.6.0.0
Original Design by Laptop Geek, Adapted by onesoft