靜態化處理,能夠大大提升客戶的訪問瀏覽速度,提升用戶體驗,同時也下降了服務器自己的壓力。在asp.net mvc3中,能夠相對容易地處理靜態化問題,不用過多考慮靜態網頁的同步,生成等等問題。我提供這個方法很簡單,就須要在須要靜態化處理的Controller或Action上加一個Attribute就能夠。下面是我寫的一個生成靜態文件的ActionFilterAttribute。html
2
using System.IO;
3
using System.Text;
4
using System.Web;
5
using System.Web.Mvc;
6
using NLog;
7
8
///
<summary>
9
///
生成靜態文件
10
///
</summary>
11 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited =
true, AllowMultiple =
true)]
12
public
class GenerateStaticFileAttribute : ActionFilterAttribute
13 {
14
#region 私有屬性
15
16
private
static
readonly Logger logger = LogManager.GetCurrentClassLogger();
17
18
#endregion
19
20
#region 公共屬性
21
22
///
<summary>
23
///
過時時間,以小時爲單位
24
///
</summary>
25
public
int Expiration {
get;
set; }
26
27
///
<summary>
28
///
文件後綴名
29
///
</summary>
30
public
string Suffix {
get;
set; }
31
32
///
<summary>
33
///
緩存目錄
34
///
</summary>
35
public
string CacheDirectory {
get;
set; }
36
37
///
<summary>
38
///
指定生成的文件名
39
///
</summary>
40
public
string FileName {
get;
set; }
41
42
#endregion
43
44
#region 構造函數
45
46
///
<summary>
47
///
默認構造函數
48
///
</summary>
49
public GenerateStaticFileAttribute()
50 {
51 Expiration =
1;
52 CacheDirectory = AppDomain.CurrentDomain.BaseDirectory;
53 }
54
55
#endregion
56
57
#region 方法
58
59
public
override
void OnResultExecuted(ResultExecutedContext filterContext)
60 {
61
var fileInfo = GetCacheFileInfo(filterContext);
62
63
if ((fileInfo.Exists && fileInfo.CreationTime.AddHours(Expiration) < DateTime.Now) || !fileInfo.Exists)
64 {
65
var deleted =
false;
66
67
try
68 {
69
if (fileInfo.Exists)
70 {
71 fileInfo.Delete();
72 }
73
74 deleted =
true;
75 }
76
catch (Exception ex)
77 {
78 logger.Error(
"
刪除文件:{0}發生異常:{1}
", fileInfo.FullName, ex.StackTrace);
79 }
80
81
var created =
false;
82
83
try
84 {
85
if (!fileInfo.Directory.Exists)
86 {
87 fileInfo.Directory.Create();
88 }
89
90 created =
true;
91 }
92
catch (IOException ex)
93 {
94 logger.Error(
"
建立目錄:{0}發生異常:{1}
", fileInfo.DirectoryName, ex.StackTrace);
95 }
96
97
if (deleted && created)
98 {
99 FileStream fileStream =
null;
100 StreamWriter streamWriter =
null;
101
102
try
103 {
104
var viewResult = filterContext.Result
as ViewResult;
105 fileStream =
new FileStream(fileInfo.FullName, FileMode.CreateNew, FileAccess.Write, FileShare.None);
106 streamWriter =
new StreamWriter(fileStream);
107
var viewContext =
new ViewContext(filterContext.Controller.ControllerContext, viewResult.View, viewResult.ViewData, viewResult.TempData, streamWriter);
108 viewResult.View.Render(viewContext, streamWriter);
109 }
110
catch (Exception ex)
111 {
112 logger.Error(
"
生成緩存文件:{0}發生異常:{1}
", fileInfo.FullName, ex.StackTrace);
113 }
114
finally
115 {
116
if (streamWriter !=
null)
117 {
118 streamWriter.Close();
119 }
120
121
if (fileStream !=
null)
122 {
123 fileStream.Close();
124 }
125 }
126 }
127 }
128 }
129
130
///
<summary>
131
///
生成文件Key
132
///
</summary>
133
///
<param name="controllerContext">
ControllerContext
</param>
134
///
<returns>
文件Key
</returns>
135
protected
virtual
string GenerateKey(ControllerContext controllerContext)
136 {
137
var url = controllerContext.HttpContext.Request.Url.ToString();
138
139
if (
string.IsNullOrWhiteSpace(url))
140 {
141
return
null;
142 }
143
144
var th =
new TigerHash();
145
var data = th.ComputeHash(Encoding.Unicode.GetBytes(url));
146
var key = Convert.ToBase64String(data, Base64FormattingOptions.None);
147 key = HttpUtility.UrlEncode(key);
148
149
return key;
150 }
151
152
///
<summary>
153
///
獲取靜態的文件信息
154
///
</summary>
155
///
<param name="controllerContext">
ControllerContext
</param>
156
///
<returns>
緩存文件信息
</returns>
157
protected
virtual FileInfo GetCacheFileInfo(ControllerContext controllerContext)
158 {
159
var fileName =
string.Empty;
160
161
if (
string.IsNullOrWhiteSpace(FileName))
162 {
163
var key = GenerateKey(controllerContext);
164
165
if (!
string.IsNullOrWhiteSpace(key))
166 {
167 fileName = Path.Combine(CacheDirectory,
string.IsNullOrWhiteSpace(Suffix) ? key :
string.Format(
"
{0}.{1}
", key, Suffix));
168 }
169 }
170
else
171 {
172 fileName = Path.Combine(CacheDirectory, FileName);
173 }
174
175
return
new FileInfo(fileName);
176 }
177
178
#endregion
179 }
若是你們對於生成的文件和目錄有特殊的要求,那能夠重寫GetCacheFileInfo方法,好比按照日期生成目錄等等更復雜的目錄和文件結構。固然以上代碼只是提供了生成靜態頁的方法,可是訪問如何解決呢? 訪問靜態文件和規則就須要在HttpApplication的Application_BeginRequest實現了。首先能夠設置須要靜態化訪問的路由地址以html結尾。下面的是一個用於首頁的靜態化訪問的實現,很簡單,固然你能夠實現比較複雜的邏輯,好比根據文件時間來判斷是否應該訪問靜態文件等等。服務器
1
protected
void Application_BeginRequest(
object sender, EventArgs e)
2 {
3 StaticContentRewrite();
4 }
5
6
///
<summary>
7
///
處理靜態發佈內容
8
///
</summary>
9
private
void StaticContentRewrite()
10 {
11
if (Context.Request.FilePath ==
"
/
" || Context.Request.FilePath.StartsWith(
"
/index.html
", StringComparison.OrdinalIgnoreCase))
12 {
13
if (File.Exists(Server.MapPath(
"
index.html
")))
14 {
15 Context.RewritePath(
"
index.html
");
16 }
17 }