c# - 在 ASP.NET Core FromHeader 中导致 Request.Body 被完全读取
问题描述
在 ASP.Net Core 中,我有这个操作方法:
[HttpPost("things")]
[DisableFormValueModelBinding]
public async Task<IActionResult> UploadAsync()
{
using StreamReader sr = new StreamReader(Request.Body);
string body = await sr.ReadToEndAsync().ConfigureAwait(false);
int bodyLength = body.Length;
return Ok();
}
它工作得很好。正文是流式传输的,我可以全部阅读。但是,一旦我尝试获取标题:
[HttpPost("things")]
[DisableFormValueModelBinding]
public async Task<IActionResult> UploadAsync(
[FromHeader(Name = "X-Test")] string test)
{
using StreamReader sr = new StreamReader(Request.Body);
string body = await sr.ReadToEndAsync().ConfigureAwait(false);
int bodyLength = body.Length;
return Ok();
}
主体已经在流的末尾,并且读取了零字节。显然我是从一个标题中读取的,它不应该影响请求正文。如果我将代码更改为:
[HttpPost("things")]
[DisableFormValueModelBinding]
public async Task<IActionResult> UploadAsync()
{
string test = Request.Headers["X-Test"].First();
using StreamReader sr = new StreamReader(Request.Body);
string body = await sr.ReadToEndAsync().ConfigureAwait(false);
int bodyLength = body.Length;
return Ok();
}
该动作再次开始起作用,我什至正在阅读标题。如果我切换回 FromHeader 它会再次失败。显然,FromHeader 正在内部做一些与请求正文混淆的事情。
对我来说,与 FromHeader 一起工作很重要,这样 Swagger 才能继续工作。如果没有 FromHeader,我将无法在 Swagger 中指定标头值。
所以我开始搜索,我找到了这个页面:
https://github.com/dotnet/aspnetcore/issues/18087
似乎其他人在使用 FromQuery 时遇到了类似的问题,有些人通过以下方式解决了这个问题:
结果:System.IO.IOException:流意外结束,内容可能已被另一个组件读取。在 Microsoft.AspNetCore.WebUtilities.MultipartReaderStream.ReadAsync(字节 [] 缓冲区,Int32 偏移量,Int32 计数,CancellationToken 取消令牌)
并且是“固定”的: [DisableFormValueModelBinding] 和 factory.RemoveType();
程序集 Microsoft.AspNetCore.WebUtilities,版本=3.1.0.0 程序集 Microsoft.AspNetCore.Mvc.Core,版本=3.1.0.0
...
仔细检查您的 DisableFormValueModelBindingAttribute 代码以确保它正在删除 FormFileValueProviderFactory。
我去尝试看看它是否有什么不同,但我在 NuGet 中看到的这些库的最新版本是 2.2.0 和 2.2.5,这是我安装的最新稳定版本。而且这些库中还不存在这种类型(FormFileValueProviderFactory)。使用 ILSpy 进行检查表明它确实不存在。VS 确实显示我的目标框架是 .NET Core 3.1。
无论如何,我什至不确定这会解决我的问题。
有人对我有什么建议吗?
谢谢!
解决方案
FormFileValueProviderFactory
我已经确认如果我在我的ValueProviderFactories
中搜索DisableFormValueModelBindingAttribute
,我可以通过简单地找到它Where(p => p.GetType().Name == "FormFileValueProviderFactory").FirstOrDefault()
。然后,如果我将其从工厂列表中删除,一切正常。
所以现在的问题变成了为什么我不能引用那个类型。由于我有拉起类型,我可以查看被引用的程序集,它是C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App\3.1.10\Microsoft.AspNetCore.Mvc.Core.dll
. 这意味着它甚至根本没有使用 NuGet,而是使用了这个程序集。因此,当我发现为什么以这种方式设置这个项目时,我开始删除旧的和不必要的 NuGet 引用。帮助程序库中有一些 ASP.NET Core MVC 实用程序,包括DisableFormValueModelBindingAttribute
. 此库当前配置为netstandard2.1
,这就是无法引用 ASP.NET Core 的原因。
要解决此问题,我所要做的就是将目标框架更改为netcoreapp3.1
并将其添加到引用 ASP.NET Core:
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
现在一切正常。
推荐阅读
- python-3.x - 通过 Python 在 PowerPoint 中更新链接的 excel 路径
- javascript - 有没有办法插入来自 api 的路由?
- r - 如何遍历数据集减去下面行中的值 - 使用 R
- react-native - 如何让 Android 上的 Chrome 启动我的图像选择器而不是 React Native 中的系统 UI?
- c# - 将父级转换为其通用子级
- css - 如何通过 css 强制所有帖子图像居中对齐?
- sql-server - SQL Server:跨数据库查询;所有权链接;存储过程签名/证书
- ruby - 为什么#force_encoding 会消耗大量内存而不释放它?
- python - Python3.6 ImportError:将 pip 从 8.1.1 升级到 19.0.1 后无法导入名称“main”
- javascript - 控制console.log的功能而不返回