在 asp.net core 的中间件中返回具体的页面的实现方法

前言

在 asp.net core 中,存在着中间件这一概念,在中间件中,我们可以比过滤器更早的介入到 http 请求管道,从而实现对每一次的 http 请求、响应做切面处理,从而实现一些特殊的功能

在使用中间件时,我们经常实现的是鉴权、请求日志记录、全局异常处理等等这种非业务性的需求,而如果你有在 asp.net core 中使用过 swashbuckle(swagger)、health check、mini profiler 等等这样的组件的话,你会发现,这些第三方的组件往往都提供了页面,允许我们通过可视化的方式完成某些操作或浏览某些数据

因为自己也需要实现类似的功能,虽然使用到的知识点很少、也很简单,但是在网上搜了搜也没有专门介绍这块的文档或文章,所以本篇文章就来说明如何在中间件中返回页面,如果你有类似的需求,希望可以对你有所帮助

Step by Step

最终实现的功能其实很简单,当用户跳转到某个指定的地址后,自定义的中间件通过匹配到该路径,从而返回指定的页面,所以这里主要会涉及到中间件是如何创建,以及如何处理页面中的静态文件引用

因为这块并不会包含很多的代码,所以这里主要是通过分析 Swashbuckle.AspNetCore 的代码,了解它是如何实现的这一功能,从而给我们的功能实现提供一个思路

在 asp.net core 中使用 Swashbuckle.AspNetCore 时,我们通常需要在 Startup 类中针对组件做如下的配置,根据当前程序的信息生成 json 文件 =》 公开生成的 json 文件地址 =》 根据 json 文件生成可视化的交互页面

public class Startup
{
 // This method gets called by the runtime. Use this method to add services to the container.
 public void ConfigureServices(IServiceCollection services)
 {
  // 生成 swagger 配置的 json 文件
  services.AddSwaggerGen(s =>
  {
   s.SwaggerDoc("v1", new OpenApiInfo
   {
    Contact = new OpenApiContact
    {
     Name = "Danvic Wang",
     Url = new Uri("https://yuiter.com"),
    },
    Description = "Template.API - ASP.NET Core 后端接口模板",
    Title = "Template.API",
    Version = "v1"
   });

   // 参数使用驼峰的命名方式
   s.DescribeAllParametersInCamelCase();
  });
 }

 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
 {
  // 公开 swagger 生成的 json 文件节点
  app.UseSwagger();

  // 启用 swagger 可视化交互页面
  app.UseSwaggerUI(s =>
  {
   s.SwaggerEndpoint($"/swagger/v1/swagger.json",
    $"Swagger doc v1");
  });
 }
}

可以看到最终呈现给用户的页面,其实是在 Configure 方法中通过调用 UseSwaggerUI 方法来完成的,这个方法是在 Swashbuckle.AspNetCore.SwaggerUI 这个程序集中,所以这里直接从 github 上找到对应的文件夹,clone 下源代码,来看下是如何实现在中间件中返回特定的页面

在 clone 下的代码中,排除掉一些 c#、node.js 使用到的项目性文件,可以看到整个项目中的文件按照功能可以分为三大块,其中最核心的则是在 SwaggerUIMiddleware 类中,因此,这里主要聚焦在这个中间件类的实现

在一个 asp.net core 中间件中,核心的处理逻辑是在 Invoke/InvokeAsync 方法中,结合我们使用 swagger 时的场景,可以看到,在将组件中所包含的页面呈现给用户时,主要存在如下两个处理逻辑

1、当匹配到用户访问的是 /swagger 时,返回 301 的 http 状态码,浏览器重定向到 /swagger/index.html,从而再次触发该中间件的执行

2、当匹配到请求的地址为 /swagger/index.html 时,将嵌入到程序集中的文件通过 stream 流的形式获取到,转换成字符串,再指定请求的响应的类型为 text/html,从而实现将页面返回给用户

public async Task Invoke(HttpContext httpContext)
{
 var httpMethod = httpContext.Request.Method;
 var path = httpContext.Request.Path.Value;

 // If the RoutePrefix is requested (with or without trailing slash), redirect to index URL
 if (httpMethod == "GET" && Regex.IsMatch(path, $"^/?{Regex.Escape(_options.RoutePrefix)}/?$"))
 {
  // Use relative redirect to support proxy environments
  var relativeRedirectPath = path.EndsWith("/")
   ? "index.html"
   : $"{path.Split('/').Last()}/index.html";

  RespondWithRedirect(httpContext.Response, relativeRedirectPath);
  return;
 }

 if (httpMethod == "GET" && Regex.IsMatch(path, $"^/{Regex.Escape(_options.RoutePrefix)}/?index.html$"))
 {
  await RespondWithIndexHtml(httpContext.Response);
  return;
 }

 await _staticFileMiddleware.Invoke(httpContext);
}

这里需要注意,因为类似于这种功能,我们可能会打包成独立的 nuget 包,然后通过 nuget 进行引用,所以为了能够正确获取到页面及其使用到的静态资源文件,我们需要将这些静态文件的属性修改成嵌入的资源,从而在打包时可以包含在程序集中

