Wednesday, September 22, 2010

Partial-Page Output Caching

Partial-Page Output Caching

1. Create a new website

2. Switch to design mode on the default aspx page.

3. Insert a table with 4 rows, 2 columns.

4. Type “Time Now:” in first column of row 1.

5. Add a Label control to the second column of row1.

6. Create a custom label control

1. Create a folder controls in the solution explorer

2. Right click on the controls folder and select Add-> new item.

3. Select Web User Control and name it customLabel

4. Get rid of the code behind files.

5. Open CustomLael.ascx file

6. Drop label control in the design mode and Type in this script and OutputCache directive in to the file

<%@ Control Language="C#" ClassName="customLabel" %>

<%@ OutputCache Duration="6" VaryByParam="*" %>

<script runat="server">

protected void Page_Load(object sender, EventArgs e)

{

Label1.Text = System.DateTime.Now.ToString("hh:mm:ss");

}

script>

<div>

<asp:Label ID="Label1" runat="server" Text="Label1">asp:Label>

div>

7. Drag and drop this control into second row second column of the table in default aspx page.

8. Type “Page attribute for control:” in the second row first column.

9. Create another custom control in the controls folder and name in customLabel1 but this time do not delete code behind files

1. Drop a label control into the file

2. In the code behind add the PartialCaching attribute and label text value.

[PartialCaching(12)]

public partial class customLabel1 : System.Web.UI.UserControl

{

protected void Page_Load(object sender, EventArgs e)

{

Label1.Text = DateTime.Now.ToString("hh:mm:ss");

}

}

10. Drag and drop this control into third row second column of the table in default aspx page.

11. Type “Class attribute for control:” in the third row first column.

12. Compile and execute.

13. You will notice that every time your refresh, the first label control updates but the second label control updates every 6 seconds and third label control updates every 12 seconds.

14. Now add a page level directive on the default aspx page

<%@ OutputCache Duration="3" VaryByParam="*" %>

15. Save and execute. You will notice that the first label control updates every 3 seconds, the second label control updates every 6 seconds and third label control updates every 12 seconds.

16. Sometimes will need to create areas on the page that can be updated dynamically and then integrated into a cached page. If you have a chunk of code or a method that you want to execute irrespective what the page level cache is set for, there is a new control called Substitution control to do that.

Use the Substitution control to specify a section of an output-cached Web page where you want to display dynamic content. The Substitution control offers a simplified solution to partial page caching for pages where the majority of the content is cached. You can output-cache the entire page, and then use Substitution controls to specify the parts of the page that are exempt from caching. Cached regions execute only once and are read from the cache until the cache entry expires or is purged. Dynamic regions execute every time that the page is requested. This caching model simplifies the code for pages that are primarily static, because you do not have to encapsulate the sections to cache in Web user controls. For example, this caching model is useful in a scenario where you have a page that contains static content, such as news stories, and an AdRotator control that displays advertisements. The news stories do not change frequently, which means that they can be cached. However, every time that a user requests the page, you want to display a new advertisement. The AdRotator control directly supports post-cache substitution and renders a new advertisement every time that the page posts back, regardless of whether the page is cached.

17. In the fourth row second column drag and drop the substitution control. Click on properties and type GetRealTime for MethodName property.

18. In the fourth row first column type “Substitution control:”

19. Switch to source mode and at the top of the page add this script

<script runat="server">

private static string GetRealTime(HttpContext context)

{

return "Uncached time is " + DateTime.Now.ToString();

}

script>

20. Save and execute. You will notice that the time changes for every refresh in the substitution control while the first three label controls refresh every 3, 6, and 12 seconds respectively.

ASP.Net - How to make use of Caching?



