ASP.NET Cache的一些总结分享

最近我们的系统面临着严峻性能瓶颈问题,这是由于访问量增加,客户端在同一时间请求增加,这迫使我们要从两个方面解决这一问题,增加硬件和提高系统的性能。

1.1.1 摘要
最近我们的系统面临着严峻性能瓶颈问题,这是由于访问量增加,客户端在同一时间请求增加,这迫使我们要从两个方面解决这一问题,增加硬件和提高系统的性能。

大家可以通过各种各样的方法去优化我们系统,本篇博文将介绍通过Cache方法来优化系统的性能,减轻系统的负担。

1.1.2 正文

不同位置的缓存


在Web应用程序中的使用缓存位置主要有:客户端浏览器缓存、客户端和服务器中以及服务器端,因此缓存可以分为以下几类:

客户端缓存(Client Caching)
代理缓存(Proxy Caching)
反向代理缓存(Reverse Proxy
Caching)
服务器缓存(Web Server Caching)
ASP.NET中的缓存

ASP.NET中有两种缓存类型:输出缓存和数据缓存。

输出缓存:这是最简单的缓存类型,它保存发送到客户端的页面副本,当下一个客户端发送相同的页面请求时,此页面不会重新生成(在缓存有限期内),而是从缓存中获取该页面;当然由于缓存过期或被回收,这时页面会重新生成。

数据缓存

除此之外,还有两个特殊的缓存:片段缓存和数据源缓存。

片段缓存:这是一种特殊的输出缓存,它不是缓存整个页面,而是缓存部分页面;由于缓存整个页面通常并不可行,因为页面的某些部分是针对用户定制的(例如用户登陆信息),但我们可以把应用程序中共享的部分进行缓存,这时我们可以考虑使用片段缓存和用户控件缓存。

数据源缓存:是建立在数据源控件的缓存,它包括SqlDataSource、ObjectDataSource和XmlDataSource控件。数据源缓存使用数据缓存方式,不同的是我们不需要通过显示方法处理缓存;我们只需设置相应的属性,然后数据源控件就能存储和检索数据。

输出缓存

输出缓存可以把最终呈现的页面缓存起来,当客户端再次请求同一页面时,控制对象不再重新创建,页面的生命周期不再启动,无需再次执行代码,通过在缓存中获取缓存的页面。

现在我们设计一个页面,每当用户发送页面请求时,就获取当前代码执行的时间,然后显示在页面上。

图1输出缓存


这是再简单不过的例子,每当用户发送页面请求都会更新页面显示的时间,这是由于每次请求都获取了一个新的页面,实际情况中,我们并不需要实时的响应用户每个页面请求,我们可以通过输出缓存把页面缓存起来每当用户发送同一页面请求时,而且在缓存有效期间,可以通过输出缓存把缓存的页面返回给用户。

我们要实现输出缓存,只需在页面中添加如下代码:

1 <!-- Adds OutputCache directive --> 2 <%@ OutputCache Duration="23" VaryByParam="None" %>

它支持五个属性,其中两个属性Duration和VaryByParam是必填的


Duration


必需属性。页面应该被缓存的时间,以秒为单位。必须是正整数。


Location


指定应该对输出进行缓存的位置。如果要指定该参数,则必须是下列选项之一:Any、Client、Downstream、None、Server 或
ServerAndClient。


VaryByParam


必需属性。Request 中变量的名称,这些变量名应该产生单独的缓存条目。"none" 表示没有变动。"*"
可用于为每个不同的变量数组创建新的缓存条目。变量之间用 ";" 进行分隔。


VaryByHeader


基于指定的标头中的变动改变缓存条目。


VaryByCustom


允许在 global.asax 中指定自定义变动(例如,"Browser")。

表1输出缓存属性

这里我们把输出缓存的有效期设置为23秒,也就是说,当缓存超过有效期就会被回收;当用户再次请求该页面时,就要重新创建页面。

客户端缓存

另一种选择是客户端缓存,如果用户在浏览器中点击“后退”按钮或在地址栏中重新输入URL,那么在这种情况下,浏览器将从缓存获取页面;然而,如果用户点击“刷新”按钮,那么浏览器中缓存将失效,浏览器发送页面请求。

如果我们要使用客户端缓存,只需指定OutputCache中的属性Location=”Client”就OK了,具体代码如下所示:

