asp.net mvc3的静态化实现

本文介绍如何在ASP.NET MVC中使用ActionFilterAttribute来生成静态页面,包括配置静态文件生成、缓存管理以及访问静态文件的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在需要静态化处理的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");
                }
            }

By:Mr.Yang 转载




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值