asp.net core生成html页面

Laughing
2017-12-04 / 0 评论 / 1,408 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2021年04月27日,已超过1361天没有更新,若内容或图片失效,请留言反馈。

为了缓解服务器的压力,我们可以将一些不经常更新的页面生成html页面,然后保存到服务器,页面进行查询时,我们先查找html是否存在,如果存在,我们直接返回html页面,否则就生成对应的html页面。这里我们通过动作过滤器ActionFilterAttribute实现。

定义属性

using Microsoft.AspNetCore.Mvc;  
using Microsoft.AspNetCore.Mvc.Filters;  
using Microsoft.AspNetCore.Mvc.Rendering;  
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;  
using Microsoft.Extensions.DependencyInjection;  
using Microsoft.Extensions.Options;  
using System;  
using System.Collections.Generic;  
using System.IO;  
using System.Linq;  
using System.Text;  
using System.Threading.Tasks;  
  
namespace xiangcaowuyu.net.Public.Attribute  
{  
    /// <summary>  
    /// 实现伪静态  
    /// </summary>  
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]  
    public class StaticFileHandlerFilterAttribute : ActionFilterAttribute  
    {  
        public string Key  
        {  
            get; set;  
        }  
        /// <summary>  
        /// 动作执行后  
        /// </summary>  
        /// <param name="context"></param>  
        public override void OnActionExecuted(ActionExecutedContext context)  
        {  
            //获取结果  
            IActionResult actionResult = context.Result;  
            //判断结果是否是一个ViewResult  
            if (actionResult is ViewResult)  
            {  
                ViewResult viewResult = actionResult as ViewResult;  
                //下面的代码就是执行这个ViewResult,并把结果的html内容放到一个StringBuiler对象中  
                var services = context.HttpContext.RequestServices;  
                var executor = services.GetRequiredService<ViewResultExecutor>();  
                var option = services.GetRequiredService<IOptions<MvcViewOptions>>();  
                var result = executor.FindView(context, viewResult);  
                result.EnsureSuccessful(originalLocations: null);  
                var view = result.View;  
                StringBuilder builder = new StringBuilder();  
                using (var writer = new StringWriter(builder))  
                {  
                    var viewContext = new ViewContext(  
                        context,  
                        view,  
                        viewResult.ViewData,  
                        viewResult.TempData,  
                        writer,  
                        option.Value.HtmlHelperOptions);  
                    view.RenderAsync(viewContext).GetAwaiter().GetResult();  
                    //这句一定要调用,否则内容就会是空的  
                    writer.Flush();  
                }  
                //按照规则生成静态文件名称  
                string controllerName = context.RouteData.Values["controller"].ToString().ToLower();  
                string actionName = context.RouteData.Values["action"].ToString().ToLower();  
                string id = context.RouteData.Values.ContainsKey(Key) ? context.RouteData.Values[Key].ToString() : "";  
                if (string.IsNullOrEmpty(id) && context.HttpContext.Request.Query.ContainsKey(Key))  
                {  
                    id = context.HttpContext.Request.Query[Key];  
                }  
                string devicedir = Path.Combine(AppContext.BaseDirectory, "wwwroot");  
                if (!Directory.Exists(devicedir))  
                {  
                    Directory.CreateDirectory(devicedir);  
                }  
                //写入文件  
                string filePath = Path.Combine(AppContext.BaseDirectory, "wwwroot", controllerName + "-" + actionName + (string.IsNullOrEmpty(id) ? "" : ("-" + id)) + ".html");  
                using (FileStream fs = File.Open(filePath, FileMode.Create))  
                {  
                    using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))  
                    {  
                        sw.Write(builder.ToString());  
                    }  
                }  
                //输出当前的结果  
                ContentResult contentresult = new ContentResult();  
                contentresult.Content = builder.ToString();  
                contentresult.ContentType = "text/html";  
                context.Result = contentresult;  
            }  
        }  
  
        /// <summary>  
        /// 动作执行前  
        /// </summary>  
        /// <param name="context"></param>  
        public override void OnActionExecuting(ActionExecutingContext context)  
        {  
            //按照一定的规则生成静态文件的名称,这里是按照area+"-"+controller+"-"+action+key规则生成  
            string controllerName = context.RouteData.Values["controller"].ToString().ToLower();  
            string actionName = context.RouteData.Values["action"].ToString().ToLower();  
            //这里的Key默认等于id,当然我们可以配置不同的Key名称  
            string id = context.RouteData.Values.ContainsKey(Key) ? context.RouteData.Values[Key].ToString() : "";  
            if (string.IsNullOrEmpty(id) && context.HttpContext.Request.Query.ContainsKey(Key))  
            {  
                id = context.HttpContext.Request.Query[Key];  
            }  
            string filePath = Path.Combine(AppContext.BaseDirectory, "wwwroot", controllerName + "-" + actionName + (string.IsNullOrEmpty(id) ? "" : ("-" + id)) + ".html");  
            //判断文件是否存在  
            if (File.Exists(filePath))  
            {  
                FileInfo fileInfo = new FileInfo(filePath);  
                TimeSpan timeSpan = DateTime.Now - fileInfo.CreationTime;  
                if (timeSpan.TotalDays <= 1)  
                {  
                    //如果存在,直接读取文件  
                    using (FileStream fs = File.Open(filePath, FileMode.Open))  
                    {  
                        using (StreamReader sr = new StreamReader(fs, Encoding.UTF8))  
                        {  
                            //通过contentresult返回文件内容  
                            ContentResult contentresult = new ContentResult();  
                            contentresult.Content = sr.ReadToEnd();  
                            contentresult.ContentType = "text/html";  
                            context.Result = contentresult;  
                        }  
                    }  
                }  
            }  
        }  
    }  
}