对于网页来说,在引用这些静态资源文件时存在一种相对的路径关系,因此,这里在中间件的构造函数中,我们需要将页面需要使用到的静态文件,通过构建 StaticFileMiddleware 中间件,将文件映射与网页相同的 /swagger 路径下面,从而确保页面所需的资源可以正确加载

public class SwaggerUIMiddleware
{
 private const string EmbeddedFileNamespace = "Swashbuckle.AspNetCore.SwaggerUI.node_modules.swagger_ui_dist";

 private readonly SwaggerUIOptions _options;
 private readonly StaticFileMiddleware _staticFileMiddleware;

 public SwaggerUIMiddleware(
  RequestDelegate next,
  IHostingEnvironment hostingEnv,
  ILoggerFactory loggerFactory,
  SwaggerUIOptions options)
 {
  _options = options ?? new SwaggerUIOptions();

  _staticFileMiddleware = CreateStaticFileMiddleware(next, hostingEnv, loggerFactory, options);
 }

 private StaticFileMiddleware CreateStaticFileMiddleware(
  RequestDelegate next,
  IHostingEnvironment hostingEnv,
  ILoggerFactory loggerFactory,
  SwaggerUIOptions options)
 {
  var staticFileOptions = new StaticFileOptions
  {
   RequestPath = string.IsNullOrEmpty(options.RoutePrefix) ? string.Empty : $"/{options.RoutePrefix}",
   FileProvider = new EmbeddedFileProvider(typeof(SwaggerUIMiddleware).GetTypeInfo().Assembly, EmbeddedFileNamespace),
  };

  return new StaticFileMiddleware(next, hostingEnv, Options.Create(staticFileOptions), loggerFactory);
 }
}

当完成了页面的呈现后,因为一般我们会创建一个单独的类库来实现这些功能,在页面中,可能会包含前后端的数据交互,由于我们在宿主的 API 项目中已经完成了对于路由规则的设定,所以这里只需要在类库中通过 nuget 引用 Microsoft.AspNetCore.Mvc.Core ,然后与 Web API 一样的定义 controller,确保这个中间件在宿主程序的调用位于路由匹配规则之后即可

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
 if (env.IsDevelopment())
 {
  app.UseDeveloperExceptionPage();
 }

 app.UseHttpsRedirection();

 app.UseRouting();

 app.UseAuthorization();

	// Endpoint 路由规则设定
 app.UseEndpoints(endpoints =>
 {
  endpoints.MapControllers();
 });

 // 自定义中间件
 app.UseMiddleware<SampleUIMiddleware>();
}

参考:https://www.jb51.net/article/116369.htm

总结