<!-- Sets client OutputCache -->
<%@ OutputCache Duration="23" VaryByParam="None" Location="Client" %>

通过在OutputCache中添加Location属性,我们实现了客户端缓存,通过设置客户端缓存我们能够减少的客户端请求,也许有人会问:“每个用户第一次页面请求都需要服务器来完成,这不能很好的减少服务的压力”。的确是这样,相对于服务器缓存,客户端缓存并没有减少代码的执行和数据库的操作,但是当我们把包含个性化数据的页面缓存在服务器中,客户端请求页面时,由于不同的用户个性化数据不同,这将会导致请求出现错误,所以我们可以使用片段缓存把公用的部分缓存起来或客户端缓存把用户信息缓存起来。

Query String缓存

在前面的例子中,我们把OutputCache中的VaryByParam属性设置为None,那么ASP.NET程序只缓存一个页面副本;如果页面请求包含查询参数,那么在缓存的有效期内,我们只可以查看到只是缓存结果,假设我们有个报表程序,它提供用户根据产品名称查询相关的产品信息。

首先我们创建两个页面:查询和结果页面,由于时间关系我们已经把页面设计好了,具体如下所示:

图2报表程序

首先我们提供查询页面,让用户根据成品名称(ProductName)查询相应的成品信息,具体的代码如下:

 1 protected void Page_Load(object sender, EventArgs e)
 2 {
 3 if (!Page.IsPostBack)
 4 {
 5 // Gets product id from table Production.Product.
 6 // Then binding data to drop down list control.
 7 InitControl(GetProductId());
 8 }
 9 }
10 /// <summary>
11 /// Handles the Click event of the btnSubmit control.
12 /// Redirects to relative product information page.
13 /// </summary>
14 protected void btnSubmit_Click(object sender, EventArgs e)
15 {
16 Response.Redirect(string.Format("Product.aspx?productname={0}", ddlProductName.SelectedValue));
17 } 

当用户点击Submit按钮后,跳转到Product页面并且在Url中传递查询参数——产品名称(ProducName)。

接下来,我们继续完成查询页面,由于在前一页面中传递了查询参数ProductName,那么我们将根据ProductName查询数据库获取相应的产品信息,具体代码如下所示:

 1 protected void Page_Load(object sender, EventArgs e)
 2 {
 3 // Get product name.
 4 string productName = Request.QueryString["productname"];
 5
 6 // Binding data to data grid view control.
 7 InitControl(this.GetData(productName));
 8 }
 9
10 /// <summary>
11 /// Inits the control.
12 /// </summary>
13 /// <param name="ds">The dataset.</param>
14 private void InitControl(DataSet ds)
15 {
16 dgvProduct.DataSource = ds;
17 dgvProduct.DataBind();
18 }
19
20 /// <summary>
21 /// Gets the data.
22 /// </summary>
23 /// <param name="productName">Name of the product.</param>
24 /// <returns>Returns dataset</returns>
25 private DataSet GetData(string productName)
26 {
27 // The query sql base on product name.
28 string sql =
29 string.Format(
30 "SELECT Name, ProductNumber, SafetyStockLevel, ReorderPoint, StandardCost, DaysToManufacture "
31 + "FROM Production.Product WHERE ProductNumber=‘{0}‘",
32 productName);
33
34 // Get data from table Production.Product.
35 using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLCONN"].ToString()))
36 using (var com = new SqlCommand(sql, con))
37 {
38 com.Connection.Open();
39 ////gdvData.DataSource = com.ExecuteReader();
40 ////gdvData.DataBind();
41 var ada = new SqlDataAdapter(com);
42 var ds = new DataSet();
43 ada.Fill(ds);
44 return ds;
45 }
46 } 

前面示例,我们通过Request的属性QueryString获取ProductName的值,然后根据ProductName查询数据库,最后把获取数据绑定到Datagridview控件中(注:前面实例没有考虑SQL Injection问题)。

图3查询结果

现在我们在页面中添加输出缓存,如下代码:

<!-- Adds OutputCache directive -->
<%@ OutputCache Duration="30" VaryByParam="None" %>

前面提到当输出缓存的属性VaryByParam=”None”时,ASP.NET程序在缓存有效期内只缓存一个页面副本;现在我们在缓存有效期内(30s)再发送请求。

图4查询结果

通过上图我们发现,现在查询参数ProductName=BK-M18B-40,但查询结果依然是ProductName=BB-9108的数据,这是由于ASP.NET程序在缓存有效期内只缓存一个页面副本。

通过上面的示例,我们发现只缓存一个页面是不适用包含查询参数的页面输出缓存;其实前面的示例我们只需稍稍改动就能符合查询参数的情况了,想必大家已经知道了,只需把VaryByParam属性设置为“*”就OK了。

图5查询结果

现在查询可以获取相应的结果,如果查询参数和前一个请求相同并且该页面缓存有效,那么缓存将被重用,否则,创建一个新的页面缓存。

由于ASP.NET给每个查询参数都添加了输出缓存,但我们要注意的是是否真的有必要缓存每个查询参数都缓存一个页面副本,假设查询Url中增加一个参数参数ProductId,那么现在Url中就有两个查询参数了(ProductName和ProductId)。

前面我们把VaryByParam设置为“*”,所为ASP.NET程序对ProductName和ProductId都创建页面缓存,如果我们只针对ProductName创建页面缓存,这时我们可以修改VaryByParam,具体如下所示:

1 <!-- Sets VaryByParam property--> 2 <%@ OutputCache Duration="30" VaryByParam="productname" %>

自定义缓存控件
前面我们介绍了通过查询参数实现缓存一个或多个页面,其实ASP.NET也允许我们自定义缓存方式来决定是否缓存页或重用现有的,这时我们可以通过设置VaryByCustom属性来实现。

假设,现在我们要设计基于不同UserHostName的缓存,由于程序在执行过程中,首先调用全局方法GetVaryByCustomString()来确定是否缓存页面或重用现有的,所以我们可以通过重写GetVaryByCustomString()方法实现基于UserHostName的缓存,首先我们创建一个Global.asax文件然后重新全局方法GetVaryByCustomString()具体实现如下:

 1 /// <summary>
 2 /// Gets vary cache based on custom string value.
 3 /// </summary>
 4 /// <param name="context">Http context.</param>
 5 /// <param name="custom">custom string</param>
 6 /// <returns></returns>
 7 public override string GetVaryByCustomString(HttpContext context, string custom)
 8 {
 9 if (string.Equals(custom, "UserHostName", StringComparison.OrdinalIgnoreCase))
10 {
11 // Indicates that the cache should be vary on user host name.
12 return Context.Request.UserHostName;
13 }
14 return base.GetVaryByCustomString(context, custom);
15 } 

前面我们重写了GetVaryByCustomString()方法,使得UserHostName值不同时,获取相应的缓存值。

然后让程序基于UserHostName创建缓存,所以我们要在页面添加以下代码:

<!-- set vary cache based on custom string value -->
<%@ OutputCache Duration="30" VaryByParam="None" VaryByCustom="UserHostName" %>

我们通过自定义现在GetVaryByCustomString()方法,实现了Web程序根据UserHostName实施不同的缓存方式,其实,我们还可以实现更多种类缓存方案,例如:基于用户角色、时间和Url等等。

片段缓存

在某些情况下,我们不能缓存整个页面,但我们仍想缓存部分页面从而减轻系统的负担;其实,我们可以通过两种方法实现:片段缓存和数据缓存.

为了实现片段缓存,我们需要创建自定义控件缓存部分页面,然后我们把OutputCache指令添加到自定义控件中,这样整个页面将不会被缓存,而自定义缓存控件除外。

前面我们介绍了输出缓存的使用,只需在页面中添加OutputCache指令,假设我们要在几个页面中添加输出缓存这可能比较简单,但我们要在几十个页面中添加输出缓存功能,而且前面介绍的例子中Duration属性值都是直接Hard
code到每个页面中,如果我们需要修改Duration属性值,那么就必须修改每个页面了,ASP.NET还需要重新编译这些页面,这不利于我们的维护,最重要的是增加了我们的工作量。

其实,我们可以在web.config文件中定义一个outputCacheProfile(ProductCacheProfile),然后在页面中添加CacheProfile属性并且赋值为ProductCacheProfile,web.config文件设置如下:

1 <caching>
2 <!-- Sets out put cache profile-->
3 <outputCacheSettings>
4 <outputCacheProfiles>
5 <add name="ProductCacheProfile" duration="30"/>
6 </outputCacheProfiles>
7 </outputCacheSettings>
8 </caching>现在,我们在页面中添加CacheProfile属性,并且设置为ProductCacheProfile,如下所示:
<!-- set CacheProfile property -->
<%@ OutputCache CacheProfile="ProductCacheProfile" VaryByParam="None" %>