使用

我们可以通过将属性设置到类或者方法上面来使用

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Threading.Tasks;  
using Microsoft.AspNetCore.Http;  
using Microsoft.AspNetCore.Mvc;  
using xiangcaowuyu.net.Models.Entity;  
using xiangcaowuyu.net.Public.ArticleHelper;  
using xiangcaowuyu.net.Public.MenuHelper;  
using Microsoft.AspNetCore.Authorization;  
using xiangcaowuyu.net.Public.Attribute;  
  
namespace xiangcaowuyu.net.Controllers  
{  
    [StaticFileHandlerFilter(Key = "id")]  
    public class ArticleController : BaseController  
    {  
        private readonly IArticleHelper articleHelper;  
  
        public ArticleController(IArticleHelper articleHelper, IMenuHelper menuHelper) : base(menuHelper)  
        {  
            this.articleHelper = articleHelper;  
        }  
  
        // GET: Article  
        public ActionResult Index()  
        {  
            List<Article> list = articleHelper.GetList();  
            return View(list);  
        }  
  
        // GET: Article/Details/5  
        [StaticFileHandlerFilter(Key = "id")]  
        public ActionResult Details(string id)  
        {  
            Article article = articleHelper.GetArticle(id);  
            return View(article);  
        }  
  
        // GET: Article/Create  
        [Authorize(Roles = "admin")]  
        public ActionResult Create()  
        {  
            return View();  
        }  
  
        // POST: Article/Create  
        [HttpPost]  
        [ValidateAntiForgeryToken]  
        [Authorize(Roles = "admin")]  
        public ActionResult Create(Article article)  
        {  
            try  
            {  
                articleHelper.InsertArticle(article);  
                return RedirectToAction(nameof(Index));  
            }  
            catch  
            {  
                return View();  
            }  
        }  
  
        // GET: Article/Edit/5  
        [Authorize(Roles = "admin")]  
        public ActionResult Edit(string id)  
        {  
            Article article = articleHelper.GetArticle(id);  
            return View(article);  
        }  
  
        // POST: Article/Edit/5  
        [HttpPost]  
        [ValidateAntiForgeryToken]  
        [Authorize(Roles = "admin")]  
        public ActionResult Edit(string id, Article article)  
        {  
            try  
            {  
                // TODO: Add update logic here  
                articleHelper.EditArticle(article);  
                return RedirectToAction(nameof(Index));  
            }  
            catch  
            {  
                return View();  
            }  
        }  
  
        // GET: Article/Delete/5  
        [Authorize(Roles = "admin")]  
        public ActionResult Delete(string id)  
        {  
            if (articleHelper.DeleteArticle(id))  
            {  
                ViewBag.IsDeleted = "删除成功";  
            }  
            else  
            {  
                ViewBag.IsDeleted = "删除失败";  
            }  
            return View();  
        }  
  
        // POST: Article/Delete/5  
        [HttpPost]  
        [ValidateAntiForgeryToken]  
        [Authorize(Roles = "admin")]  
        public ActionResult Delete(string id, IFormCollection collection)  
        {  
            try  
            {  
                // TODO: Add delete logic here  
  
                return RedirectToAction(nameof(Index));  
            }  
            catch  
            {  
                return View();  
            }  
        }  
    }  
}

查看结果

我们查看wwroot页面,可以查看生成的html页面

2

评论 (0)

取消
  1. 头像
    Panacea
    Windows 7 · Google Chrome

    哇,还要在要回复一次?

    回复
  2. 头像
    perry
    MacOS · Safari

    怎么看不了啊

    回复