How to make use of Caching?
Step 1: Basic sample with date output.
1. Create a new web project.
2. Add <%Response.Write(System.DateTime.Now); %> between div tags
Add this special directive after the page directive
<%@ OutputCache Duration="20" VaryByParam="*" %>.
The cache duration here is 20 seconds. VarByParam=”*” applies the caching to every page irrespective of the query string that is passed in. Now if you open the page in the browser, you will notice that the page doesn’t get updated if you refresh within 20 seconds of the last refresh. This is page level output caching.
Step 2 : Let’s take it a step higher by connecting our system to the database and use Database Caching.
1. Add the connection string to web.config file
<configuration>
<connectionStrings>
<add name="NW"
connectionString="data source=devserver;Initial Catalog=devdb;User ID=sa;Password=hello" providerName="System.Data.SqlClient" />
connectionStrings>
2. Add this to the webForm1.aspx page
<div>
<%Response.Write(System.DateTime.Now); %>
<asp:SqlDataSource ID="ds1" runat="server" ConnectionString="<%$ConnectionStrings:NW %>" SelectCommand="Select * from dbo.Customer" />
<asp:DataGrid ID="dg1" runat="server" DataSourceID="ds1" />
div>
Now if you refresh the webpage, it displays the table and it does not make a query back to the database within the 20 seconds of the last refresh. You can see this by opening sql profiler and enabling it. You will notice in the sql profiler that there is no database traffic going back to the system. You have to wait for 20secs to elapse and there is our query in sql profiler. This is a great simple way of doing data caching. However there is a problem. If the data changes on the back end, you would want the cached version of this page thrown away and refreshed immediately. Now that has been something that has been difficult to do in the past. Now it is easily supported with asp.net 2.0 and higher.
Step 3: To do this we have to enable database support to table dependency caching. So there is a command line tool called aspnet_regsql you could use to enable table cache to include customer table in the ibddevdb database. So execute the following command
Aspnet_regsql –S devserver –U sa –d devdb –ed –et –t Customer
The command prompts for password. Enter the password and you can see in the sql profiler that it did some stuff on the backend.



Now open the Microsoft Sql Server management studio and open the tables under devdb database and open the tables. Now you will notice that there is an extra table AspNet_SqlCacheTablesForChangeNotification. Expand the Customer table, you will notice that there is a trigger Customer_AspNet_SqlCacheNotification_Trigger. Every time there is a change to the Customer table, it writes a row to the table AspNet_SqlCacheTablesForChangeNotification. This table is going to be polled by asp.net to see if there are any changes to the system.
Now that we have set it up for the database, we need to set it up for our website.
Step 4:
1. To do this, we need to make an entry in the web.config file
<system.web>
<caching>
<sqlCacheDependency enabled="true" pollTime="2000">
<databases>
<add connectionStringName="NW" name="NW"/>
databases>
sqlCacheDependency>
The polling time is set to 2000 milli seconds.
2. Go back to the default page and add SqlDependency attribute to the OutputCache directive.
<%@ OutputCache Duration="20" VaryByParam="*" SqlDependency="NW:Customer"%>
3. Now if we go back and hit refresh, we see we have the table. If we go back to the sql server profiler, we see that the polling is happening every couple of seconds. If we go change a record in the table, and we go hit refresh, it shows right away.
4. This is great because it works both for Sql server 2000 and 2005.But Sql server 2005 introduces a new concept called broker service. This broker service allows asp.net to serve as a client where it can be notified if there is a change. For that we need to setup a dialog between asp.net 2.0 and sql server 2005. To enable that simple change, change the sqldependency attribute in the OutputCache directive.
<%@ OutputCache Duration="20" VaryByParam="*" SqlDependency="CommandNotification"%>
5. Now open Global.asax file and add this line inside the function Application_Start(..)
System.Data.SqlClient.SqlDependency.Start(ConfigurationManager.ConnectionStrings[“NW”].ConnectionString);
6. Now go back to the web page and hit refresh. Now the webpage functions the same way but if you go back to sql profiler, you will see there is much less traffic going on back and forth. There is no polling going on at this point. If we do go change the data, and hit refresh, it shows the change right away. So we get the benefit of this page invalidation at the table level with a lot less traffic going on back and forth.
Conclusion:
We learnt output caching has been around for a while and two techniques to enable table level caching: The polling mechanism that is working with sql server 2000 and 2005, and the new feature of 2005 only which is the broker service called the command notification