数据缓存
Cache对象是线程安全:这表示无需显式实现锁定或解锁,在添删Cache对象中的元素,然而,在Cache对象中元素必须是线程安全的。例如,我们创建一个实体Product,而且存在多个客户端可能同时操作该对象的情况,这时我们必须为实体Product实现锁定和解锁操作(同步操作请参考《单例模式(Singleton)的6种实现》)。

Cache对象中的缓存项自动移除:当缓存过期,依赖项被修改或内存不足缓存ASP.NET会自动移除该缓存项。

缓存项支持依赖关系:我们可以给缓存项添加文件、数据库表或其他资源类型的依赖关系。

SqlDataSource缓存

当我们在SqlDataSource控件中启用缓存,它缓存SelectCommand中的结果;如果SQL查询语句中带有参数时,SqlDataSource控件会缓存每一个参数值对应的结果。

这跟我们之前通过输出缓存实现报表程序缓存查询页面效果一样,所以我们将使用SqlDataSource缓存实现该效果。

假设我们要提供一个报表程序,让用户通过选择产品名称(ProductName),获取相应的产品信息。

首先,我们在页面中创建两个数据源控件:sourceProductName和sourceProduct,接着把数据源分别绑定到Dropdownlist和Gridview中,具体实现如下:

<!-- The product number datasource START -->
<asp:SqlDataSource ID="sourceProductName" runat="server" ProviderName="System.Data.SqlClient"
EnableCaching="True" CacheDuration="3600" ConnectionString="<%$ ConnectionStrings:SQLCONN %>"
SelectCommand="SELECT ProductNumber FROM Production.Product"></asp:SqlDataSource>
<!-- The product number datasource END --> 

<!-- The product datasource START -->
<asp:SqlDataSource ID="sourceProduct" runat="server" ProviderName="System.Data.SqlClient"
EnableCaching="True" CacheDuration="3600" ConnectionString="<%$ ConnectionStrings:SQLCONN %>"
SelectCommand="SELECT Name, ProductNumber, SafetyStockLevel, ReorderPoint, StandardCost, DaysToManufacture
FROM Production.Product WHERE [email protected]">
<SelectParameters>
<asp:ControlParameter ControlID="ddlProductNumber" Name="ProductNumber" PropertyName="SelectedValue" />
</SelectParameters>
</asp:SqlDataSource>
<!-- The product number datasource END --> 

<!-- Binding the product number to gridview control -->
<!-- NOTE: Due to search and result in the same page, so need to set AutoPostBack is True-->
<asp:DropDownList ID="ddlProductNumber" AutoPostBack="True" DataSourceID="sourceProductName"
DataTextField="ProductNumber" runat="server">
</asp:DropDownList> 

<!-- Binding the product datasource to gridview control -->
<asp:GridView ID="gvProduct" runat="server" DataSourceID="sourceProduct" CssClass="Product">
</asp:GridView>

现在我们对报表程序进行查询,如果ProudctName之前没有被缓存起来就会创建相应的缓存,而已经缓存起来的将被重用,查询结果如下:


图6查询结果

缓存的依赖关系
缓存项之间的依赖

ASP.NET
Cache允许我们建立缓存之间的依赖关系,即一个缓存项依赖于另一个缓存项;以下示例代码创建了二个缓存项,并且它们之间建立依赖关系。具体实现如下:

// Creates cache object Key1.
Cache["Key1"] = "Cache Item 1"; 

// Makes Cache["Key2"] dependent on Cache["Key1"].
string[] dependencyKey = new string[1];
dependencyKey[0] = "Key1"; 

// Creates a CacheDependency object.
CacheDependency dependency = new CacheDependency(null, dependencyKey); 

// Establishs dependency between cache Key1 and Key2.
Cache.Insert("Key2", "Cache Item 2", dependency); 

现在,当Key1缓存项更新或从缓存中删除,Key2缓存项就会自动从缓存删除。

文件依赖

前面我们介绍了缓存项之间的依赖关系,ASP.NET Cache还提供缓存项与文件之间的依赖关系,当文件被更新或删除对应的缓存项也将失效。

