MVC 3.5中动态页面的静态化实现

静态化处理,可以大大提高客户的访问浏览速度,提高用户体验,同时也降低了服务器本身的压力。在asp.net mvc3中,可以相对容易地处理静态化问题,不用过多考虑静态网页的同步,生成等等问题。我提供这个方法很简单,就需要在需要静态化处理的Controller或Action上加一个Attribute就可以。下面是我写的一个生成静态文件的ActionFilterAttribute。

 

   1     using System;

 

  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             }

18         }

摘自 easynet

posted @ 2012-11-07 17:14  鸿鹄_A  阅读(393)  评论(0编辑  收藏  举报