Professional ASP.NET 3.5 in C# and Visual Basic Part 112 ppsx

10 286 0
Professional ASP.NET 3.5 in C# and Visual Basic Part 112 ppsx

Đang tải... (xem toàn văn)

Thông tin tài liệu

Evjen c22.tex V2 - 01/28/2008 3:19pm Page 1068 Chapter 22: State Management expensive database retrieval, those UserControls can retrieve the necessary data from HttpContext.Items . The database is hit only once. ❑ When individual units within a single HttpRequest need to act on the same or similar data: If the lifetime of your data is just one request, consider using HttpContext.Items ,asashortterm cache. The Items collection holds objects, just like m any of the collections that have been used in this chapter. You need to cast those objects back to their specific type when they are retrieved. Within a Web-aware Database Access Layer, per-request caching can be quickly implemented with the simple coding pattern shown here. Note that this sample code is a design pattern and there is no MyData class; it’s for illustration. VB Public Shared Function GetExpensiveData(ID As Integer) As MyData Dim key as string = "data" & ID.ToString() Dim d as MyData = _ CType(HttpContext.Current.Items(key), MyData) If d Is Nothing Then d = New Data() ’Go to the Database, do whatever HttpContext.Current.Items(key) = d End If Return d End Function C# public static MyData GetExpensiveData(int ID) { string key = "data" + ID.ToString(); MyData d = (MyData) HttpContext.Current.Items[key]; if (d == null) { d = new Data(); //Go to the Database, do whatever HttpContext.Current.Items[key] = d; } return d; } This code checks the Items collection of the current HttpContext to see if the data is already there. If not, the data is retrieved from the appropriate backing store and then stored in the Items collection. Subsequent calls to this function within the same HttpRequest receive the already-cached object. As with all optimizations and caching, premature optimization is the root of all evil. Measure your need for caching, and measure your improve ments. Don’t cache just because it feels right;cachebecauseit makes sense. 1068 Evjen c22.tex V2 - 01/28/2008 3:19pm Page 1069 Chapter 22: State Management Summary This chapter explored the many ways to manage State within your ASP.NET application. The Session object and its providers offer many choices. Each has its own pros and cons for managing state in the form of object references and serialized objects in a way that can be made largely transparent to the application. Server-side Session state data can have its unique identifying key stored in a cookie or the key can be carried along in the URL. Cookies can also be used independently to store small amounts of data and persist it between visits, albeit in much smaller amounts and with simpler types. Hidden fields, ViewState, ControlState, postbacks, and new cross-page postbacks offer new possibilities for managing small bits of state within a multi-page user experience. HttpContext.Current.Items offers a perfect place to hold transient state, living the life of only a single HttpRequest . QueryStrings are an old standby for holding non-private state that is appropriate for navigation. ASP.NET has improved on ASP.NET 1.x’s state management options with a flexible Session State Provider module, the addition of Control State for user controls, and cross-page postbacks for a more mature programming model. 1069 Evjen c23.tex V2 - 01/28/2008 3:38pm Page 1071 Caching Performance is a key requirement for any application or piece of code that you develop. The browser helps with client-side caching of text and images, whereas the server-side caching you choose to implement is vital for creating the best possible performance. Caching is the process of storing frequently used data on the server to fulfill subsequent requests. You will discover that grab- bing objects from memory is much faster than re-creating the Web pages or items contained in them from scratch e ach time they are requested. Caching increases your application’s performance, scalability, and availability. The more you fine -tune your application’s caching approach, the better it performs. This chapter focuses on caching, including the SQL invalidation caching capabilities that ASP.NET provides. This chapter takes a close look at this unique aspect of caching. When you are using SQL cache invalidation, if the result set from SQL Server changes, the output cache can be triggered to change automatically. This ensures that the end user always sees the latest result set, and the data presented is never stale. After introducing SQL cache invalidation, this chapter also covers other performance enhancements. It discusses the new Post-Cache Substitution feature, which caches entire pages while dynamically replacing specified bits of content. Lastly, this chapter covers a new capability that enables a developer to create custom dependencies. Caching There are several ways to deal with caching in ASP.NET. First, you can cache an entire HTTP response (the entire Web page) using a mechanism called output caching. Two other methods are partial page caching and data caching. The following sections describe these methods. Output Caching Output caching is a way to keep the dynamically generated page content in the server’s memory or disk for later retrieval. This type of cache saves post-rendered content so it won‘t have to be regenerated again the next time it’s requested. After a page is cached, it can be served up again Evjen c23.tex V2 - 01/28/2008 3:38pm Page 1072 Chapter 23: Caching when any subsequent requests are made to the server. You apply output caching by inserting an OutputCache page directive at the top of an .aspx page, as follows: < %@ OutputCache Duration="60" VaryByParam="None" % > The Duration attribute defines the number of seconds a page is stored in the cache. The VaryByParam attribute determines which versions of the page output are actually cached. You can generate different responses based on whether an HTTP-POST or HTTP-GET response is required. Other than the attributes for the OutputCache directive, ASP.NET includes the VaryByHeader , VaryByCustom , VaryByControl ,and Location attributes. Additionally, the Shared attribute can affect UserControls, as you’ll see later. Caching in ASP.NET is implemented as an HttpModule that listens to all HttpRequest s that come through the ASP.NET worker process. The OutputCacheModule listens to the application’s ResolveRequestCache and UpdateRequestCache events, handles cache hits and misses, and returns the cached HTML, bypass- ing the Page Handler if need be. VaryByParam The VaryByParam attribute can specify which QueryString parameters cause a new version of the page to be cached: < %@ OutputCache Duration="90" VaryByParam="pageId;subPageId" % > For example, if y ou have a page called navigation.aspx that includes navigation information in the QueryString ,suchas pageId and subPageId ,the OutputCache directive shown here caches the page for every different value of pageId and subPageId . In this example, the number of pages is best expressed with an equation: cacheItems = (num of pageIds) * (num of subPageIds) where cacheItems is the number of rendered HTML pages that would be stored in the cache. Pages are cached only after they’re requested and pass through the OutputCacheModule . The maximum amount of cache memory in this case is used only after every possible combination is visited at least once. Although these are just potential maximums, creating an equation that represents your system’s potential maximum is an important exercise. If you want to cache a new version of the page based on any differences in the QueryString parameters, use VaryByParam = "*" , as in the following code. < %@ OutputCache Duration="90" VaryByParam="*" % > It’s important to ‘‘do the math’’ when using the VaryBy attributes. For example, you could add VaryByHeader and cache a different version of the page based on the browser’s reported User-Agent HTTP Header. < %@ OutputCache Duration="90" VaryByParam="*" VaryByHeader="User-Agent"% > The User-Agent identifies the user’s browser type. ASP.NET can automatically generate different ren- derings of a given page that are customized to specific browsers, so it makes sense in many cases to save these various renderings in the cache. A Firefox user might have slightly different HTML than an IE user so we don’t want to send all users the exact same post-rendered HTML. Literally dozens, if not hundreds, of User-Agent strings exist in the wild because they identify more than just the browser type; 1072 Evjen c23.tex V2 - 01/28/2008 3:38pm Page 1073 Chapter 23: Caching this OutputCache directive could multiply into thousands of different versions of this page being cached, depending on server load. In this case, you should measure the cost of the caching against the cost of re-creating the page dynamically. Always cache what will give you the biggest performance gain, and prove that assumption with testing. Don’t ‘‘cache by coincidence’’ using attributes like VaryByParam = "*" . A common rule of thumb is to cache the least possible amount of data at first and add more caching later if you determine a need for it. Remember that the server memory is a limited resource so you may want configure the use of disk caching in some cases. Be sure to balance your limited resources with security as a primary concern; don’t put sensitive data on the disk. VaryByControl VaryByControl can be a very easy way to get some serious performance gains from complicated User- Controls that render a lot of HTML that doesn’t change often. For example, imagine a UserControl that renders a ComboBox showing the names of all the countries in the world. Perhaps those names are retrieved from a database and rendered in the combo box as follows: < %@ OutputCache Duration="2592000" VaryByControl="comboBoxOfCountries" % > Certainly the names of the world’s countries don’t change that often, so the Duration might be set to a month (in seconds). The rendered output of the UserControl is cached, allowing a page using that control to reap performance benefits of caching the control while the page itself remains dynamic. VaryByCustom Although the VaryBy attributes offer a great deal of power, sometimes you need more flexibility. If you want to take the OutputCache directive from the previous navigation example and cache by a value stored in a cookie, you can add VaryByCustom .Thevalueof VaryByCustom is passed into the GetVaryByCustomString method that can be added to the Global.asax.cs . This method is called every time the page is requested, and it is the function’s responsibility to return a value. A different version of the page is cached for each unique value returned. For example, say your users have a cookie called Language that has three potential values: en, es, and fr. You want to allow users to specify their preferred language, regardless of their language reported by their browser. Language also has a fourth potential value — it may not exist! Therefore, the OutputCache directive in the following example caches many versions of the page, as described in this equation: cacheItems = (num of pageIds) * (num of subPageIds) * (4 possible Language values) To summarize, suppose there were 10 potential values for pageId ,fivepotential subPageId values fo r each pageId , and 4 possible values for Language . That adds up to 200 different potential cached versions of this single navigation page. T his math isn’t mea nt to scare you away f rom caching, but you should realize that with great (caching) power comes great responsibility. The following OutputCache directive includes pageId and subPageId as values for VaryByParam ,and VaryByCustom passes in the value of "prefs" to the GetVaryByCustomString callback function in Listing 23-1: 1073 Evjen c23.tex V2 - 01/28/2008 3:38pm Page 1074 Chapter 23: Caching < %@ OutputCache Duration="90" VaryByParam="pageId;subPageId" VaryByCustom="prefs"% > Caching in ASP.NET involves a tradeoff between CPU and memory: how hard is it to make this page, versus whether you can afford to hold 200 versions of it. If it’s only 5 KB of HTML, a potential megabyte of memory could pay off handsomely versus thousands and thousands of database accesses. Since most pages will hit the database a t least once during a page cycle, every page request served from the cache saves you a trip to the database. Efficient use of caching can translate into cost savings if fewer database servers and licenses are needed. The code in Listing 23-1 returns the value stored in the Language cookie. The arg parameter to the GetVaryByCustomString method contains the string "prefs" ,asspecifiedin VaryByCustom . Listing 23-1: GetVaryByCustomString callback method in the HttpApplication VB Overrides Function GetVaryByCustomString(ByVal context As HttpContext, _ ByVal arg As String) As String If arg.ToLower() = "prefs" Then Dim cookie As HttpCookie = context.Request.Cookies("Language") If cookie IsNot Nothing Then Return cookie.Value End If End If Return MyBase.GetVaryByCustomString(context, arg) End Function C# public override string GetVaryByCustomString(HttpContext context, string arg) { if(arg.ToLower() == "prefs") { HttpCookie cookie = context.Request.Cookies["Language"]; if(cookie != null) { return cookie.Value; } } return base.GetVaryByCustomString(context, arg); } The GetVaryByCustomString method in Listing 23-1 is used by the HttpApplication in Global.asax.cs and will be called for every page that uses the VaryByCustom OutputCache directive. If your application has many pages that use VaryByCustom , you can create a switch statement and a series of helper functions to retrieve whatever information you want from the user’s HttpContext and to generate unique values for cache keys. Partial Page (UserControl) Caching Similar to output caching, partial page caching enables you to cache only specific blocks of a Web page. You can, for example, cache only the center of the page the user sees. Partial page caching is achieved w ith the caching of user controls so you can build your ASP.NET pages to utilize numerous user controls and 1074 Evjen c23.tex V2 - 01/28/2008 3:38pm Page 1075 Chapter 23: Caching then apply output caching to the selected user controls. This, in essence, caches only the parts of the page that you want, leaving other parts of the page outside the reach of caching. This is a nice feature and, if done correctly, it can lead to pages that perform better. This requires a modular design to be planned up front so you can partition the components of the page into logical units composed of user controls. Typically, UserControls are designed to be placed on multiple pages to maximize reuse of common func- tionality. However, when these UserControls (ASCX files) are cached with the @OutputCache directive’s default attributes, they are cached on a per-page basis. That means that even if a UserControl outputs the identical HTML when placed on pageA.aspx as it does when placed on pageB.aspx , its output is cached twice. By enabling the Shared = "true" attribute, the UserControl’s output can be shared among multiple pages and on sites that make heavy use of shared UserControls: < %@ OutputCache Duration="300" VaryByParam="*" Shared="true" % > The resulting memory savings can be surprisingly large since you only cache one copy of the post- rendered user control instead of caching a copy for each page. As with all optimizations, you need to test both for correctness of output as well as memory usage. If you have an ASCX UserControl using the OutputCache directive, remember that the UserControl exists only for the first request. If a UserControl has its HTML retrieved from the OutputCache , the control doesn’t really exist on the ASPX page. Instead, a PartialCachingControl is created that acts as a proxy or ghost of that control. Any code in the ASPX page that requires a UserControl to be constantly available will fail if that control is reconstituted from the OutputCache . So be sure to always check for this type of caching before using a ny control. The following code fragment illustrates the kind of logic required when accessing a potentially cached UserControl: VB Protected Sub Page_Load() If Not PossiblyCachedUserControl is Nothing Then " Place code manipulating PossiblyCachedUserControl here. End If End Sub C# protected void Page_Load() { if (PossiblyCachedUserControl != null) { // Place code manipulating PossiblyCachedUserControl here. } } Post-Cache Substitution Output caching has typically been an all-or-nothing proposition. The output of the entire page is cached for later use. However, often you want the benefits of output caching, but you also want to keep a small bitofdynamiccontentonthepage.Itwouldbeashametocacheapagebutbeunabletooutputa dynamic ‘‘Welcome, Scott!’’ 1075 Evjen c23.tex V2 - 01/28/2008 3:38pm Page 1076 Chapter 23: Caching ASP.NET 2.0 added post-cache substitution as an opportunity to affect the about-to-be-rendered page. A control is added to the page that acts as a placeholder. It calls a method that you specify after the cached content has been returned. The method returns any string output you like, but you should be careful not to abuse the feature. If your post-cache substitution code calls an expensive stored procedure, you could easily lose any performance benefits you might have expected. Post-cache substitution is an easy feature to use. It gives you two ways to control the substitution: ❑ Call the new Response.WriteSubstitution method, passing it a reference to the desired substi- tution method callback. ❑ Add a < asp:Substitution > control to the page at the desired location, and set its methodName attribute to the name of the callback method. To try this feature, create a new Web site with a Default.aspx . Drag a label control and a substitution control to the design surface. The code in Listing 23-2 updates the label to display the current time, but the page is cached immediately and future requests return that cached value. Set the methodName property in the substitution control to GetUpdatedTime , meaning the name of the static method that is called after the page is retrieved from the cache. The callback function must be static because the page that is rendered doesn’t really exist at this point (an instance of it doesn’t). Because you don’t have a page instance to work with, this method is limited in its scope. However, the current HttpContext is passed into the method, so you have access to the Session , Request ,and Response . The string returned from this method is injected into the Response in place of the substitution control. Listing 23-2: Using the substitution control ASPX < %@ Page Language="C#" CodeFile="Default.aspx.cs" Inherits="_Default" % > < %@ OutputCache Duration="30" VaryByParam="None" % > < html xmlns="http://www.w3.org/1999/xhtml" > < head > < title > Substitution Control < /title > < /head > < body > < form id="form1" runat="server" > < div > < asp:Label ID="Label1" Runat="server" Text="Label" >< /asp:Label > < br / > < asp:Substitution ID="Substitution1" Runat="server" methodName="GetUpdatedTime" / > < br / > < /div > < /form > < /body > < /html > VB Partial Class _Default Inherits System.Web.UI.Page Public Shared Function GetUpdatedTime(ByVal context As HttpContext) As String 1076 Evjen c23.tex V2 - 01/28/2008 3:38pm Page 1077 Chapter 23: Caching Return DateTime.Now.ToLongTimeString() + " by " + _ context.User.Identity.Name End Function Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles Me.Load Label1.Text = DateTime.Now.ToLongTimeString() End Sub End Class C# public partial class _Default : System.Web.UI.Page { public static string GetUpdatedTime(HttpContext context) { return DateTime.Now.ToLongTimeString() + " by " + context.User.Identity.Name; } protected void Page_Load(object sender, EventArgs e) { Label1.Text = DateTime.Now.ToLongTimeString(); } } The ASPX page in Listing 23-2 has a label and a Post-Cache Substitution Control. The control acts as a placeholder in the spot where you want fresh content injected after the page is returned from the cache. The very first time the page is visited only the label is updated because no cached content is returned. The second time the page is visited, however, the entire page is retrieved from the cache — the page handler isn’t called and, consequently, none of the page-level events fire. However, the GetUpdatedTime method is called after the cache module completes its work. Figure 23-1 shows the result if the first line is cached and the second line is created dynamically. Figure 23-1 1077 Evjen c23.tex V2 - 01/28/2008 3:38pm Page 1078 Chapter 23: Caching HttpCachePolicy and Client-Side Caching Caching is more than just holding data in memory on the server-side. A good caching strategy should also include the browser and its client-side caches, controlled by the Cache-Control HTTP Header. HTTP Headers are hints and directives to the browser on how t o handle a request. Some people recommend using HTML < META > tags to control caching behavior. Be aware that neither the browsers nor routers along the way are obligated to pay attention to these directives. You might have more success using HTTP Headers to control caching. Because HTTP Headers travel outside the body of the HTTP message, you have several options for viewing them. You can enable tracing (see Chapter 21) and view the Headers from the tracing output. In Figure 23-2 I’m using the free TcpTrace redirector from PocketSoap.com. For background information on HTTP headers and controlling caching, see the document RFC 2616: Hypertext Transfer Protocol - HTTP/1.1, available on the World Wide Web Consortium’s site at www.w3c.org . You might also check out Fiddler at www.fiddlertool.com/fiddler and FireBug for Firefox at www.getfirebug.com . Commercial tools such as HttpWatch from www.httpwatch.com add more features. Create a Default.aspx that writes the current time in its Load event. Now, view the default HTTP Headers used by ASP.NET, as in Figure 23-2 with page-level tracing turned on. Note that one header, Cache-Control: private , indicates to routers and other intermediates that this response is intended only for you (private). Figure 23-2 1078 . first line is cached and the second line is created dynamically. Figure 23- 1 1077 Evjen c 23. tex V2 - 01/28/2008 3: 38pm Page 1078 Chapter 23: Caching HttpCachePolicy and Client-Side Caching Caching. caching of user controls so you can build your ASP. NET pages to utilize numerous user controls and 1074 Evjen c 23. tex V2 - 01/28/2008 3: 38pm Page 10 75 Chapter 23: Caching then apply output caching. of "prefs" to the GetVaryByCustomString callback function in Listing 23- 1: 10 73 Evjen c 23. tex V2 - 01/28/2008 3: 38pm Page 1074 Chapter 23: Caching < %@ OutputCache Duration="90"

Ngày đăng: 05/07/2014, 19:20

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan