前言

上一篇文章《ASP.NET Core 中的SEO优化(1):中间件实现服务端静态化缓存》中介绍了中间件的使用方法、以及使用中间件实现服务端静态化缓存的功能。本系列文章的这些技巧都是我最近在做的公司实际项目中的一些奇怪的需求之后总结而来的……

要解决的问题

好了,本篇说说如何在中间件中渲染Razor视图。之所以会有这个技巧,是因为我们有个需求:

需要在所有返回404状态的路由都输出一个特定视图。

比如当有id=1的文章,而没有id=2的文章时,那么/url/1.html展示文章详情页,/url/2.html展示404视图。

所以,要实现这个需求只有两种办法:

  1. 当文章查找不到时直接执行return View("404")返回404视图。
  2. 在中间件中执行完MVC的处理之后检查返回状态,如果是错误状态就直接渲染视图并输出。

由于CMS系统中不止一处需要返回404状态,所以因为用代码整洁作为懒惰的借口,决定尝试第二个方法。

实现

实现方式很简单,就是在Configure中注入ICompositeViewEngine实例,构造视图上下文,再渲染视图为字符串,最后输出。其它的分析就在代码注释中说明吧。

直接上代码:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ICompositeViewEngine engine)
{
app.Use(async (context, next) =>
{
//因为只是在请求最后处理,所以这里直接就运行下一个中间件
await next();
//返回后检查是否出现错误的状态
if (context.Response.StatusCode >= 400)
{
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
//ContentType设置为text/html,使浏览器以正常页面的格式显示
context.Response.ContentType = "text/html";
//指向特定的视图
var viewResult = engine.GetView("~/", "~/Views/Default/Home/Error.cshtml", true); if (!viewResult.Success)
await context.Response.WriteAsync("OMG! 连错误视图都找不到了。。");
//创建临时的StringWriter实例,用来配置到视图上下文中
using (var output = new StringWriter())
{
//视图上下文对于视图渲染来说很重要,视图中的前后台交互都需要它
var viewContext = new ViewContext()
{
HttpContext = context,
Writer = output,
RouteData = new Microsoft.AspNetCore.Routing.RouteData()
{
//RouteData在这里传入视图,这样视图可以显示错误信息之类的数据
},
View = viewResult.View,
FormContext = new FormContext(),
ActionDescriptor = new Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor()
};
//渲染
await viewResult.View.RenderAsync(viewContext);
//输出到响应体
await context.Response.WriteAsync(output.ToString());
}
}
}); //后面是Mvc的中间件,执行Mvc的处理
//...app.UseMvc
}

总结

这个技巧还能用于单页面应用程序的路由重定向,把所有路由都输出入口页面代码。

ASP.NET Core 中的SEO优化(2):中间件中渲染Razor视图的更多相关文章

  1. ASP.NET Core 中的SEO优化(4):自定义视图路径及主题切换

    系列回顾 <ASP.NET Core 中的SEO优化(1):中间件实现服务端静态化缓存> <ASP.NET Core 中的SEO优化(2):中间件中渲染Razor视图> < ...

  2. ASP.NET Core 中的SEO优化(3):自定义路由匹配和生成

    前言 前两篇文章主要总结了CMS系统两个技术点在ASP.NET Core中的应用: <ASP.NET Core 中的SEO优化(1):中间件实现服务端静态化缓存> <ASP.NET ...

  3. 创建ASP.NET Core MVC应用程序(4)-添加CRUD动作方法和视图

    创建ASP.NET Core MVC应用程序(4)-添加CRUD动作方法和视图 创建CRUD动作方法及视图 参照VS自带的基架(Scaffold)系统-MVC Controller with view ...

  4. ASP.NET Core 中的SEO优化(1):中间件实现服务端静态化缓存

    分享 最近在公司成功落地了一个用ASP.NET Core 开发前台的CMS项目,虽然对于表层的开发是兼容MVC5的,但是作为爱好者当然要用尽量多的ASP.NET Core新功能了. 背景 在项目开发的 ...

  5. ASP.NET Core 数据保护(Data Protection)【中】

    前言 上篇主要是对 ASP.NET Core 的 Data Protection 做了一个简单的介绍,本篇主要是介绍一下API及使用方法. API 接口 ASP.NET Core Data Prote ...

  6. 制作移动端手机网站过程中的SEO优化方法技巧

    据国内三大运营商数据来看,中国的手机用户数已达10亿,超过2/5的移动用户每个月都会从手机终端访问网页,如今的移动端手机网站比例肯定有提升,但是对于这些存在的移动版本网站来说,马海祥查看了很大一部分手 ...

  7. ASP.NET CORE MVC 2.0 如何在Filter中使用依赖注入来读取AppSettings,及.NET Core控制台项目中读取AppSettings

    问: ASP.NET CORE MVC 如何在Filter中使用依赖注入来读取AppSettings 答: Dependency injection is possible in filters as ...

  8. 探索ASP.Net Core 3.0系列六:ASP.NET Core 3.0新特性启动信息中的结构化日志

    前言:在本文中,我将聊聊在ASP.NET Core 3.0中细小的变化——启动时记录消息的方式进行小的更改. 现在,ASP.NET Core不再将消息直接记录到控制台,而是正确使用了logging 基 ...

  9. asp.net core 3.1 入口:Program.cs中的Main函数

    本文分析Program.cs 中Main()函数中代码的运行顺序分析asp.net core程序的启动,重点不是剖析源码,而是理清程序开始时执行的顺序.到底用了哪些实例,哪些法方. asp.net c ...

