1、WebAPI新增日志过滤器or中间件后Action读取到的请求Body为空问题

案例:

自定义了一个中间件,用于记录每次访问webapi的入参,以及引用了Swagger。

先看下面这段代码:

 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseMvc(); //各种中间件
app.UseVisitLogger();
app.UsAirExceptionHandler();
app.UseHttpsRedirection();
//SignalR
app.UseSignalR(routes =>
{
routes.MapHub<TriageHub>("/triage", (options) =>
{
//指定采取WebSoket协议进行双工通讯
options.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.WebSockets;
});
}); //swagger
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TestWebAPI"));
}

  上面这段代码看上去是不是人畜无害,没啥问题。 恩,F5启动后,我们试下执行post方式的webapi。执行结果是ok的,但是UseVisitLogger中间件里的

日志记录却没有记录webapi的访问日志。

我们把Startup下的Configure方法改成下面这种方式:

   public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
//各种中间件
app.UseVisitLogger();
app.UsAirExceptionHandler();
app.UseHttpsRedirection();
//SignalR
app.UseSignalR(routes =>
{
routes.MapHub<TriageHub>("/triage", (options) =>
{
//指定采取WebSoket协议进行双工通讯
options.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.WebSockets;
});
});
app.UseMvc();
//swagger
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TestWebAPI"));
}

  我们把UseMvc()放置 各类中间件的后面,再来试下webapi的post方式(post的入参是一个模型,不是基础数据类型!)

执行结果如上图。。。这一次api执行失败,但是日志记录成功了,如下图:

哎。。。是不是很坑。。目前先记录下,还要想办法怎么去解决

---------------------------------------------------------------------解决新增自定义中间件后执行带模型Post请求400问题----------------------------------

原因: 因为自定义中间件里有一个是写日志的,会将HttpContext对象的Request.Body对象(一个Steam对象)的读取位置改变。原来的日志中间件是这样写的,如下:

      public async Task Invoke(HttpContext context)
{
visitLog = new VisitLog();
HttpRequest request = context.Request;
visitLog.Url = request.Path.ToString();
visitLog.Headers = request.Headers.ToDictionary(k => k.Key, v => string.Join(";", v.Value.ToList()));
visitLog.Method = request.Method;
visitLog.ExcuteStartTime = DateTime.Now;
using (StreamReader reader = new StreamReader(request.Body))
{
visitLog.RequestBody = reader.ReadToEnd();
} context.Response.OnCompleted(ResponseCompletedCallback, context);
await _next(context);
}

  上面的 requst.Body 在通过ReadToEnd后实际上的context.Request.Body的读取位置已经是最后了,在后续的中间件接收到的context因为读取位置不是0而是内容的

长度,所以怎么都读不到数据。这就是为什么post请求会出现400错误,因为到action那里的时候确实Requst.Body的内容他啥也没读到啊!!

现在找到了问题所在就好处理了,处理方式如下:

  public async Task Invoke(HttpContext context)
{
visitLog = new VisitLog();
HttpRequest request = context.Request;
visitLog.Url = request.Path.ToString();
visitLog.Headers = request.Headers.ToDictionary(k => k.Key, v => string.Join(";", v.Value.ToList()));
visitLog.Method = request.Method;
visitLog.ExcuteStartTime = DateTime.Now;
var originalRequestBody = request.Body; var requestBodyStream = new MemoryStream();
await request.Body.CopyToAsync(requestBodyStream);
//设置当前流的位置未0
requestBodyStream.Seek(0, SeekOrigin.Begin);
//这里ReadToEnd执行完毕后requestBodyStream流的位置会从0到最后位置(即request.ContentLength)
visitLog.RequestBody = new StreamReader(requestBodyStream).ReadToEnd();
//需要将流位置重置偏移到0,不然后续的action读取不到request.Content的值
requestBodyStream.Seek(0, SeekOrigin.Begin); context.Response.OnCompleted(ResponseCompletedCallback, context);
context.Request.Body = requestBodyStream;
await _next(context);
context.Request.Body = originalRequestBody;
}

  好啦,我们把流的读取位置重新偏移下就好了!

2、.NetCore项目智能提示英文更改为中文的方法

.NetCore下载后,在VS2017开发时候,智能提示是下图这样的:

很不爽是吧,尤其是我们这种英文渣。解决方案呢其实就是需要将框架里的Nuget包的注释xml文件替换成中文版的(至少我是这么做的,其他办法未知..)

首先从C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5.1 这个目录下将zh-Hans文件夹下的所有文件copy到

C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1目录下。 这里我是因为用的.NetCore2.1,如果

是2.0则将目录里的2.1更改成2.0。 然后重新打开VS2017就可以发现智能提示是中文啦~~~~

3、字符集GB2312引用错误处理

在对csv文件读取时候乱码,后来发现.NetCore需要安装System.Text.Encoding.CodePages这个Nuget包,然后在类的构造函数里加上这一段代码System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance)

4、Linux上部署.NetCore站点端口号与launchSettings.json设置不一致的解决办法

在Linux上部署站点绝对会出现这个问题,除非你的端口号恰巧就和默认的站点一致。不然你在launchSettings.json上的端口设置好后发现在Linux上启动你的应用后监听的端口不一致。

