ASP.NET MVC3.0 静态化实现

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

     using System.IO;

     using System.Text;

     using System.Web;

     using System.Web.Mvc;

     using NLog;

 

     /// <summary>

     /// 生成静态文件

     /// </summary>

     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]

     public class GenerateStaticFileAttribute : ActionFilterAttribute

     {

         #region 私有属性

 

         private static readonly Logger logger = LogManager.GetCurrentClassLogger();

 

         #endregion

 

         #region 公共属性

 

         /// <summary>

         /// 过期时间,以小时为单位

         /// </summary>

         public int Expiration { get; set; }

 

         /// <summary>

         /// 文件后缀名

         /// </summary>

         public string Suffix { get; set; }

 

         /// <summary>

         /// 缓存目录

         /// </summary>

         public string CacheDirectory { get; set; }

 

         /// <summary>

         /// 指定生成的文件名

         /// </summary>

         public string FileName { get; set; }

 

         #endregion

 

         #region 构造函数

 

         /// <summary>

         /// 默认构造函数

         /// </summary>

         public GenerateStaticFileAttribute()

         {

             Expiration = 1;

             CacheDirectory = AppDomain.CurrentDomain.BaseDirectory;

         }

 

         #endregion

 

         #region 方法

 

         public override void OnResultExecuted(ResultExecutedContext filterContext)

         {

             var fileInfo = GetCacheFileInfo(filterContext);

 

             if ((fileInfo.Exists && fileInfo.CreationTime.AddHours(Expiration) < DateTime.Now) || !fileInfo.Exists)

             {

                 var deleted = false;

 

                 try

                 {

                     if (fileInfo.Exists)

                     {

                         fileInfo.Delete();

                     }

 

                     deleted = true;

                 }

                 catch (Exception ex)

                 {

                     logger.Error("删除文件:{0}发生异常:{1}", fileInfo.FullName, ex.StackTrace);

                 }

 

                 var created = false;

 

                 try

                 {

                     if (!fileInfo.Directory.Exists)

                     {

                         fileInfo.Directory.Create();

                     }

 

                     created = true;

                 }

                 catch (IOException ex)

                 {

                     logger.Error("创建目录:{0}发生异常:{1}", fileInfo.DirectoryName, ex.StackTrace);

                 }

 

                 if (deleted && created)

                 {

                     FileStream fileStream = null;

                     StreamWriter streamWriter = null;

 

                     try

                     {

                         var viewResult = filterContext.Result as ViewResult;

                         fileStream = new FileStream(fileInfo.FullName, FileMode.CreateNew, FileAccess.Write, FileShare.None);

                         streamWriter = new StreamWriter(fileStream);

                         var viewContext = new ViewContext(filterContext.Controller.ControllerContext, viewResult.View, viewResult.ViewData, viewResult.TempData, streamWriter);

                         viewResult.View.Render(viewContext, streamWriter);

                     }

                     catch (Exception ex)

                     {

                         logger.Error("生成缓存文件:{0}发生异常:{1}", fileInfo.FullName, ex.StackTrace);

                     }

                     finally

                     {

                         if (streamWriter != null)

                         {

                             streamWriter.Close();

                         }

 

                         if (fileStream != null)

                         {

                             fileStream.Close();

                         }

                     }

                 }

             }

         }

 

         /// <summary>

         /// 生成文件Key

         /// </summary>

         /// <param name="controllerContext">ControllerContext</param>

         /// <returns>文件Key</returns>

         protected virtual string GenerateKey(ControllerContext controllerContext)

         {

             var url = controllerContext.HttpContext.Request.Url.ToString();

 

             if (string.IsNullOrWhiteSpace(url))

             {

                 return null;

             }

 

             var th = new TigerHash();

             var data = th.ComputeHash(Encoding.Unicode.GetBytes(url));

             var key = Convert.ToBase64String(data, Base64FormattingOptions.None);

             key = HttpUtility.UrlEncode(key);

 

             return key;

         }

 

         /// <summary>

         /// 获取静态的文件信息

         /// </summary>

         /// <param name="controllerContext">ControllerContext</param>

         /// <returns>缓存文件信息</returns>

         protected virtual FileInfo GetCacheFileInfo(ControllerContext controllerContext)

         {

             var fileName = string.Empty;

 

             if (string.IsNullOrWhiteSpace(FileName))

             {

                 var key = GenerateKey(controllerContext);

 

                 if (!string.IsNullOrWhiteSpace(key))

                 {

                     fileName = Path.Combine(CacheDirectory, string.IsNullOrWhiteSpace(Suffix) ? key : string.Format("{0}.{1}", key, Suffix));

                 }

             }

             else

             {

                 fileName = Path.Combine(CacheDirectory, FileName);

             }

 

             return new FileInfo(fileName);

         }

 

         #endregion

     }

如果大家对于生成的文件和目录有特殊的要求,那可以重写GetCacheFileInfo方法,比如按照日期生成目录等等更复杂的目录和文件结构。当然以上代码只是提供了生成静态页的方法,但是访问如何解决呢? 访问静态文件和规则就需要在HttpApplication的Application_BeginRequest实现了。首先可以设置需要静态化访问的路由地址以html结尾。下面的是一个用于首页的静态化访问的实现,很简单,当然你可以实现比较复杂的逻辑,比如根据文件时间来判断是否应该访问静态文件等等。

protected void Application_BeginRequest(object sender, EventArgs e)

         {

             StaticContentRewrite();

         }

 

         /// <summary>

         /// 处理静态发布内容

         /// </summary>

         private void StaticContentRewrite()

         {

             if (Context.Request.FilePath == "/" || Context.Request.FilePath.StartsWith("/index.html", StringComparison.OrdinalIgnoreCase))

             {

                 if (File.Exists(Server.MapPath("index.html")))

                 {

                     Context.RewritePath("index.html");

                 }

             }

  

  

你可能感兴趣的:(asp.net)