如果你的应用程序中应用了Membership Provider,那么在应用程序上线前,你不得不对web.config做一些调整:
<profileenabled="true">.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }每当一次请求完全,profile provider都会自动保存profile,这样我们的应用程序就因为大量的非必须的update操作降低了性能,所以关闭profile的自动保存并且在需要时,显示的通过Profile.Save()来保存。
<providers>
<clear/>
<addname="..."type="System.Web.Profile.SqlProfileProvider"
connectionStringName="..."applicationName="YourApplicationName"
description="..."/>
</providers>
<profileenabled="true"automaticSaveEnabled="false">.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }Role Manager每次都需要查询数据库来确定一个用户的角色,这同样也是一个很大的性能损失,我们可以通过将用户的角色缓存在cookie中来解决这个问题,但是请注意cookie的最大容量是2KB,所以如果我们有许多用户并且每个用户都有特别多的角色,就有可能超出cookie的容量,当然这种情况毕竟是少数,所以通常我们可以通过下面的设置将用户角色信息缓存在cookie中,以减少数据库访问次数。
<roleManagerenabled="true"cacheRolesInCookie="true">.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
浏览器可以缓存图片、js文件、css文件,同样浏览器也可以缓存XML Http调用(当然这需要XML Http以get方式发送调用),这种缓存基于URL,当我们发送一个请求时,如果和以前请求的URL相同,那么浏览器就会从缓存中响应,而不是从重新请求服务器,这可以节省一些时间。通常来说,浏览器会缓存所有的Http get请求的结果,所以如果我们让XML Http以get方式发送请求,并且服务器返回特定的header告诉浏览器缓存结果,那么在以后的请求中,我们就可以直接从缓存中得到响应,从而节约了大量的时间。
在PageFlakes网站中,作者缓存了用户状态,所以如果用户重新登录网站,用户将会从浏览器缓存中得到一个缓存的页面而不是重新请求服务器,所以第二次访问是快很多,另外作者还缓存了许多用户的操作结果,所以当用户重新做相同的动作时,被缓存的结果会迅速的出现,这就使用户得到了更好的体验。
所以如果以http get方式调用Ajax请求时,我们应该返回特定的http header以告诉浏览器缓存请求的结果。下面是两种不同的方式,我们可以采取其中之一:
HTTP/1.1 200 OK
Expires: Fri, 1 Jan 2030
Cache-Control: public
上面的header告诉浏览器将请求结果缓存到2030年,所以如果我们在2030年之前发出同样的xml http请求,浏览器都会直接从缓存中读取结果,而不用重新请求服务器。另外还有一种更高级的header用来控件请求结果的缓存,下面的header指示浏览器也将请求结果缓存60分钟,并在60分钟后重新请求结果,
HTTP/1.1 200 OK
Cache-Control: private, must-revalidate, proxy-revalidate, max-age=60
让我们尝试在Asp.NET web service响应中加入上述的header:
[WebMethod][ScriptMethod(UseHttpGet=true)]
publicstringCachedGet()
{
TimeSpan cacheDuration = TimeSpan.FromMinutes(1);
Context.Response.Cache.SetCacheability(HttpCacheability.Public);
Context.Response.Cache.SetExpires(DateTime.Now.Add(cacheDuration));
Context.Response.Cache.SetMaxAge(cacheDuration);
Context.Response.Cache.AppendCacheExtension(
"must-revalidate, proxy-revalidate");
returnDateTime.Now.ToString();
}
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }上面的代码将会产生如下的response headwers :
从上图我们可以看到,Expires属性被正确的设置了,但是cache-control属性却没有被正确设置,其max-age的值是0,而不是60,这样浏览器就不会做任何缓存,所以当我们重新请求时,还是会请求服务器,而不是从缓存中返回结果。
这是Asp.net 2.0的一个bug,你无法改变max-age的值,这是因为在处理一个web services请求之前,asp.net ajax framework截取了请求并且错误地将max-age设置为0,这就意味着浏览器不会缓存ajax响应。
但是通过反编译HttpCachePolicy的代码,我们发现了如下代码段:
不知怎么地,只有在"if(!this._isMaxAgeSet || (delta
<this._maxAge))
" 时,才会设置_maxAge的值,这是不正确的,因为这阻止了将_maxAge的值设为一个大于当前值的值。所以我们需要通过反射来绕过SetMaxAge方法去设置_maxAge的值:
[WebMethod][ScriptMethod(UseHttpGet=true)]
publicstringCachedGet2()
{
TimeSpan cacheDuration = TimeSpan.FromMinutes(1);
FieldInfo maxAge = Context.Response.Cache.GetType().GetField("_maxAge",
BindingFlags.Instance|BindingFlags.NonPublic);
maxAge.SetValue(Context.Response.Cache, cacheDuration);
Context.Response.Cache.SetCacheability(HttpCacheability.Public);
Context.Response.Cache.SetExpires(DateTime.Now.Add(cacheDuration));
Context.Response.Cache.AppendCacheExtension(
"must-revalidate, proxy-revalidate");
returnDateTime.Now.ToString();
}
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }上面的代码返回如下的header:
现在我们可以看到 max-age的值是60,并且浏览器会缓存结果60分钟,如果你在60分钟内进行相同的调用,浏览器将会从缓存中响应。一分钟后,缓存过期,浏览器会自动发送一个请求,那个请求的代码就像下面一样:
functiontestCache()
{
TestService.CachedGet(function(result)
{
debug.trace(result);
});
}
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }请注意,这里还有一个问题,因为asp.net ajax的默认信任级别是中等的,
<system.web>
<trustlevel="Medium"/>
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }而我们的CachedGet2方法却用到了反射,所以仅有中等信任是不够的,我们需要按如下的方式修改web.config文件:
<system.web>
<trustlevel="Full"/>
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }5 更好的应用浏览器缓存
浏览器缓存的基础是URL,当一个URL改变时,浏览器就会从服务器重新请求页面。我们可以通过不同的查询参数来改变URL,例如我们在缓存中缓存了default.aspx页面,如果我们再请求default.aspx/?1页面,这时虽然是相同的操作,但浏览器仍会重新请求服务器,另外如果在Header中做了设置,新的请求结果也会被缓存。因此我们要确保使用一致的URL。