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

 更新时间:2020-09-24 15:09:14   作者:佚名   我要评论(0)

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

前言

果博东方在 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("http://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>();
}

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

总结

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

您可能感兴趣的文章:
  • 浅谈ASP.NET Core中间件实现分布式 Session
  • 详解在ASP.NET Core 中使用Cookie中间件
  • 浅谈ASP.NET Core 中间件详解及项目实战
  • Asp.Net Core 通过中间件防止图片盗链的实例

果博东方相关的文章

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

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

    前言 在 asp.net core 中,存在着中间件这一概念,在中间件中,我们可以比过滤器更早的介入到 http 请求管道,从而实现对每一次的 http 请求、响应做切面处理,从而
    2020-09-24
  • 使用Seq搭建免费的日志服务的方法

    使用Seq搭建免费的日志服务的方法

    Seq简介 Seq是老外开发的一个针对.NET平台非常友好的日志服务。支持容器部署,提供一个单用户免费的开发版本。 官网:http://datalust.co/seq 使用文档:http://d
    2020-09-24
  • 在IIS上部署ASP.NET Core Web API的方法步骤

    在IIS上部署ASP.NET Core Web API的方法步骤

    对于本文,我想与您分享有关如何在IIS上部署ASP.NET Core Web API的指南。我将指导您安装Visual Studio 2019,.NET Core Runtime 3.0。我还确保我逐步引导您在服务器
    2020-09-24
  • .net core实用技巧——将EF Core生成的SQL语句显示在控制台中

    .net core实用技巧——将EF Core生成的SQL语句显示在控制台中

    前言 笔者最近在开发和维护一个.NET Core项目,其中使用几个非常有意思的.NET Core相关的扩展,在此总结整理一下。 EF Core性能调优 如果你的项目中使用了EF Core,
    2020-09-24
  • asp .net core静态文件资源的深入讲解

    asp .net core静态文件资源的深入讲解

    前言 对静态资源的简单的一个概况,在《重新整理.net core 计1400篇》系列后面会深入。 正文 我们在加入中间件是这样写的: app.UseStaticFiles(); 默认是给wwwro
    2020-09-24
  • c# rabbitmq 简单收发消息的示例代码

    c# rabbitmq 简单收发消息的示例代码

    发布消息:(生产者) /// <summary> /// 发送消息 /// </summary> /// <param name="queue">队列名</param> /// <param name="message">消息
    2020-09-24
  • ASP.net百度主动推送功能实现代码

    ASP.net百度主动推送功能实现代码

    官方提供了curl、post、php、ruby的实现示例,并没有C#的官方示例。既然提供了post的方式,那么就可以用C#实现,下面是实现代码: ASP.net百度主动推送代码范例 p
    2020-09-24
  • ASP .NET Core API发布与部署以及遇到的坑和解决方法

    ASP .NET Core API发布与部署以及遇到的坑和解决方法

    最近在写.Net Core的API,由于之前没接触过Core,所以自己的想法很简单,感觉和.Net都是差不多的东西,发布部署还是按.Net的那一套来,可谓是困难重重,走了
    2020-09-24
  • 深入浅析ASP在线压缩access数据库的方法

    深入浅析ASP在线压缩access数据库的方法

    ASP在线压缩ACCESS数据库原理很简单:利用JRO.JetEngine的压缩功能建立一个新的数据库文件,然后把原来的删掉、替换!既然这样,压缩程序只需几行就ok了! 把下面的
    2020-09-24
  • 如何利用PHP实现上传图片功能详解

    如何利用PHP实现上传图片功能详解

    HTML文件 一、 设置编码UTF-8 对于中文网页需要使用<meta charset="utf-8">声明编码,否则会出现乱码。 二 、form表单 <form>标签用于为用户输入创建 HTML 表单,表
    2020-09-24

最新评论

黄奕聂远同框攀钢董事长被查中国新说唱王毅谈全球化魔兽世界怀旧服中国大妈篮球公园广州暴雨引泥石流