到此这篇关于在 asp.net core 的中间件中返回具体的页面的实现方法的文章就介绍到这了,更多相关asp.net core 中间件返回具体的页面内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 浅谈ASP.NET Core中间件实现分布式 Session

    1.1. 中间件原理 1.1.1. 什么是中间件 中间件是段代码用于处理请求和响应,通常多个中间件链接起来形成管道,由每个中间件自己来决定是否要调用下一个中间件. 1.1.2. 中间件执行过程 举一个示例来演示中间件的执行过程(分别有三个中间件:日志记录.权限验证和路由):当请求进入应用程序时,执行执行日志记录的中间件,它记录请求属性并调用链中的下一个中间件权限验证,如果权限验证通过则将控制权传递给下一个中间件,不通过则设置401 HTTP代码并返回响应,响应传递给日志中间件进行返回. 1.1.

  • 浅谈ASP.NET Core 中间件详解及项目实战

    前言 本篇文章是我们在开发自己的项目中实际使用的,比较贴合实际应用,算是对中间件的一个深入使用了,不是简单的Hello World. 中间件(Middleware)的作用 我们知道,任何的一个web框架都是把http请求封装成一个管道,每一次的请求都是经过管道的一系列操作,最终到达我们写的代码中.那么中间件就是在应用程序管道中的一个组件,用来拦截请求过程进行一些其他处理和响应.中间件可以有很多个,每一个中间件都可以对管道中的请求进行拦截,它可以决定是否将请求转移给下一个中间件. asp.net

  • 详解在ASP.NET Core 中使用Cookie中间件

    在 http:// ASP.NET Core 中使用Cookie中间件 ASP.NET Core 提供了Cookie中间件来序列化用户主题到一个加密的Cookie中并且在后来的请求中校验这个Cookie,再现用户并且分配到HttpContext对象的User属性中.如果你想提供自己的登录方式和用户数据你可以使用Cookie中间件来实现独立的功能. 添加和配置 第一步是增加Cookie中间件到你的应用中.首先使用nuget增加Microsoft.AspNetCore.Authentication.

  • Asp.Net Core 通过中间件防止图片盗链的实例

    一.原理 要实现防盗链,我们就必须先理解盗链的实现原理,提到防盗链的实现原理就不得不从HTTP协议说起,在HTTP协议中,有一个表头字段叫referer,采用URL的格式来表示从哪儿链接到当前的网页或文件.换句话说,通过referer,网站可以检测目标网页访问的来源网页,如果是资源文件,则可以跟踪到显示它的网页地址.有了referer跟踪来源就好办了,这时就可以通过技术手段来进行处理,一旦检测到来源不是本站即进行阻止或者返回指定的页面.如果想对自己的网站进行防盗链保护,则需要针对不同的情况进行区

  • 在 asp.net core 的中间件中返回具体的页面的实现方法

    前言 在 asp.net core 中,存在着中间件这一概念,在中间件中,我们可以比过滤器更早的介入到 http 请求管道,从而实现对每一次的 http 请求.响应做切面处理,从而实现一些特殊的功能 在使用中间件时,我们经常实现的是鉴权.请求日志记录.全局异常处理等等这种非业务性的需求,而如果你有在 asp.net core 中使用过 swashbuckle(swagger).health check.mini profiler 等等这样的组件的话,你会发现,这些第三方的组件往往都提供了页面,允

  • ASP.NET Core自定义中间件如何读取Request.Body与Response.Body的内容详解

    背景# 最近在徒手造轮子,编写一个ASP.NET Core的日志监控器,其中用到了自定义中间件读取Request.Body和Response.Body的内容,但是编写过程,并不像想象中的一帆风顺,ASP.NET Core针对Request.Body和Response.Body的几个特殊设计,导致了完成以上功能需要绕一些弯路. 原始代码# 为了读取Request.Body和Response.Body的内容,我的实现思路如下: 创建一个LoggerMiddleware的中间件,将它放置在项目中间件管

  • ASP.NET Core 2.0中Razor页面禁用防伪令牌验证

    在这篇短文中,我将向您介绍如何ASP.NET Core Razor页面中禁用防伪令牌验证. Razor页面是ASP.NET Core 2.0中增加的一个页面控制器框架,用于构建动态的.数据驱动的网站:支持跨平台开发,可以部署到Windows,Unix和Mac操作系统. 跨站点请求伪造(也称为XSRF或CSRF)是对Web托管应用程序的攻击,因为恶意网站可能会影响客户端浏览器和浏览器信任网站之间的交互.这种攻击是完全有可能的,因为Web浏览器会自动在每一个请求中发送某些身份验证令牌到请求网站.这种

  • ASP.NET Core 应用程序中的静态文件中间件的实现

    在这篇文章中,我将向大家介绍,如何使用中间件组件来处理静态文件.这篇文章中,我们讨论下面几个问题: 在ASP.NET Core中,我们需要把静态文件存放在哪里? 在ASP.NET Core中 wwwroot文件夹是啥? 怎样在ASP.NET Core应用程序中,配置静态文件中间件? UseFileServer中间件的作用是什么? 最重要的特性之一就是;几乎所有的web应用程序都应该具备直接从文件系统存取静态文件的能力.ASP.NET Core能够直接从客户端获取应用程序的静态文件,比如:HTML

  • 详解如何在ASP.NET Core Web API中以三种方式返回数据

    在 ASP.NET Core 中有三种返回 数据 和 HTTP状态码 的方式,最简单的就是直接返回指定的类型实例,如下代码所示: [ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase { [HttpGet] public IEnumerable<WeatherForecast> Get() { var rng = new Random()

  • ASP.NET Core自定义中间件的方式详解

    目录 1.委托形式 2.强类型中间件 2.1.定义中间件的依赖 2.2.定义中间件类型 3.基于约定的中间件 3.1.约定规则 3.2.应用实现 总结 ASP.NET Core应用本质上,其实就是由若干个中间件构建成的请求处理管道.管道相当于一个故事的框架,而中间件就相当于故事中的某些情节.同一个故事框架采用不同的情节拼凑,最终会体现出不同风格的故事.而我们的ASP.NET Core应用也正是如此,同一管道采用不同的中间件组合,最终也会呈现出不同的应用形态. 从上述的概念种可以看出,中间件在AS

  • ASP.NET Core 2.2中的Endpoint路由详解

    Endpoint路由 在ASP.NET Core 2.2中,新增了一种路由,叫做 Endpoint (终结点)路由.本文将以往的路由系统称为 传统路由 . 本文通过源码的方式介绍传统路由和 Endpoint 路由部分核心功能和实现方法,具体功能上的差异见 官方文档 . 在升级到ASP.NET Core 2.2后,会自动启用 Endpoint 路由.如果要恢复以往的实现逻辑,需要加入以下代码: services.AddMvc(options => options.EnableEndpointRou

  • .Net Core解决WebAPI中返回时间格式带T的问题

    在项目开发中遇到了返回的时间格式带T的问题,如图所示: 直接把这种结果返回给前端,前端很难处理这个时间格式问题,所以就需要后端在返回数据的时候对这种格式进行处理. 新建Order类: using System; namespace WebApiTest { public class Order { public int ID { get; set; } public DateTime OrderTime { get; set; } } } 新建一个格式化类DatetimeJsonConverte

  • vue.js分页中单击页码更换页面内容的方法(配合spring springmvc)

    html代码: <section class="container page-home"> <div id="main-content" class="wrap-container zerogrid"> <article id="news_content" v-for="item in items"> <div class="col-1-2 right&q

随机推荐