随机推荐

  1. Spring MVC 方法注解拦截器

    应用场景,在方法级别对本次调用进行鉴权,如api接口中有个用户唯一标示accessToken,对于有accessToken的每次请求可以在方法加一个拦截器,获得本次请求的用户,存放到request或者 ...

  2. python学习笔记(字典乱码)

    博主总结下 python中字典中包含中文时,使用过程中出现乱码 json.dumps(params, encoding="UTF-8", ensure_ascii=False) p ...

  3. Java中unicode增补字符(辅助平面)相关用法简介

    转载自 http://blog.csdn.net/gjb724332682/article/details/51324036 前言 Java从1.5版本开始,加入了unicode辅助平面的支持.相关的 ...

  4. guava的事件发布订阅功能

    事件的重要性,不用说很重要,在很多时候我们做完一个操作的时候,需要告知另外一个对象让他执行相应操作,比如当用户注册成功的时候,需要抛出一个注册成功的事件,那么有监听器捕获到这个事件,完成后续用户信息初 ...

  5. SpringMVC - 多个同名name提交与后台参数解析

    简洁来说,就是form表单有多个input(checkbox,hidden),name同名,后台是如何接收的. [1]多个inpu 同名name form表单如下: <form action=& ...

  6. Zeratul的完美区间(线段树||RMQ模板题)

    原题大意:原题链接 给定元素无重复数组,查询给定区间内元素是否连续 解体思路:由于无重复元素,所以如果区间内元素连续,则该区间内的最大值和最小值之差应该等于区间长度(r-l) 解法一:线段树(模板题) ...

  7. Mycat跨分片Join

    1 前言 Mycat目前版本支持跨分片的join,主要实现的方式有四种. 全局表 ER分片 HBT(参考MyCAT人工智能解决跨分片SQL.docx) ShareJoin ShareJoin在开发版中 ...

  8. java语言基础-变量

    一丶变量的基本概念 1.什么是变量 (1).内存中的一个存储区域 (2).该区域有自己的名称(变量名),和类型(数据类型) (3.)该区域的数据可以在同一类型范围内不断变化(定义变量的主要目的是因为数 ...

  9. 20165202 week10课下补做

    相关知识点总结 在数据结构和算法中,排序是很重要的操作,要让一个类可以进行排序,有两种方法: 有类的源代码,针对某一成员变量排序,让类实现Comparable接口,调用Collection.sort( ...

  10. PostgreSQL时间格式及相关函数实践

    在创建表的时候,有客户需要将时间转为字符串,而且要求了具体的格式,如:20181115101010001.方便记录数据的更新时间,貌似是给Mysql使用,当时就很蛋疼,时间格式存储子啊数据库中就是va ...