Monday 28 October 2013

Caching Techniques in ASP.NET

 

Introduction

This article is a beginner's tutorial on ASP.NET caching mechanism. We will try to see different types of caching available in ASP.NET and which caching technique is right for which scenario. We will also try to see how can we customize the caching behaviour so that it suits our needs.

 

Background

As ASP.NET web developers, we are mostly involved in developing web pages that are dynamic, i.e., contents coming from databases, Server directories, XML files or getting pulled from some other websites. Caching means to store something in memory that is being used frequently to provide better performance. Now can we think of the usability of caching in ASP.NET.

Let us imagine a scenario when the contents of a web page are being pulled from a database. The user asks for contents depending on some criteria. Now if the database is getting changed very frequently that even between two requests of same user, we anticipate database change, then we can in no way cache the data that the user is requesting. But if the database is not getting changed that frequently, we can have some caching in place so that if the user is requesting the same data very frequently, we don't hit the database every time (since we know contents are not changed).

The two keys terms here are frequency and criteria. Frequency is the number of times we are anticipating the user requests for a particular page and criteria is what governs the uniqueness of result that is being displayed on the page.

Frequency is important because we need to figure out the interval in which database is changing and compare it with the frequency of user requests so that we can have caching in place and also make sure that user is not viewing out dated data.

Criteria is important because we need to make sure that we have caching implemented for the page on every unique criteria. It should not be the case that user is requesting contents based on criteria01 and we are showing him the cached results of criteria00 (cached earlier for him).

So with all this theory in mind, let's go ahead and see how ASP.NET provides caching features without us writing a lot of code to manage the same.

 

Types of Caching

There are two types of caching available in ASP.NET:

1. Page Output Caching

2. Application Caching

 

 

Page Output Caching

Page output caching refer to the ability of the web server to cache a certain webpage after user request in its memory so that further requests for the same page will check for the cached page's validity and will not result in resource usage (DB access or file access) and the page will be returned to user from cache.

Now the question is how can we ensure that the user is not viewing the out dated data. ASP.NET provides us various configuration options which will let us program in such a way that we can ensure that the user never gets stale data.

Let us have a simple web page with a textbox, button and a label. Right now, the caching is not enabled for this page so everytime the postback occurs, the request to the web server is made. We can verify this by displaying the current time in the label.

 

protected void Page_Load(object sender, EventArgs e)

{
    Label1.Text = DateTime.Now.ToLongTimeString();
}
 

Now let us go ahead and enable caching for this page by adding the following declaration to the page:

 

<%@ OutputCache Duration="30" VaryByParam="none" %>
 

Here we are saying that this page should be cached for 30 seconds, We can verify this by pressing the button. The time string will not change for 30 seconds and the second property VaryByParam specifies that caching doesn't depend on anything doing so can lead to a situation where user can see stale data, like in our case for 30 seconds if we write something in textbox and do a postback, it will keep reverting to the old data that was in the textbox at the time page was cached.

 

clip_image004

 

So it's a good idea to say that the cached page is not valid if the data in textbox is changed so let's do that now:

 

 


<%@ OutputCache Duration="30" VaryByParam="TextBox1" %>
 

So now we can see that the page output will be cached as long as the contents of the textbox are not changed. If we change the contents of the textbox, then the server processes the page again and then caches it again.

 

clip_image006

 

So what we saw is that we can specify the Duration the page should be cached which is related to the talk about frequency we did earlier. The Duration should be chosen so that during that time we are not expecting any change in data and for the criteria, we saw how we can use VaryByCustom to make sure that the output for every different criteria is generated and the cached copy is not just presented to the user.


Let us look as some other parameters that we can use to customize caching behavior.

· VaryByParam: List of strings that are sent to server via POST that are checked to validate cache

· VaryByControl: List of controls whose value will determine the validity of cache

· SqlDependency: Defines the Database-tablename pair on which the validity of cache depends

· VaryByCustom: Used for custom output cache requirements

· VaryByHeader: HTTPs header that determines the cache validity

 


If we need different output pages based on query string, then we can specify the list of querystring parameters here or we can simply say VaryByParam ="*" to do the same for all querystring parameters. Now let us just have a quick look at what we need to do if we need to change the cached page based on query string parameter.

 

<%@ OutputCache Duration="30" VaryByParam="name" %>
 
