C# 如何在asp net core 2.2中间件中多次读取请求正文?
我试过这个: 这是: 但没有起作用。 我这样读请求体:C# 如何在asp net core 2.2中间件中多次读取请求正文?,c#,middleware,asp.net-core-2.2,C#,Middleware,Asp.net Core 2.2,我试过这个: 这是: 但没有起作用。 我这样读请求体: app.Use(async (context, next) => { var requestBody = await ReadStream(context.Request.Body); var requestPath = context.Request.Path.ToString(); //Do some thing await next.Invoke(); var responseStat
app.Use(async (context, next) =>
{
var requestBody = await ReadStream(context.Request.Body);
var requestPath = context.Request.Path.ToString();
//Do some thing
await next.Invoke();
var responseStatusCode = context.Response.StatusCode;
//Do some other thing
});
private async Task<string> ReadStream(Stream stream)
{
using (var streamReader = new StreamReader(stream))
{
var result = await streamReader.ReadToEndAsync();
return result;
}
}
app.Use(async (context, next) =>
{
context.Request.EnableRewind();
var stream = context.Request.Body;
using (var reader = new StreamReader(stream))
{
var requestBodyAsString = await reader.ReadToEndAsync();
if (stream.CanSeek)
stream.Seek(0, SeekOrigin.Begin);
//Do some thing
await next.Invoke();
var responseStatusCode = context.Response.StatusCode;
//Do some other thing
}
});
app.Use(异步(上下文,下一步)=>
{
var requestBody=await ReadStream(context.Request.Body);
var requestPath=context.Request.Path.ToString();
//做点什么
等待next.Invoke();
var responseStatusCode=context.Response.StatusCode;
//做些别的事
});
专用异步任务读取流(流)
{
使用(var streamReader=新streamReader(stream))
{
var result=wait streamReader.ReadToEndAsync();
返回结果;
}
}
在controller中,我得到了“disposed object”或“empty stream”。这可能是因为
StreamReader周围使用了语句。使用dispose处理StreamReader
,它在底层流上调用dispose。有关更多详细信息,请参见答案。您可以尝试在wait next.Invoke()之后保留引用并处理StreamReader
代码>完成。经过更多的努力和使用
“context.Request.EnableRewind()”
它最终是这样工作的:
app.Use(async (context, next) =>
{
var requestBody = await ReadStream(context.Request.Body);
var requestPath = context.Request.Path.ToString();
//Do some thing
await next.Invoke();
var responseStatusCode = context.Response.StatusCode;
//Do some other thing
});
private async Task<string> ReadStream(Stream stream)
{
using (var streamReader = new StreamReader(stream))
{
var result = await streamReader.ReadToEndAsync();
return result;
}
}
app.Use(async (context, next) =>
{
context.Request.EnableRewind();
var stream = context.Request.Body;
using (var reader = new StreamReader(stream))
{
var requestBodyAsString = await reader.ReadToEndAsync();
if (stream.CanSeek)
stream.Seek(0, SeekOrigin.Begin);
//Do some thing
await next.Invoke();
var responseStatusCode = context.Response.StatusCode;
//Do some other thing
}
});
当第二次读取流时,流指针被设置到最后一个位置。您应该尝试将其移回零位,以便从头开始再次读取
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用Microsoft.AspNetCore.Builder;
使用Microsoft.AspNetCore.Http;
使用Microsoft.AspNetCore.WebUtilities;
使用Microsoft.Extensions.Logging;
使用Newtonsoft.Json;
使用Newtonsoft.Json.Linq;
使用NLog;
命名空间测试\u middleware.middleware
{
//您可能需要在项目中安装Microsoft.AspNetCore.Http.Abstractions包
公共类日志中间件
{
private readonly RequestDelegate\u next;
专用只读ILogger\u记录器;
公共日志中间件(RequestDelegate next,ILogger logger)
{
_下一个=下一个;
_记录器=记录器;
}
公共异步任务InvokeAsync(HttpContext HttpContext)
{
var HttpContextBody=httpContext.Request.Body;
字符串requestBody=“”;
httpContext.Request.EnableBuffering();
//让主体保持打开状态,以便下一个中间件可以读取它。
使用(var reader=newstreamreader)(
httpContext.Request.Body,
编码:encoding.UTF8,
从字节顺序标记检测到编码:false,
缓冲区大小:-1,
(开:对)
{
var body=wait reader.ReadToEndAsync();
//对身体做一些处理…
//重置请求主体流位置,以便下一个中间件可以读取它
httpContext.Request.Body.Position=0;
}
_LogDebug(“中间件1 body=“+requestBody”);
wait_next.Invoke(httpContext);
}
}
//用于将中间件添加到HTTP请求管道的扩展方法。
公共静态类日志MiddleWareExtensions
{
公共静态IApplicationBuilder UseLoggingMiddleware(此IApplicationBuilder)
{
返回builder.UseMiddleware();
}
}
}
有关更多信息,请参阅以下链接:
.netcore 3.1版@HoussamNasser的上述答案。我创建了一个可重用的函数来读取请求体。请注意更改:HttpRequestRewindExtensions.EnableBuffering(请求)
。启用缓冲现在是类的一部分
公共异步任务GetRequestBodyAsync(HttpRequest请求)
{
JObject objRequestBody=新JObject();
//要点:确保可以多次读取requestBody。
HttpRequestWrindExtensions.EnableBuffering(请求);
//重要提示:保持主体打开,以便下一个中间件可以读取它。
使用(StreamReader=新StreamReader)(
请求机构,
Encoding.UTF8,
从字节顺序标记检测到编码:false,
(开:对)
{
string strRequestBody=wait reader.ReadToEndAsync();
objRequestBody=Serialized.Deserialize(strRequestBody);
//重要提示:重置请求主体流位置,以便下一个中间件可以读取它
request.Body.Position=0;
}
返回objRequestBody;
}
此函数将返回一个JObject,可用于读取请求主体对象的属性。Serialized是用于序列化和反序列化的自定义扩展
在中间件中,您可以在构造函数中注入IHttpContextAccessor httpContextAccessor
。然后访问请求对象,如HttpRequest Request=\u httpContextAccessor.HttpContext.Request代码>。最后,可以调用可重用的函数,如GetRequestBodyAsync(request)
我一直在努力解决这个问题,.net core 3.1已经有了突破性的更改,.net core 3.1中不再提供“context.request.EnableRewind();”,更多有用的提示
asp.net mvc api.net core 3.1(startup.cs)中的工作代码
说得好,我在next.Invoke()之后处理了streamReader,它成功了。您在.NETCore3中尝试过这个吗?我试过了,但它似乎不起作用了。是的,它在dotnet core 3.0中不起作用。还有另一种方法:使用Microsoft.AspNetCore.Http;然后调用“context.Request.enableBuffer()”@JanPaoloGo@AlirezaYavari迁移到.net core 3.0时,我也面临同样的问题。在.NETCore3.0中,我想使用BodyReader管道。我出于日志目的处理了请求正文,但收到验证错误“输入不包含任何JSON令牌。当isFinalBlock为true时,输入应以有效的JSON令牌开头。路径:$|行号:0
app.Use(async (context, next) =>
{
context.Request.EnableBuffering();
var stream = context.Request.Body;
using (var reader = new StreamReader(stream))
{
var requestBodyAsString = await reader.ReadToEndAsync();
if (stream.CanSeek)
stream.Seek(0, SeekOrigin.Begin);
//some logging and other stuff goes here
await next.Invoke();
}
});