7

I am trying to store a complex object in Viewstate to avoid calling it everytime on page load. I do understand that it needs to be serialized in order to be saved and retrived from Viewstate which means my class should be marked as [Serializable]

It's a fairly complex entity and basically i wish to avoid marking every class as Serializable as it may effect my other dependencies used for mapping.

Class Article
{
    Albums albumList { get; set; }
    Authors authorList { get; set; }
    ...
}

Is it even possible and is there any possible way out to save and retrieve the viewstate Object without Serializing?

Sangram Nandkhile
  • 17,634
  • 19
  • 82
  • 116
  • What about an in-memory cache? You can store there _live_ objects. – Adriano Repetti Nov 19 '15 at 12:29
  • 1
    You can wrap your class in a wrapper class that implements ISerializable, and then you can implement it however you like without marking the various dependent classes as Serializable. That said -- it has been my experience that it is best to reduce the size of the viewstate to the greatest extent possible. If you're putting a potentially large object into the viewstate, it is being sent to clients and then they post it back on *every* request/response. This is almost always less efficient than the alternative options. – mikey Nov 19 '15 at 12:34
  • i'll avoid cache for some unavoidable reasons. Thanks anyways! – Sangram Nandkhile Nov 19 '15 at 15:05

4 Answers4

4

It seems to me from your use case that "to avoid calling it everytime on page load" screams for cache. I think if you want it to expire maybe set some dependencies, it might work better than session (we don't know all the details).

Now, you can probably use json.net which can help you serialize your info without changing your objects. Just don't abuse viewstate, it can get nasty really fast if you let it grow. Using either session or cache (if it fits your needs) is something that can scale better in the long run.

If this is a display thing, also take a look at Output cache as maybe you can separate your repeated content in a user control or something.

All being said, I wanted to add a little example of what you actually asked using JSON.net (example stolen from them):

//Doesnt need to be marked as serializable
Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Sizes = new string[] { "Small" };
//Use this string to save into view state
string json = JsonConvert.SerializeObject(product);
ViewState["something"]=json;

After that, get the string back from ViewState[something] and deserialize it.

string json = (string)ViewState["something"];
Product m = JsonConvert.DeserializeObject<Product>(json);

Warning, code written without compiling it.

Community
  • 1
  • 1
Ernesto
  • 1,523
  • 1
  • 14
  • 32
1

You can use ASP.NET Session object instead (this avoids the serialization route, because everything in Session is stored as an Object), like this:

var theArticle = new Article();

Session["MyArticle"] = theArticle;

Everything in Session is stored as an object so when you retrieve the Article object, then you need to cast it to an Article, like this:

var myArticleFromSession = Session["MyArticle"] as Article;

Note: It is recommended to put in checks to see if the Session key actually exists before attempting to access the value, like this:

if(Session["MyArticle"] != null)
{
    // The key MyArticle exists, so it is safe to attempt to get the object value
    var myArticleFromSession = Session["MyArticle"] as Article;

    // Since we used as to attempt the cast, 
    // then myArticleFromSession will be null if the cast failed 
    // so check for null before using myArticleFromSession
    if(myArticleFromSession != null)
    {
        // Use myArticleFromSession here

    }
}
Karl Anderson
  • 34,606
  • 12
  • 65
  • 80
  • Thanks for your answer Karl. I had given a try to store and retrieve it using Session but unfortunately it is returning NULL object. Though I've done this before and I've seen it working but unfortunately didn't work in this case. – Sangram Nandkhile Nov 19 '15 at 15:01
0

Serialization should be avoided, if possible, because it is relatively slow (doesn't scale well).

If you are looking to cache a specific object between postbacks or across pages, use the ASP.NET Session object for session-specific caching, the Application object for site-wide caching, or use the System.Web.Caching.Cache for your own custom caching behavior. You can also cache the output of ASP.NET pages or parts of pages. More info here: ASP.NET Caching

But if you are looking to cache the whole page's viewstate, there is the option of server-side viewstate persistence. You will need to create a new BasePage in this case. For example, this is quite helpful when browsers limit the size of very large viewstates. You can get more information on this approach here: Server Side Viewstate

Special Sauce
  • 5,338
  • 2
  • 27
  • 31
0

Another possible solution is you can map all the non required properties as [NonSerialized] so that only required once will be used. I had the similar issue and went with this option.

So suppose in the above example you want Albums but not Artists then your class will become as below

[Serializable]
Class Article
{
    Albums albumList { get; set; }

    [NonSerialized]
    Authors authorList { get; set; }
    ...
}
Chaitanya Gadkari
  • 2,669
  • 4
  • 30
  • 54