protected void Button2_Click(object sender, EventArgs e)
{
    int name;
    if (Request.QueryString["name"] == null)
    {
        name = 1;
    }
    else
    {
        name =  Convert.ToInt32(Request.QueryString["name"]) + 1;
    }
    Response.Redirect("varybyqs.aspx?name=" + name.ToString());
}
 
 

clip_image008


 

 

 

In order to cache a page's output, we need to specify an @OutputCache directive at the top of the page. The syntax is as shown below:


<%@ OutputCache Duration=5  VaryByParam="None" %>

 


As you can see, there are two attributes to this directive. They are:


  • Duration - The time in seconds of how long the output should be cached. After the specified duration has elapsed, the cached output will be removed and page content generated for the next request. That output will again be cached for 10 seconds and the process repeats.
  • VaryByParam - This attribute is compulsory and specifies the querystring parameters to vary the cache.

    In the above snippet, we have specified the VaryByParam attribute as None which means the page content to be served is the same regardless of the parameters passed through the querystring [see Example 1 in the sample download].

    If there are two requests to the same page with varying querystring parameters, e.g.: .../PageCachingByParam.aspx?id=12 and .../PageCachingByParam.aspx?id=15] and separate page content is generated for each of them, the directive should be:

     

    <%@ OutputCache Duration=5 VaryByParam="id" %>

    The page content for the two requests will each be cached for the time specified by the Duration attribute [see Example 2 in the sample download].

    To specify multiple parameters, use semicolon to separate the parameter names. If we specify the VaryByParam attribute as *, the cached content is varied for all parameters passed through the querystring.


Some pages generate different content for different browsers. In such cases, there is provision to vary the cached output for different browsers. The @OutputCache directive has to be modified to:

 

<%@ OutputCache Duration=5 VaryByParam="id" VaryByCustom="browser" %>
 

This will vary the cached output not only for the browser but also its major version. I.e., IE5, IE 6, Netscape 4, Netscape 6 will all get different cached versions of the output.

 

 

 

Partial Page Caching (or) Fragment Caching


Sometimes we might want to cache just portions of a page. For example, we might have a header for our page which will have the same content for all users. There might be some text/image in the header which might change everyday. In that case, we will want to cache this header for a duration of a day.


The solution is to put the header contents into a user control and then specify that the user control content should be cached. This technique is called fragment caching.

To specify that a user control should be cached, we use the @OutputCache directive just like we used it for the page.

 



<%@ OutputCache Duration=10  VaryByParam="None" %>
 

With the above directive, the user control content will be cached for the time specified by the Duration attribute [10 secs]. Regardless of the querystring parameters and browser type and/or version, the same cached output is served. [See Example 3 in the download for a demonstration].

Similar to output caching, partial page caching allows you to cache certain blocks of your website. You can, for example, only cache the center of the page. Partial page caching is achieved with the caching of user controls. You can build your ASP.NET pages consisting of numerous user controls and then apply output caching on the user controls you select. This will cache only parts of the page that you want, leaving other parts of the page outside the reach of caching. This is a very nice feature, and if done correctly, it can lead to pages that perform better.


Note: Typically, UserControls are placed on multiple pages to maximize reuse. However, when these UserControls (ASCX files) are cached with the @OutputCache directive, they are cached on a per page basis. That means even if a User Control outputs identical HTML when placed on pageA.aspx as it does when placed on pageB.aspx, its output is cached twice. You can prevent this happening by adding Shared = true in the output cache directive.

 

<%@ OutputCache Duration="300" VaryByParam="*" Shared="true" %>
 

By putting the Shared attributed, the memory savings can be surprisingly large. If you have an ASCX User control using the OutputCache directive, remember that the User Control exists only for the first request.

 


Also, if we have a requirement for partial page caching (Fragment caching), we can simply use the controls that require caching and put them in a user control. We can then use the same above mentioned technique to enable caching behaviour in the custom control and we have partial page caching in place. (See the code for implementation.)

 

clip_image010

Note: The above mentioned approaches enabled us to use caching by using declarations on the page. We can also control caching programmatically.

 

 

Application Data Caching


Output caching and partial page caching is useful if you want to cache the output of a page. However, if you like to cache a DataSet object or any collection object, you can use data caching to implement that.


