.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共享时遇到的坑,欢迎大家共同探讨。
.Net Core Web Api实践之中间件的使用(一)的更多相关文章
- .Net Core Web Api实践(三).net core+Redis+docker实现Session共享
前言:上篇文章介绍了.net core+Redis+IIS+nginx实现Session共享,本来打算直接说明后续填坑过程,但毕竟好多坑是用docker部署后出现的,原计划简单提一下.net core ...
- .Net Core Web Api实践(二).net core+Redis+IIS+nginx实现Session共享
前言:虽说公司app后端使用的是.net core+Redis+docker+k8s部署的,但是微信公众号后端使用的是IIS部署的,虽说公众号并发量不大,但领导还是使用了负载均衡,所以在介绍docke ...
- .Net Core Web Api实践(四)填坑连接Redis时Timeout performing EVAL
前言:前两篇文章.net core+Redis+IIS+nginx实现Session共享中,介绍了使用Microsoft.Extensions.Caching.Redis实现Session共享的方法, ...
- .net core web api + Autofac + EFCore 个人实践
1.背景 去年时候,写过一篇<Vue2.0 + Element-UI + WebAPI实践:简易个人记账系统>,采用Asp.net Web API + Element-UI.当时主要是为了 ...
- ASP.NET Core Web API 最佳实践指南
原文地址: ASP.NET-Core-Web-API-Best-Practices-Guide 介绍 当我们编写一个项目的时候,我们的主要目标是使它能如期运行,并尽可能地满足所有用户需求. 但是,你难 ...
- [转]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 一.概述 本篇介绍如 ...
- 循序渐进学.Net Core Web Api开发系列【13】:中间件(Middleware)【有源码】
原文:循序渐进学.Net Core Web Api开发系列[13]:中间件(Middleware) 系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:ht ...
- 加快ASP。NET Core WEB API应用程序。第3部分
下载source from GitHub 对ASP进行深度重构和优化.NET Core WEB API应用程序代码 介绍 第1部分.创建一个测试的RESTful WEB API应用程序. 第2部分.增 ...
随机推荐
- @游记@ THUWC2019
目录 @day -???@ @day -30~-1@ @day 0@ @day 1@ @day 2@ @day 3@ @day -???@ 我这个蒟蒻居然收到了 THUWC 的邀请? 那就去试试运气吧 ...
- H3C 路由器SSH服务配置命令(续)
- 模块化Vs组件化
模块化&组件化 原因 图解 模块化Module 概念 使用 目的 依赖 架构定位 内容:组件内的Script 组件化 概念 使用 目的:复用,解耦 依赖 架构定位 内容:template.st ...
- h3c 广域网与OSI参考模型
- js利用select标签生成简易计算功能
html中使用select option作为运算符的承接容器,输入值,选择不同运算符,计算结果. 文章地址 https://www.cnblogs.com/sandraryan/ <!DOCTY ...
- UVA 11107 Life Forms——(多字符串的最长公共子序列,后缀数组+LCP)
题意: 输入n个序列,求出一个最大长度的字符串,使得它在超过一半的DNA序列中连续出现.如果有多解,按照字典序从小到大输出所有解. 分析:这道题的关键是将多个字符串连接成一个串,方法是用不同的分隔符把 ...
- 21个项目玩转深度学习:基于TensorFlow的实践详解01—MNIST机器学习入门
数据集 由Yann Le Cun建立,训练集55000,验证集5000,测试集10000,图片大小均为28*28 下载 # coding:utf-8 # 从tensorflow.examples.tu ...
- zeppelin开启多个
conf/zeppelin-env.sh 添加行: export ZEPPELIN_PID_DIR=/xx/zeppelin/run_2
- P1026 翻硬币
题目描述 小明正在玩一个"翻硬币"的游戏.桌上放着排成一排的若干硬币.我们用 * 表示正面,用 o 表示反面(是小写字母,不是零). 比如,可能情形是:**oo***oooo 如果 ...
- 为什么Redis是单线程,性能还如此高?
一. Redis为什么是单线程 注意:redis 单线程指的是网络请求模块使用了一个线程,即一个线程处理所有网络请求,其他模块仍用了多个线程. 因为CPU不是Redis的瓶颈.Redis的瓶颈最有可能 ...