[Original address] tip/TRICK: Implement "Donut Caching" with the ASP. NET 2.0 output cache substitution feature
[Original article publication date] Tuesday, November 28,200 6 AM
Background:
ASP. NET is very powerful, but its rich cache facilities are often not fully utilized. ASP. the cache function of Net allows you to avoid repeated work for each new request from the client on the server. Instead, you can generate HTML content or data structure at a time and then ASP on the server.. Net cache or store the results and reuse the results in future Web requests. This can greatly improve the performance of your application and reduce the load on key background resources such as the object database.
Steve Smith wrote a good article about ASP on msdn a few years ago. NET 1.1 cache article, discussed ASP. NET 1.1 provides some basic knowledge about the caching function, and provides a good summary of how to use them. If you have never used ASP. NET cache before, I suggest you read this article and try every feature. I also recommend that you view ASP. NET 2.0 free video series of this 15-minute about ASP.. Net cached "How do I" video. This video demonstrates ASP.. Net cache.
Two important improvements have been added to ASP. NET 2.0 to improve the cache function:
1)Support for invalid SQL Cache-This allows you to automatically invalidate the cached content and regenerate the cached content when the data table or record row on which the cached page or data structure depends is updated. For example, you can output a webpage that caches all your product lists on an e-commerce website, and make sure that the price of the products in the database is changed, these web pages will be re-generated in the next request, so that the user will not be displayed with expired price data.
2)Replacement of output Cache-This wonderful feature allows you to implement the "Donut Caching" function, which is sometimes called "Sweet circle cache". Here, you output everything on the cache page, but there are several dynamic regions included in the cache area. This allows you to implement full-page output caching more actively. You do not need to divide your page into multiple. ascx user files to achieve partial page caching. The following tips/TIPS guide better explains the driving factors of this feature and its implementation.
Actual scenarios:
You need to implement a product list webpage on your website to list all products under a specified product category. You also want to output the cached webpage so that you do not need to access the database every time you request it. You are in products. add a <% @ outputcache %> command to the top of the ASPX page to achieve this goal easily, the webpage contains a <asp: datalist> Control bound to the product data returned from your intermediate layer.
Note how to set the output cache content for 100,000 seconds for this webpageOrThe products data table in the northwind database is updated to the new price data. In this case, when the next request is made, the page is regenerated. The outputcache command also has a varybyparam attribute, which tells ASP. NET to store a cache page for each unique categoryid. For example, products. aspx? Categoryid = 1, products. aspx? Categoryid = 2 each has a separate cache page.
Products. aspx:
<% @ Page Language = "VB" masterpagefile = "~ /Site. Master "autoeventwireup =" false "codefile =" products. aspx. VB "inherits =" Products "%>
<% @ Outputcache duration = "100000" varybyparam = "categoryid" sqldependency = "northwind: Products" %>
<Asp: Content ID = "content1" contentplaceholderid = "contentplaceholder1" runat = "server">
<Div class = "Catalogue">
<Asp: datalist id = "datalist1" repeatcolumns = "2" runat = "server">
<Itemtemplate>
<Div class = "productimage">
</Div>
<Div class = "productdetails">
<Div class = "productlisthead">
<% # Eval ("productname") %>
</Div>
<SPAN class = "productlistitem">
<Strong> price: </strong>
<% # Eval ("unitprice", "{0: c}") %>
</Span>
</Div>
</Itemtemplate>
</ASP: datalist>
<H3> generated @ <% = now. tolongtimestring () %>
</Div>
</ASP: content>
Products. aspx. VB:
Partial class products
Inherits system. Web. UI. Page
Sub page_load (byval sender as object, byval e as system. eventargs) handles me. Load
Dim products as new northwindtableadapters. productstableadapter
Datalist1.datasource = products. getproductsbycategoryid (request. querystring ("categoryid "))
Datalist1.databind ()
End sub
End Class
When accessing the browser, the server returns the following page:
Note: The time stamp at the bottom of the page is every 100,000 seconds,OrWhen the price data in the products data table is updated, it is updated. It will be cached to handle all other HTTP requests, allowing us to process 1000 requests per second on the production server, avoiding unnecessary database access, therefore, the access speed is extremely fast.
Problem:
A problem we will encounter in the above example is related to the welcome message and username (in red circles above) that we output in the upper right corner of the page. This is generated by using a new ASP. NET 2.0 <asp: loginname> Control in our site. Master motherboard page file, as shown in the following figure:
<Div class = "Header">
<H1> caching samples
<Div class = "loginstatus">
<Asp: loginname formatstring = "Welcome {0 }! "Runat =" server "/>
</Div>
</Div>
The problem we will hit is that because we add the full page output cache to our page, the name of the first user accessing the website will be saved to the cache output of the page, which means that, by default, users who access the website within 100,000 seconds after the initial request will receive an error welcome message. Worse, the error username is displayed!
Solution:
There are two ways to solve this problem.
The first solution is to make the entire page dynamic, that is, remove the top-layer <% @ outputcache %> command, refactor the page content, and encapsulate all the cacheable content in ASP. in. Net user controls, these user controls are implemented through. implemented by the ascx file. Then you add the <% @ outputcache %> command on the top of each file of these user controls so that they can be cached separately. This avoids the need to access the database for each request and ensures that the username is always correctly output because the username is not in the cached user control area. This method is currently feasible in ASP. NET 1.1. Of course, it is still effective in ASP. NET 2.0.
However, the disadvantage of this solution is that, in order to make the cache feasible, it requires us to refactor the encoding and layout of our page. However, if we only have a few places on the page that we want to keep dynamic, This refactoring will be very inconvenient. The good news is that ASP. NET 2.0 has added support for the output cache replacement block, which provides an extremely clean way to deal with this scenario.
Use the <asp: substitution> Control's output cache to replace the block:
The output cache replacement block allows you to outputcache the output of the entire page. At the same time, several dynamic region tags are left in the HTML output to indicate where you need to dynamically fill the content in future requests (for example, user name message in the preceding example ). I sometimes call this the "Donut Caching" function, because the external page content is cached, and only a few holes (hole) in the page content stream are dynamic. This is the opposite of the local page cache implemented by the user control, because in the case of local page cache, the entire page is dynamic and the middle area is cached.
You can replace the output cache by using the full-page output cache. The syntax is exactly the same as that in the products. aspx example above. Then, you can add the <asp: substitution> control on the page to specify which areas of the page you need to dynamically fill with replacement blocks, as shown in the following figure:
<Div class = "Header">
<H1> caching samples
<Div class = "loginstatus">
<Asp: substitution id = "substitution1" runat = "server" methodname = "logintext"/>
</Div>
</Div>
<Asp: substitution> controls and ASP.. net, which is different from ASP. net output cache registers a callback event, when the page content is later requested from ASP. when the net output cache is sent, this event will cause a static method call on your page or parent page. This static method will be passed into an httpcontext object at runtime, which contains ASP. NET Request, response, user, server, session, application and other internal objects, then you can use them to return a string, Asp. net will automatically inject this string into the relevant area of the page before the content is sent back to the client.
For example, in the output cached products. in the ASPX page, to process the scenario above which we need to dynamically output the welcome message, we just need to simply add this method to our site. in the master background code file, and then let the above <asp: substitution> Control call:
Partial class site
Inherits system. Web. UI. masterpage
Shared function logintext (byval context as httpcontext) as string
Return "hello" & context. User. Identity. Name
End Function
End Class
In this way, the entire page will be output and cached, except the content of the welcome message represented by the <asp: substitution> Control in the upper-right corner of the page.
Obviously, we can extend this further if we want to include other personalized information like how many items in the user's shopping basket. What's cool is that all other content on the page is still completely cached. We don't need to access the database in subsequent requests to generate its content, this means that we can process thousands of product pages on a single server every second. In fact, there is no need to generate any controls on the page in the request. In future requests, except for the static method above, no code will be executed, which makes everything very fast.
Use the output cache replacement block of the response. writesubstitution method:
In addition to specifying replaceable content blocks on the page using the <asp: substitution> control, you can also use the response. writesubstitution method. This method accepts the delegate object of the httpresponsesubstitutioncallback method as the parameter. You can implement this method in any class of your application (andNoOnly static methods in your background class ).
<Asp: substitution> the control uses this method internally to connect the delegate method in the background class of the page. Similarly, you can use this method on your own controls or pages to achieve maximum control and flexibility.
Conclusion:
I have not found an ASP. NET application that cannot benefit from the ASP. NET cache function. Because ASP. net supports the entire page output cache, the partial page output cache, and the current sweet circle (donut) layer cache, this allows you to change the cached content based on any parameter or custom logic you need. Now, you can automatically invalidate the cached content and regenerate the cached content when the database changes, you should not find yourself building an application that does not use any caching.
I absolutely recommend that you take some time to familiarize yourself with all ASP. NET cache functions. If you want to find another example about caching, please download the tips/tips I gave at the ASP. NET connections conference recently. The download contains handouts and Demo code, which describes how to use the full page cache, partial page cache, substitution block caching, and SQL cache invalidation ).
If you want to read other ASP. NET Tips/blog posts I have written, visit my ASP. NET tips, tips and Resource Web pages.
I hope this article will help you,
Scott