ASP.NET has a class called Cache to cache specific data items for later use on a particular page or group of pages. The Cache enables you to store everything from simple name/value pairs to more complex objects like datasets and entire aspx pages.

 


          To store data into the cache, you can use the code below:


    C#

    Cache["MyDataSet"] = myDataSet;

     

    To retrieve data from the cache, you can use the code below:

    C#

    DataSet ds = new DataSet();
    ds = (DataSet) Cache["MyDataSet"];


 


Application data caching is a mechanism for storing the Data objects on cache. It has nothing to do with the page caching. ASP.NET allows us to store the object in a Key-Value based cache. We can use this to store the data that need to cached. Let us work on the same example and try to store the DateTime object in the Application Cache now.

 

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack == false)
    {
        Cache["time"] = DateTime.Now;
    }
 
    Label1.Text = ((DateTime)Cache["time"]).ToLongTimeString();
}

 

What this code will do is that it will store the DateTime object in application cache and will keep displaying the time of initial request by using the object from the cache.

 

clip_image012

 

 


There are various parameters associated with application data caching that can be used to control its behavior.

· Dependencies: Any file or item in cache that invalidates this cache item

· absoluteExpiration: Absolute time when this object should be removed from cache

· slidingExpiration: Relative time when this object should be removed from the cache

· priority: Defines the priority of the item. This is useful when server runs out of memory as in that case it start removing items from cache with lowest priority first

· onRemoveCallBack: This is the event handler that will be called when the object is removed from cache. It gives us a place to take further actions.


 

 

Understanding Asp.net Cache Sliding Expiration and Absolute Expiration


 


Asp .Net provides two different ways to expire the cache on the basis of time. Here are two approaches:-

 


  1. Sliding Expiration
  2. Absolute Expiration 

 


1. Absolute Expiration



Absolute expiration means that your data will be removed from cache after fixed amount of time either it is accessed or not. Generally we use it when we are displaying data which is changing but we can afford to display outdated data in our pages.  Mostly I put all of my dropdown values in cache with Absolute Expiration. Here is how you can code:-


DataTable dt = GetDataFromDatabase();

Cache.Insert("AbsoluteCacheKey", dt, null,

DateTime.Now.AddMinutes(1), //Data will expire after 1 minute

System.Web.Caching.Cache.NoSlidingExpiration);

 

2. Sliding Expiration



Sliding expiration means that your data will be removed from cache if that is not accessed for certain amount of time. Generally we store that data in this cache mode which is accessed many time on certain occasions. For example if you go in account settings section of a site, then you will be frequently accessing account information in that section. But most of the time you wont be using account setting's related data so there is no point of storing that data in cache. In such scenarios sliding expiration should be used. here is how you can save data in cache with sliding expiration:-


DataTable dt = GetDataFromDatabase();

Cache.Insert("SlidingExpiration", data, null,

System.Web.Caching.Cache.NoAbsoluteExpiration,

TimeSpan.FromMinutes(1));//Data will be cached for 1 mins


Blogger Labels: Techniques,Introduction,article,beginner,tutorial,mechanism,technique,scenario,behaviour,Background,developers,databases,Server,memory,performance,database,user,criteria,data,frequency,interval,theory,Types,Page,Output,Application,resource,usage,configuration,options,Page_Load,sender,EventArgs,Text,DateTime,declaration,OutputCache,Duration,VaryByParam,Here,situation,VaryByCustom,parameters,List,POST,VaryByControl,SqlDependency,Defines,custom,requirements,VaryByHeader,header,parameter,Request,Convert,Response,Redirect,directive,syntax,snippet,Example,PageCachingByParam,Some,provision,version,Netscape,versions,Partial,Fragment,Sometimes,users,solution,Similar,Note,UserControls,ASCX,basis,Control,outputs,HTML,savings,Also,requirement,implementation,declarations,DataSet,collection,Cache,items,MyDataSet,Value,IsPostBack,Dependencies,item,Absolute,Relative,event,handler,Expiration,DataTable,GetDataFromDatabase,Insert,AbsoluteCacheKey,AddMinutes,System,NoSlidingExpiration,mode,account,settings,information,scenarios,SlidingExpiration,NoAbsoluteExpiration,TimeSpan,FromMinutes,textbox,postback,behavior,aspx,browsers,browser

No comments:

Post a Comment