.Net Core Web Api实践之中间件的使用(一)

前言:从2019年年中入坑.net core已半年有余,总体上来说虽然感觉坑多,但是用起来还是比较香的。本来我是不怎么喜欢写这类实践分享或填坑记录的博客的,因为初步实践坑多,文章肯定也会有各种错误,跟别人优秀的文章比起来,好像我写的东西没有什么存在的价值。但是入坑.net core以来,这种思想开始慢慢改变了,毕竟我依靠别人解决问题的文章也不尽是教科书般的存在,但是很使用。所以,把自己的实践过程记录出来,一方面是巩固和完善自己的技术栈,另一方能帮助到其他人,或者跟他人共同探讨,也不算闭门造轮子,自娱自乐了吧。.net core web api的实践记录,就由中间件的使用开始吧。

1、必要的知识储备

在阅读这篇文章的时候,我希望读者已经了解接口的逆变与协变、泛型、委托等知识点(个人认为这是了解.net各种框架的必备知识),同时也知道.net core的依赖注入、生命周期的相关内容(园子里前几名的大佬,对这块都有非常优秀的讲解,这里我就不作介绍,有需要的童鞋可以留言,我提供连接)。

2、.net core webapi项目中配置中间件

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMiddleware<RequestMiddleware>();
            app.UseMvc();
        }

  在项目的Startup.cs文件中,找到Configure方法,加上app.UseMiddleware<RequestMiddleware>(); 这里的RequestMiddleware就是自定义的中间件,我们可以简单看下UseMiddleware的定义:

TMiddleware是一个泛型,使用UseMiddleware传递的就是自定义的中间件。

3、自定义中间件的实现

很遗憾我的反编译工具未能找到UseMiddleware的实现方法,但是结合官网上的介绍https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/write?view=aspnetcore-3.1),自定义的中间件需要构造函数来接收一个RequestDelegate对象,是关于HttpRequest的一个委托,另外还需要一个名为 Invoke 或 InvokeAsync 的公共方法,用于写一些HttpRequest的预处理逻辑。在我的项目中,我用它来进行参数预处理、登录预处理、Session预处理以及请求的转发功能。

public class RequestMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IConfig config;

        public RequestMiddleware(RequestDelegate next, IConfig config)
        {
            _next = next;
            this.config = config;
        }

        public Task Invoke(HttpContext context)
        {
            context.Request.EnableRewind(); //支持context.Request.Body重复读取,内部调用了EnableBuffering方法,否则在使用部分方法或属性时会报错误System.NotSupportedException: Specified method is not supported,例如context.Request.Body.Position
            // && context.Request.Path.Value == "/api/Main"
            if (context.Request.ContentLength != null)
            {
                Stream stream = context.Request.Body;
                byte[] buffer = new byte[context.Request.ContentLength.Value];
                stream.Read(buffer, 0, buffer.Length);
                string querystring = Encoding.UTF8.GetString(buffer);

                RequestMiddleParam requestEntity = Newtonsoft.Json.JsonConvert.DeserializeObject<RequestMiddleParam>(querystring);
                if (requestEntity == null)
                {
                    throw new Exception("无法处理的请求");
                }

                string param = Newtonsoft.Json.JsonConvert.SerializeObject(requestMiddleMapParam);        //参数
                //todo 参数校验
                byte[] bs = Encoding.UTF8.GetBytes(param);    //参数转化为utf8码

                //context.Request.Body.Seek(0, SeekOrigin.Begin);
                //context.Request.EnableBuffering();

                var ms = new MemoryStream();
                context.Request.Body = ms;
                context.Request.Body.Write(bs, 0, bs.Length);

                context.Request.Body.Position = 0;   //重置context.Request.Body的Stream指针,否则报A non-empty request body is required.错误
            }

            // Call the next delegate/middleware in the pipeline
            return this._next(context);
        }
    }

  值得注意的是,构造函数可以使用Startup.cs中ConfigureServices方法里的注入项,上面实例代码中的IConfig就是的。(这里还有一个坑,就是中间件通过构造函数来接收services.AddDbContext的注入项,因为生命周期不一样)

4、参数预处理遇到的坑

以一个Post请求为例,参数是Json结构,为了判断Json参数中的某字段是否符合规则,就需要对其进行反序列化,校验完成后,再序列化填进Body对象中。这里注意下context.Request.EnableRewind();与context.Request.Body.Position = 0;两行代码的添加,因为是以流的形式读取和再写入参数,EnableRewind方法支持重复读取,而context.Request.Body.Position的归0则保证在重新将参数写入Body后,报A non-empty request body is required.错误。

以上就是.net core中间件的简单介绍了,其实它的作用有些像asp.net的拦截器,将请求拦截做一些预处理,针对请求参数的处理、服务的转发,甚至登录校验等需求,都是个不错的选择。如果还想深入了解的同学,可自行去寻找UseMiddleware的实现方式。下一篇文章,我将介绍使用.net core + Redis + Session完成分布式Session共享时遇到的坑,欢迎大家共同探讨。

