C# 如何使用.NET4API端点从request.Content对象获取原始请求正文
我试图捕获原始请求数据以实现责任,并希望从请求对象中提取请求正文内容 我看到一些建议正在执行Request.InputStream,但是这个方法在Request对象上不可用 知道如何获取Request.Content主体的字符串表示形式吗C# 如何使用.NET4API端点从request.Content对象获取原始请求正文,c#,asp.net-web-api,C#,Asp.net Web Api,我试图捕获原始请求数据以实现责任,并希望从请求对象中提取请求正文内容 我看到一些建议正在执行Request.InputStream,但是这个方法在Request对象上不可用 知道如何获取Request.Content主体的字符串表示形式吗 您可以通过调用Request.Content属性上的readasstringasync来获取原始数据 string result = await Request.Content.ReadAsStringAsync(); 如果您希望在字节或流中使用它,则有各种
您可以通过调用
Request.Content
属性上的readasstringasync
来获取原始数据
string result = await Request.Content.ReadAsStringAsync();
如果您希望在字节或流中使用它,则有各种重载。由于这些是异步方法,您需要确保控制器是异步的:
public async Task<IHttpActionResult> GetSomething()
{
var rawMessage = await Request.Content.ReadAsStringAsync();
// ...
return Ok();
}
在这种情况下,您的端点不需要是异步的(除非您有其他异步方法)在您对@Kenneth答案的评论中,您是说
ReadAsStringAsync()
返回的是空字符串
这是因为您(或类似model binder的东西)已经阅读了内容,所以Request.content中内部流的位置在末尾
你能做的是:
public static string GetRequestBody()
{
var bodyStream = new StreamReader(HttpContext.Current.Request.InputStream);
bodyStream.BaseStream.Seek(0, SeekOrigin.Begin);
var bodyText = bodyStream.ReadToEnd();
return bodyText;
}
对于其他不想使其控制器异步、无法访问HttpContext或正在使用dotnet core的未来用户(这是我在Google上首次找到的尝试实现此目的的答案),以下内容适用于我:
[HttpPut("{pathId}/{subPathId}"),
public IActionResult Put(int pathId, int subPathId, [FromBody] myViewModel viewModel)
{
var body = new StreamReader(Request.Body);
//The modelbinder has already read the stream and need to reset the stream index
body.BaseStream.Seek(0, SeekOrigin.Begin);
var requestBody = body.ReadToEnd();
//etc, we use this for an audit trail
}
如果您既需要从请求中获取原始内容,又需要在控制器中使用它的绑定模型版本,则可能会出现此异常
NotSupportedException: Specified method is not supported.
例如,您的控制器可能是这样的,这让您想知道为什么上面的解决方案不适合您:
public async Task<IActionResult> Index(WebhookRequest request)
{
using var reader = new StreamReader(HttpContext.Request.Body);
// this won't fix your string empty problems
// because exception will be thrown
reader.BaseStream.Seek(0, SeekOrigin.Begin);
var body = await reader.ReadToEndAsync();
// Do stuff
}
公共异步任务索引(WebhookRequest)
{
使用var reader=newstreamreader(HttpContext.Request.Body);
//这不会解决字符串空的问题
//因为异常将被抛出
reader.BaseStream.Seek(0,SeekOrigin.Begin);
var body=wait reader.ReadToEndAsync();
//做事
}
您需要将模型绑定从方法参数中取出,然后手动绑定自己:
public async Task<IActionResult> Index()
{
using var reader = new StreamReader(HttpContext.Request.Body);
// You shouldn't need this line anymore.
// reader.BaseStream.Seek(0, SeekOrigin.Begin);
// You now have the body string raw
var body = await reader.ReadToEndAsync();
// As well as a bound model
var request = JsonConvert.DeserializeObject<WebhookRequest>(body);
}
公共异步任务索引()
{
使用var reader=newstreamreader(HttpContext.Request.Body);
//你不应该再需要这条线了。
//reader.BaseStream.Seek(0,SeekOrigin.Begin);
//现在,主体字符串已处于原始状态
var body=wait reader.ReadToEndAsync();
//以及一个约束模型
var request=JsonConvert.DeserializeObject(主体);
}
很容易忘记这一点,我以前解决过这个问题,但现在不得不重新学习解决方案。希望我在这里的回答能给我自己一个很好的提醒…谢谢Kenneth,但是原始消息返回一个空字符串,我做对了吗?我可以看到内容包含数据,为什么ReadAsStringAsync()返回空字符串?与@MarkKadlec的问题相同,此解决方案不起作用检查您是否在
ReadAsStringAsync
之前已经阅读过它。此方法将读取到该流的末尾,并将指针保留在该流中。如果正在调试并希望在“监视”窗口中以字符串形式查看内容,则无法在Request.Body流中进行搜索。使用此:Request.Content.ReadAsStringAsync().Result
此代码在HTTP中运行良好,但当我使用HTTPS连接时,它在bodytext中给出了空字符串,你能帮我吗?奇怪的是,对我来说,它甚至在HTTPS连接上工作。从HTTPS调用时得到空字符串,我是否需要在web配置中添加任何内容?如果您想知道.Current”-属性在HttpContext中不可用,它已被删除,原因是架构不好。此处可以找到解释:重要提示:如果您的方法没有参数,则不要使用Seek
,否则您将得到“NotSupportedException:指定的方法不受支持。Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.Seek”
public async Task<IActionResult> Index()
{
using var reader = new StreamReader(HttpContext.Request.Body);
// You shouldn't need this line anymore.
// reader.BaseStream.Seek(0, SeekOrigin.Begin);
// You now have the body string raw
var body = await reader.ReadToEndAsync();
// As well as a bound model
var request = JsonConvert.DeserializeObject<WebhookRequest>(body);
}