如何解决呢?没办法,在dotnet命令后加urls参数。如:

dotnet HY.Admin.Host.dll --urls http://*:5001

 上面就是指定了端口5001,结果如下:

.NetCore WebAPI采坑之路(持续更新)的更多相关文章

  1. React Native之坑总结(持续更新)

    React Native之坑总结(持续更新) Genymotion安装与启动 之前我用的是蓝叠(BlueStack)模拟器,跑RN程序也遇到了一些问题,都通过搜索引擎解决了,不过没有记录. 但是Blu ...

  2. Windows MySql增量备份、完整备份采坑之路

    1.前言 这周公司交给我一个任务,负责项目Mysql数据库的备份,因为项目上线后数据是一个大问题,出了什么问题数据才是最大的问题,备份这时候就显得尤为重要, 公司项目的思路是:在项目系统设置内可以勾选 ...

  3. 移动端WEBAPP开发遇到的坑,以及填坑方案!持续更新~~~~

    前言:在移动端WEBAPP开发中会遇到各种各样的问题,通过此文对遇到的问题做一个归纳总结,方便自己日后查询,也给各位前端开发友人做一个参考.   此文中涉及的问题是本人开发中遇到的,解决方案是本人思考 ...

  4. axios采坑之路

    POST请求设置Content-Type 由于后端采用的是form表单形式上送参数,需要设置Content-Type axios设置如下 const _axios = axios.create(con ...

  5. java采坑之路

    判断相等 字符串判断相等         String str1 = null;         String str2 = "java金融";        // str1.eq ...

  6. win10+tensorflow+CUDA 心酸采坑之路

    最近准备学习机器学习和深度学习,所以入坑Tensorflow,之前一直使用的是Anaconda3的cpu版本的Tensorflow,但是这次作死一直想用GPU版本的,主要是不想浪费我的1080ti,但 ...

  7. 【微信小程序】踩坑指南(持续更新)

    前言 说明: 基于mpvue框架:mpvue官方文档 语法同vue框架:vue官方文档 小程序中会有一些坑点,这里会就工作中遇到的坑一一列举出来 无说明时请直接看代码注释 v-show无法使用在小程序 ...

  8. Springmvc 一个简单的管理系统 我所遇到的坑1(持续更新)

    前言 好久没有用springmvc写项目了,抽时间写一个简单的springmvc项目 是什么(what)为什么(why)怎么做(how) 1.读书破万卷下笔如有神(理清思路,知识储备和前期整理) 2. ...

  9. 【笔记】Java微服务之路(持续更新)

    微服务架构的说明: 微服务的架构风格是将一个单体的应用程序开发拆解为一组"小"的服务,这里的"小"是以业务边界 来区分的,而不是根据代码的多少区分.每个服务都运 ...

随机推荐

  1. spot 状压dp

    题目大意:数轴上有n个泥点,共有m个木板,求最少用几个木板可以覆盖全部泥点,并求最优方案数(n,m<=15) 看范围,肯定是状压 f[i][j]表示前i个泥点都被覆盖,使用的木板集合为j 转移: ...

  2. C# 指定父層級目錄

    lstrcatW(pszpath, "\\..\\..\\"); DWORD dwlen = GetFullPathNameW(pszpath, 0u, null, null); ...

  3. CMake入门实战

    本文用来记录基本的Cmake用法,以一个实例,讲解如何通过cmake构建一个一个基本的工程,文件的目录如下: 说明: bin文件夹下的debug和release分别存放编译输出的文件和相关依赖的动态库 ...

  4. TiDB show processlist命令源码分析

    背景 因为丰巢自去年年底开始在推送平台上尝试了TiDB,最近又要将承接丰巢所有交易的支付平台切到TiDB上.我本人一直没有抽出时间对TiDB的源码进行学习,最近准备开始一系列的学习和分享.由于我本人没 ...

  5. C#ComboBox控件“设置 DataSource 属性后无法修改项集合”的解决方法

    在使用ComboBox控件时,遇到了重新绑定赋值出问题的情况.正常情况下,对于数据重新赋值的或者绑定数据源的时候,为了防止数据出现问题,都会先清空原来数据,所以就这样写了,但是没有相当恰恰这样写就出现 ...

  6. Java工程师必备书单

    微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...

  7. 学习 JavaScript (四)核心概念:操作符

    JavaScript 的核心概念主要由语法.变量.数据类型.操作符.语句.函数组成,前面三个上一篇文章已经讲解完了.后面三个内容超级多,这篇文章主要讲解的是操作符. 操作符 什么叫做操作符? 这是一种 ...

  8. c#中@标志的作用

    参考微软官方文档-特殊字符@,地址 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/tokens/verbatim ...

  9. 【原创】详细案例解剖——浅谈Redis缓存的常用5种方式(String,Hash,List,set,SetSorted )

    很多小伙伴没接触过Redis,以至于去学习的时候感觉云里雾里的,就有一种:教程随你出,懂了算我输的感觉. 每次听圈内人在谈论的时候总是插不上话,小编就偷偷去了解了一下,也算是初入门径. 然后就整理了一 ...

  10. python:前端(HTML)+后端(Django)+数据库(MySQL)

    1.创建一个html文件用于简单的网页注册demo <!DOCTYPE html> <html lang="en"> <head> <me ...