原文地址:https://www.cnblogs.com/BradPitt/p/12146409.html

时间: 2024-11-08 02:32:37

.Net Core Web Api实践之中间件的使用(一)的相关文章

.Net Core Web Api实践(三).net core+Redis+docker实现Session共享

前言:上篇文章介绍了.net core+Redis+IIS+nginx实现Session共享,本来打算直接说明后续填坑过程,但毕竟好多坑是用docker部署后出现的,原计划简单提一下.net core+Redis+docker实现Session共享,但是发现篇幅也不小,所以还是单独起草一篇,除了k8s部署docker,其它部分都有基本介绍. 1.环境准备 操作系统:Windows10 VS2019.本地Redis数据库.Windows docker 2.背景介绍 由于项目从asp.net MVC

.Net Core Web Api实践(二).net core+Redis+IIS+nginx实现Session共享

前言:虽说公司app后端使用的是.net core+Redis+docker+k8s部署的,但是微信公众号后端使用的是IIS部署的,虽说公众号并发量不大,但领导还是使用了负载均衡,所以在介绍docker+k8s实现分布式Session共享之前,就先介绍一下IIS+nginx实现Session共享的方案,两者其实区别不大,所以这篇着重介绍方案,下篇介绍测试的区别以及填坑的方式. 1.环境准备 操作系统:Windows10 IIS:需要安装模块 VS2019.本地Redis数据库.ngnix(win

.Net Core Web Api实践(四)填坑连接Redis时Timeout performing EVAL

前言:前两篇文章.net core+Redis+IIS+nginx实现Session共享中,介绍了使用Microsoft.Extensions.Caching.Redis实现Session共享的方法,但是高并发时会有连接Redis出现Timeout的问题,这篇文章将介绍该问题的解决方案. 1.环境及工具准备 操作系统:windows10 数据库:Redis 压力测试工具:JMeter(传送门) 2.背景介绍 项目迁移到.net core并上线以后,运行没多久接口就频繁罢工,容器没有挂,redis

[转]ASP.NET Core Web API 最佳实践指南

原文地址: ASP.NET-Core-Web-API-Best-Practices-Guide 转自 介绍# 当我们编写一个项目的时候,我们的主要目标是使它能如期运行,并尽可能地满足所有用户需求. 但是,你难道不认为创建一个能正常工作的项目还不够吗?同时这个项目不应该也是可维护和可读的吗? 事实证明,我们需要把更多的关注点放到我们项目的可读性和可维护性上.这背后的主要原因是我们或许不是这个项目的唯一编写者.一旦我们完成后,其他人也极有可能会加入到这里面来. 因此,我们应该把关注点放到哪里呢? 在

循序渐进学.Net Core Web Api开发系列【13】:中间件(Middleware)

系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇介绍如何使用中间件(Middleware). 二.初步演练 先写几个中间件 public class DemoAMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; public Dem

asp.net core web api token验证和RestSharp访问

对与asp.net core web api验证,多种方式,本例子的方式采用的是李争的<微软开源跨平台移动开发实践>中的token验证方式. Asp.net core web api项目代码: 首先定义三个Token相关的类,一个Token实体类,一个TokenProvider类,一个TokenProviderOptions类 代码如下: /// <summary> /// Token实体 /// </summary> public class TokenEntity

通过Swashbukle给DotNet Core Web API 增加自动文档功能

DotNet Core Web API给开发者提供了一个很好的框架来开发Restful的API.那么这些API接口该如何管理起来呢?Swagger是一个很好的选择,Swagger不需要开发者额外去维护接口文档,只要开发者的接口遵循Restful的规范,Swagger就会根据API接口生成文档. 对于前后端分离的开发模式,前后端开发者一般会先定义好接口,然后各自独立开发,后端开发者可以使用Swagger很快的生成没有业务逻辑的接口文档,接口返回的是Mock Data,这样前端开发人员就可以更早的开

docker中运行ASP.NET Core Web API

在docker中运行ASP.NET Core Web API应用程序 本文是一篇指导快速演练的文章,将介绍在docker中运行一个ASP.NET Core Web API应用程序的基本步骤,在介绍的过程中,也会对docker的使用进行一些简单的描述.对于.NET Core以及docker的基本概念,网上已经有很多文章对其进行介绍了,因此本文不会再详细讲解这些内容.对.NET Core和docker不了解的朋友,建议首先查阅与这些技术相关的文档,然后再阅读本文. 先决条件 要完成本文所介绍的演练任

在docker中运行ASP.NET Core Web API应用程序

本文是一篇指导快速演练的文章,将介绍在docker中运行一个ASP.NET Core Web API应用程序的基本步骤,在介绍的过程中,也会对docker的使用进行一些简单的描述.对于.NET Core以及docker的基本概念,网上已经有很多文章对其进行介绍了,因此本文不会再详细讲解这些内容.对.NET Core和docker不了解的朋友,建议首先查阅与这些技术相关的文档,然后再阅读本文. 先决条件 要完成本文所介绍的演练任务,需要准备以下环境: Visual Studio 2015,或者Vi