无法读取输入流



我在点击控制器之前使用ActionFilterAttribute获取请求,如下所示:

public override void OnActionExecuting(HttpActionContext actionContext)
{
using (var stream = new MemoryStream())
{
HttpContextBase context = (HttpContextBase)actionContext.Request.Properties["MS_HttpContext"];
context.Request.InputStream.Seek(0, SeekOrigin.Begin);
context.Request.InputStream.CopyTo(stream);
requestBody = Encoding.UTF8.GetString(stream.ToArray());
}
}

上述方法适用于小请求,但对于大型 json,它给了我此错误:

在 HttpRequest.GetBufferedInputStream 的调用方填充内部存储之前,访问了 BinaryRead、Form、Files 或 InputStream。

输入流给出此错误

上下文。Request.InputStream 抛出了一个类型为 System.InvalidOperationException System.IO.Stream {System.InvalidOperationException} 的异常

正如我在研究中发现的那样,这是超时的问题,但我无法更改代码中的超时。我尝试更改 web.config 文件中的值maxRequestLength="102400000"maxAllowedContentLength="209715100"但仍然面临相同的错误。
如果我读取GetBufferedInputStream但仍然是相同的问题,它只是读取缓冲区的一部分,而不是整个流。

我还尝试了以下方法:

Stream InStream;
int Len;
InStream = HttpContext.Current.Request.InputStream;
Len = System.Convert.ToInt32(InStream.Length);
byte[] ByteArray = new byte[Len + 1];
InStream.Seek(0, SeekOrigin.Begin);
InStream.Read(ByteArray, 0, Len);
var jsonParam = System.Text.Encoding.UTF8.GetString(ByteArray); 

请注意,如果我将内容类型设置为application/xmlapplication/x-www-form-urlencoded它就可以工作,但是如果我将其设置为application/json它会给我此错误!!

请指教!

有几点:

首先,如果您尝试从流中读取 0 个字节,那么它将引发 System.InvalidOperationException 异常。因此,我将像下面一样更改您的代码并添加对ContentLength > 0的检查。

using (var stream = new MemoryStream())
{
HttpContextBase context = (HttpContextBase)actionContext.Request.Properties["MS_HttpContext"];
if(context.Request.Contentlength > 0)
{
context.Request.InputStream.Seek(0, SeekOrigin.Begin);
context.Request.InputStream.CopyTo(stream);
requestBody = Encoding.UTF8.GetString(stream.ToArray());
}
}

另外,我曾经遇到过同样的问题,在web.config中增加maxRequestLength似乎已经解决了这个问题。 此链接在此处进一步提供更多信息

这就是我在模型活页夹中执行此操作的方式,但我不确定它将如何与您的操作过滤器配合使用。我在网上检查了一下,有相互矛盾的信息;有人说您无法读取输入流,因为它不可搜索,ASP.NET 需要读取它才能绑定模型。有人说这确实是可以寻求的,并使用您上面分享的方法。因此,找出真正有效的方法的唯一方法是进行测试。

我希望我的代码示例可以帮助您弄清楚。

object request = null;
if (actionContext.Request.Method == HttpMethod.Post && "application/json".Equals(actionContext.Request.Content.Headers.ContentType.MediaType))
{
var jsonContentTask = actionContext.Request.Content.ReadAsStringAsync();
Task.WaitAll(jsonContentTask);
string jsonContent = jsonContentTask.Result;
//... other stuff
}

我可能是错的,但这是我发现的。操作筛选器在模型绑定后执行,这意味着已读取请求流。就你而言,我不确定这意味着什么。https://exceptionnotfound.net/the-asp-net-web-api-2-http-message-lifecycle-in-43-easy-steps-2/详细解释了生命周期。更改内容类型不会更改生命周期事件,而是更改请求内容,这反过来可能会影响模型绑定。 如果您为操作设置了模型,则如何在操作筛选器中获取当前模型应该会有所帮助。因此,解决方案是从actionContext中获取模型对象,然后相应地对其进行修改。

最新更新