在上篇博文《Ajax与JSON的一些总结》的最后介绍的一个DEMO——Weibo
Feed中,我们通过实时方式向新浪微博API发送请求获取相应的数据,但在一定时间内请求的次数是有限制的,一旦超出了限制次数就不再接受请求了(具体请参考Rate-limiting)。所以可以通过Cache的方式把数据缓存起来,当客户端请求时,如果缓存数据已经存在那么直接返回数据,否则重新想微博API请求数据。

首先,我们创建一个HttpHandler,它负责向微博API发送请求并且把数据保存的文件中,最后把数据返回的客户端。

图7 请求流程

接下来,我们定义CacheData()方法把微博数据保存到文本文件中并且建立缓存与数据文件的依赖关系。

/// <summary>
/// Caches the data into text file.
/// </summary>
/// <param name="context">The http context</param>
private void CacheData(HttpContext context)
{
// Weibo API.
string uri = context.Request.QueryString["api"] + "?" +
"source=" + context.Request.QueryString["source"] + "&" +
"count=" + context.Request.QueryString["count"];
HttpWebResponse response = this.GetWeibos(uri);
if (null == response)
{
throw new ArgumentNullException("Response is null");
}
string jsonData;
// Writes the reponse data into text file.
using (var reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(response.CharacterSet)))
{
jsonData = reader.ReadToEnd();
}
string dataPath = context.Server.MapPath("weibo.json");
using (var writer = new StreamWriter(dataPath, false, Encoding.GetEncoding(response.CharacterSet)))
{
writer.Write(jsonData);
}
// Establishs dependency between cache weibo and text file.
// Sets cache expires after 2 minuntes.
HttpRuntime.Cache.Insert("weibo", jsonData, Dep, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(2));
} 

现在我们把数据保存到文本文件中并且建立了缓存weibo与数据文件的依赖关系,接下来我们要把JSON格式数据返回给客户端。

/// <summary>
/// Responses the weibo data.
/// </summary>
/// <param name="context">The http contex.</param>
private void ResponseWeibo(HttpContext context)
{
// Gets the weibo cache data.
byte[] buf = Encoding.UTF8.GetBytes(HttpRuntime.Cache["weibo"].ToString());
// Writes the data into output stream.
context.Response.OutputStream.Write(buf, 0, buf.Length);
context.Response.OutputStream.Flush();
////context.Response.Close();
} 

上面我们把JSON格式字符串转换为Byte数值,然后写入到OutputStream中,最后把数据返回给客户端。

// The function to get weibo data.
loadWeibo: function() {
$.ajax({
// Weibo API.
url: "WeiboHandler.ashx",
type: "GET",
// NOTE: We get the data from same domain,
// dataType is json.
dataType: "json",
data: {
source: JQWeibo.appKey,
count: JQWeibo.numWeibo
},
// When the requet completed, then invokes success function.
success: function(data, textStatus, xhr) {
// Sets html structure.
var html =
‘<div class="weibo">‘ +
‘<a href="http://weibo.com/DOMAIN" target="_blank">USER</a>‘ +
‘:WEIBO_TEXT<div class="time">AGO</div>‘;
// Appends weibos into html page.
for (var i = 0; i < data.length; i++) {
$(JQWeibo.appendTo).append(
html.replace(‘WEIBO_TEXT‘, JQWeibo.ify.clean(data[i].text))
// Uses regex and declare DOMAIN as global, if found replace all.
.replace(/DOMAIN/g, data[i].user.domain)
.replace(/USER/g, data[i].user.screen_name)
.replace(‘AGO‘, JQWeibo.timeAgo(data[i].created_at))
);
}
}
})
} 

图8请求结果
1.1.3 总结

缓存可以使应用程序的性能得到很大的提高,因此在设计应用程序应该予以考虑,本博文主要介绍了ASP.NET中输出缓存和数据缓存的应用场合和区别。

页面缓存适用于生成的页面通常都相同或改变时间比较固定情况,例如:数据在每小时都会更新,那么我们可以设置duration为3600s。

数据缓存适用生成的页面总是在变化情况。

http://www.codeproject.com/Articles/29899/Exploring-Caching-in-ASP-NET

http://msdn.microsoft.com/zh-cn/library/aa478965.aspx#XSLTsection129121120120

http://www.amazon.com/Beginning-ASP-NET-3-5-2008-Professional/dp/1590598911

时间: 2024-07-31 15:57:44

ASP.NET Cache的一些总结分享的相关文章

asp.net Cache

