ASP.NET Core 中读取Post Request.Body 的正确姿势


.NET Core 2.* 获取 Post 的 Body 内容字符串

ASP.NET Core 中的 Request.Body 虽然是一个 Stream ,但它是一个与众不同的 Stream —— 不允许 Request.Body.Position=0 ,这就意味着只能读取一次,要想多次读取,需要借助 MemoryStream ,详见博问 asp.net core中2次读取Request.Body的问题 

using (var buffer = new MemoryStream())
{
    Request.Body.CopyTo(buffer);
    buffer.Position = 0;
    buffer.CopyTo(writer.BaseStream);
    Console.WriteLine("Request.Body:");
    buffer.Position = 0;
    buffer.CopyTo(Console.OpenStandardOutput());
} 
GarsonZhang www.yesdotnet.com

昨天读了博文 Reading request body in ASP.NET Core 之后得知在 ASP.NET Core 2.0 中已经针对这个问题提供了解决方法 —— EnableRewind() ,只要启用倒带功能,就可以让  Request.Body 回归正常 Stream 。

使用非常简单,引用命名空间 Microsoft.AspNetCore.Http.Internal ,调用方法 Request.EnableRewind()  即可,下面我们用简单的示例代码体验一下

public class HomeController : Controller
{
    public IActionResult Index()
    {
      
        Request.EnableRewind(); // .net core 3.0为 Request.EnableBuffering ();

        Console.WriteLine("Request.Body1:");
        Request.Body.Position = 0;
        Request.Body.CopyTo(Console.OpenStandardOutput());
        Console.WriteLine();

        Console.WriteLine("Request.Body2:");
        Request.Body.Position = 0;
        Request.Body.CopyTo(Console.OpenStandardOutput());
        Console.WriteLine();

        return Ok();
    }
}
GarsonZhang www.yesdotnet.com

EnableRewind 有 2 个参数 bufferThreshold 与 bufferLimit 。 bufferThreshold 设置的是 Request.Body 最大缓存字节数(默认是30K),超出这个阈值的字节会被写入磁盘;bufferLimit 设置的是 Request.Body 允许的最大字节数(默认值是null),超出这个限制,就会抛出异常  System.IO.IOException 。

EnableRewind 的实现源代码见 BufferingHelper.cs

 

.NET Core 3.* 获取 Post 的 Body 内容字符串

更新:.NET Core 3.0 中 EnableRewind 被改名为 EnableBuffering 。

[HttpPost]
public WXNotifyResponse WXNotify(WXNotifyData request)
{
    Request.EnableBuffering();
    Request.Body.Position = 0;

    string body;
    using (var reader = new StreamReader(Request.Body))
    {
        body = reader.ReadToEnd();
    }

    return Content(body);
}
GarsonZhang www.yesdotnet.com

因为使用了一个 using,所以该方法调用过了之后,Request.Body就被 释放 了,不能再读取

.NET5 获取 Post 的 Body 内容字符串

在 Startup.cs 的 Configure 方法中添加配置

//允许body重用
app.Use(next => new RequestDelegate(
  async context =>
  {
	  context.Request.EnableBuffering();
	  await next(context);
  }
));

Post 数据 Body Data 获取方法如下:

[HttpPost]
public async Task<string> GetBodyData(WXNotifyData request)
{
    //Request.EnableBuffering();
    string body = "";
    Request.Body.Position = 0;
    using (var reader = new StreamReader(Request.Body))
    {
        body = await reader.ReadToEndAsync();
    }
    return body;
}
GarsonZhang www.yesdotnet.com

因为使用了一个 using,所以该方法调用过了之后,Request.Body就被 释放 了,不能再读取

.NET获取Post Request Body数据可以新建一个扩展 【推荐使用】

C# 全选
public static class HttpRequestExtensions
{
    /// <summary>
	/// 获得body请求
	/// </summary>
	/// <param name="request"></param>
	/// <returns></returns>
	public static string GetBodyData(this HttpRequest request)
	{
		request.EnableBuffering();
		// 改方法 StreamReader释放的时候,也会把request.Body对象释放掉,然后以后的请求就不能再次读取request.Body了
		/*
		request.Body.Seek(0, SeekOrigin.Begin);
		using (var reader = new StreamReader(request.Body, Encoding.UTF8))
		{
			var param = reader.ReadToEnd();
			return param;
		}
		*/

		// 这里由于没有释放StreamReader 担心内存问题
		/*
		string body = "";
		// 获取请求参数
		long? length = request.HttpContext.Request.ContentLength;
		//request.HttpContext.Request.Body.Position = 0;
		request.Body.Seek(0, SeekOrigin.Begin);
		if (length != null && length > 0)
		{
			// 使用这个方式读取,并且使用异步
			StreamReader streamReader = new StreamReader(request.HttpContext.Request.Body, Encoding.UTF8);
			body = streamReader.ReadToEndAsync().Result;
		}
		return body;
		*/

		string body = "";
		var buffer = new MemoryStream();
		request.Body.Seek(0, SeekOrigin.Begin);
		request.Body.CopyTo(buffer);
		buffer.Position = 0;
		try
		{
			using (StreamReader streamReader = new StreamReader(buffer, Encoding.UTF8))
			{
				body = streamReader.ReadToEndAsync().Result;
			}
		}
		finally
		{
			if (buffer != null)
				buffer.Dispose();
		}
		return body;
	}
}

使用

 [HttpPost]
public async Task<string> GetBodyData(WXNotifyData request)
{
    //Request.EnableBuffering();
    string body = Request.GetBodyData();
    return body;
}
GarsonZhang www.yesdotnet.com

 

 

版权声明:本文为YES开发框架网发布内容,转载请附上原文出处连接
YES开发框架
上一篇:TT模板断点调试
下一篇:微信支付:C#计算签名
评论列表

发表评论

评论内容
昵称:
关联文章

ASP.NET Core 读取Post Request.Body 正确姿势
.NET Core 读取 Request.Headers 姿势
C# 解析加载读取XML文件正确姿势
.NET Core鉴权授权正确方式(.NET5)
ASP.NET Core MVC路由约束
RestSharp请求https添加Cookie信息正确姿势
ASP.NET Core MVC 在过滤器ActionFilter保存页面生成html静态页面文件
asp.net - 在 ASP.NET Core MVC 嵌套 TagHelper
ASP.NET MVC和ASP.NET Core MVC获取当前URL/Controller/Action
C# ASP.NET Core开发学生信息管理系统(一)
ASP.NET Core web API使用Swagger/OpenAPI(Swashbuckle)
C# ASP.NET Core开发学生信息管理系统(三)
.NET5 ASP.NET Core 添加API限流
【推荐】Razor文件编译 ASP.NET Core
ASP.NET Core官网教程,资料查找
asp.net core 支持多种身份认证方式
C# ASP.NET Core开发学生信息管理系统(二)
ASP.NET Core 使用 LESS
.net core MVC 使用 jquery ajax请求 Post json
asp.net core 断点调试无法修改代码

联系我们
联系电话:15090125178(微信同号)
电子邮箱:garson_zhang@163.com
站长微信二维码
微信二维码