views:

306

answers:

3

Currently I am using ViewData or TempData for object persistance in my ASP.NET MVC application.

However in a few cases where I am storing objects into ViewData through my base controller class, I am hitting the database on every request (when ViewData["whatever"] == null).

It would be good to persist these into something with a longer lifespan, namely session. Similarly in an order processing pipeline, I don't want things like Order to be saved to the database on creation. I would rather populate the object in memory and then when the order gets to a certain state, save it.

So it would seem that session is the best place for this? Or would you recommend that in the case of order, to retrieve the order from the database on each request, rather than using session?

Thoughts, suggestions appreciated. Thanks Ben

A: 

You can serialize what you wish to persist and place it in a hidden input field like ViewState in WebForms.

Here's an article that should get you started: http://weblogs.asp.net/shijuvarghese/archive/2010/03/06/persisting-model-state-in-asp-net-mvc-using-html-serialize.aspx

mark123
This doens't really help me as this is no different to using ViewData. I have asked about persisting objects and making available to entire application. Also I am using MVC, not web forms.
Ben
Yes, the article I posted deals with persisting data in MVC. It's useful where you want to have a wizard type control in MVC, such as order processing.
mark123
Yes I could use this in a wizard type scenario. However, it is important that should a customer navigate away from the ordering process, that the model is retained. For this, I need to use session.
Ben
+3  A: 

I believe this is what Session was designed for - to temporarily store session specific data.

However, due to increased complexity connected with using the Session, even if negligible - in my own ASP.NET MVC project, I have decided to hit the database on every Order creation step page (only ID is passed between the steps). I am ready to optimize and start using session as soon as I will see that the extra database hit for every request is a performance bottleneck.

Marek
Exactly. No need to reinvent the wheel.
TomTom
Great, thanks. I had the same performance concerns. I'm using the state pattern for orders so can add a property to my states to determine if changes should be persisted to database or not.
Ben
+1  A: 

Just thought I would share how I am using session in my application. I really like this implementation (http://stackoverflow.com/questions/2213052/suggestions-for-accessing-asp-net-mvc-session-data-in-controllers-and-extension/2213232#2213232) of using session as it makes it easy to swap out session for another store or for testing purposes.

Looking at the implementation it reminded me of the ObjectStore I have used in other projects to serialize objects as binary or xml and store in a database or on the filesystem.

I therefore simplified my interface (previously T had to be a class) and came up with the following:

public interface IObjectStore {
    void Delete(string key);
    T Get<T>(string key);
    void Store<T>(string key, T value);
    IList<T> GetList<T>(string key);
}

And my session store implementation:

public class SessionStore : IObjectStore
{      
    public void Delete(string key) {
        HttpContext.Current.Session.Remove(key);
    }

    public T Get<T>(string key) {
        return (T)HttpContext.Current.Session[key];
    }

    public void Store<T>(string key, T value) {
        HttpContext.Current.Session[key] = value;
    }

    public IList<T> GetList<T>(string key) {
        throw new NotImplementedException();
    }
}

I then take in an IObjectStore in my base controller's constructor and can then use it like so to expose properties to my other controllers:

   public string CurrentCustomer {
        get {
            string currentCustomer = 
                sessionStore.Get<string>(SessionKeys.CustomerSessionKey);
            if (currentCustomer == null) {
                currentCustomer = Guid.NewGuid().ToString();
                sessionStore.Store<string>(SessionKeys.CustomerSessionKey, currentCustomer);
            }
            return currentCustomer;               
        }
    }

Am quite pleased with this approach.

Ben