因微信分享功能,获取access_token(一个toke 套一个token,7200秒过期时间)所以用到了asp.net Cache ,暂时发现Cache是最好用的,可以设置缓存自动过期时间,不说了 直接上代码...就一两行代码....,暂时记下来,方便以后快速回忆代码... //获取缓存 object cacheaccess_token = Cache.Get("access_token"); //添加缓存 Cache.Insert("access_token"

ASP.net Cache丢失的问题诊断

1 业务需求 缓存来自数据库的数据,不用频繁到数据库中加载. 2 使用模型 添加一个类 MyCache,然后在里面添加静态属性字段: public static DataTable FolderData { get { string key = "FolderData"; object o = HttpRuntime.Cache[key]; if (o == null) { //从DB中加载数据 o = LoadFromDB(); //添加到缓存中(分钟过期) HttpRuntime.

细说 ASP.NET Cache 及其高级用法

许多做过程序性能优化的人,或者关注过程程序性能的人,应该都使用过各类缓存技术. 而我今天所说的Cache是专指ASP.NET的Cache,我们可以使用HttpRuntime.Cache访问到的那个Cache,而不是其它的缓存技术. 以前我在[我心目中的Asp.net核心对象] 这篇博客中简单地提过它,今天我打算为它写篇专题博客,专门来谈谈它,因为它实在是太重要了.在这篇博客中, 我不仅要介绍它的一些常见用法,还将介绍它的一些高级用法. 在上篇博客[在.net中读写config文件的各种方法] 的

Asp.Net Cache辅助类

辅助类代码 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Caching; namespace BusinessRules.Common { /// <summary> /// Cache高度缓存 /// </summary> public class CacheManager { #region --Property-- p

细说 ASP.NET Cache 及其高级用法【转】

阅读目录 开始 Cache的基本用途 Cache的定义 Cache常见用法 Cache类的特点 缓存项的过期时间 缓存项的依赖关系 - 依赖其它缓存项 缓存项的依赖关系 - 文件依赖 缓存项的移除优先级 缓存项的移除通知 巧用缓存项的移除通知 实现[延迟操作] 巧用缓存项的移除通知 实现[自动加载配置文件] 文件监视技术的选择 各种缓存方案的共存 许多做过程序性能优化的人,或者关注过程程序性能的人,应该都使用过各类缓存技术. 而我今天所说的Cache是专指ASP.NET的Cache,我们可以使用

ASP.NET Cache缓存的使用

ASP.NET Cache是提升系统性能的重要方法,它使用了“最近使用”原则(a least-recently-used algorithm).在数据库访问中经常会用到Cache保存数据库数据. 1.缓存的添加: Cache的添加方法有Add()或Insert(),两种方法几乎类似,只是Inser方法可以使用可选参数,即使用默认参数,来实现缓存的添加: Cache.Add( KeyName,//缓存名 KeyValue,//要缓存的对象 Dependencies,//依赖项 AbsoluteEx

php仿照asp实现application缓存的代码分享

php 怎么没有asp 那样的application缓存呢?最近我找了很多,都只有自己写,下面我分享一段代码 class php_cache{ //相对或者绝对目录,末尾不要加 '/' var $cache_dir = './cache'; var $cache_extension = '.cache.php'; function set_cache($name, $value){ $pre = "< ?\n//Cache Created at: ".date('Y-m-d H:

ASP.NET cache缓存的用法

本文导读:在.NET运用中经常用到缓存(Cache)对象.有HttpContext.Current.Cache以及HttpRuntime.Cache,HttpRuntime.Cache是应用程序级别的,而HttpContext.Current.Cache是针对当前WEB上下文定义的.HttpRuntime下的除了WEB中可以使用外,非WEB程序也可以使用. 1.HttpRuntime.Cache 相当于就是一个缓存具体实现类,这个类虽然被放在了 System.Web 命名空间下了.但是非 Web

ASP.NET MVC 開發心得分享 (21):Routing 觀念與技巧

ASP.NET MVC 預設在 Global.asax 所定義的 RegisterRoutes 方法中可以輕易的定義你希望擁有的網址格式,嚴格上來講這並非 ASP.NET MVC 的專利,而是從 ASP.NET 3.5 SP1 就加入的新特性,所以就算是傳統的 ASP.NET Web Form 一樣可以利用 Routing 所帶來的好處,今天我就來講一些 Routing 的觀念與技巧. 快速上手 我先解釋在 ASP.NET MVC 專案中 Global.asax 所定義的 Routing 程式碼