我正在开发一个处理多部分POST请求的ASP.NET Core API。
今天我尝试在路线中添加一个参数,当我尝试在IOException
上调用ReadNextSectionAsync
时,该参数触发MultipartReader
(意外的流结束)。
我在两种情况下都将(ObjectDumper)MultipartReader
转储到日志中,唯一的区别(显然除了边界)是内部流的字段。流是我直接从控制器传递的Request.Body
。
我将用一个最小的例子来表明这种差异:
[Route("foo/")]
public class FooController : Controller
{
private readonly ILogger<FooController> _log;
public FooController(ILoggerFactory loggerFactory)
{
_log = loggerFactory.CreateLogger<FooController>();
}
[HttpPost("1/bar")]
public void Foo()
{
_log.LogInformation(Request.Body.DumpToString("Works"));
}
}
记录以下内容:
INFO: #1: Works [Microsoft.AspNetCore.Server.Kestrel.Internal.Http.FrameRequestStream]
{
properties {
CanRead = True [System.Boolean]
CanSeek = False [System.Boolean]
CanWrite = False [System.Boolean]
#2: Length = TargetInvocationException: Exception has been thrown by the target of an invocat (+4 chars) [System.Reflection.TargetInvocationException]
#3: Position = TargetInvocationException: Exception has been thrown by the target of an invocat (+4 chars) [System.Reflection.TargetInvocationException]
CanTimeout = False [System.Boolean]
#4: ReadTimeout = TargetInvocationException: Exception has been thrown by the target of an invocat (+4 chars) [System.Reflection.TargetInvocationException]
#5: WriteTimeout = TargetInvocationException: Exception has been thrown by the target of an invocat (+4 chars) [System.Reflection.TargetInvocationException]
}
fields {
#6: _body [Microsoft.AspNetCore.Server.Kestrel.Internal.Http.MessageBody+ForContentLength]
{
properties {
RequestKeepAlive = True [System.Boolean]
}
fields {
_contentLength = 242 [System.Int64]
_inputLength = 242 [System.Int64]
}
}
_state = Open [Microsoft.AspNetCore.Server.Kestrel.Internal.Http.FrameStreamState]
{
fields {
value__ = 0 [System.Int32]
}
}
}
}
但是,如果我这样做:
[Route("foo/")]
public class FooController : Controller
{
// ...
// Same logging setup
// ...
[HttpPost("{id:int}/bar")] // This doesn't actually need to change
public void Foo(int id)
{
_log.LogInformation(Request.Body.DumpToString("Doesn't work"));
}
}
_inputLength
字段的值为0。
然后,当我使用此流创建MultipartReader
时,它在第一次调用ReadNextSectionAsync
时失败。
这对我来说看起来有点像ASP.NET Core,但我是ASP.NET的新手,所以我可能会遗漏一些重要的东西!
答案 0 :(得分:1)
看起来向路径添加参数会触发ASP.NET模型绑定,该模型绑定会读取请求正文。之后,我无法阅读。
这让我有两个选择:
我选择了第二个选项,写道:
[HttpPost("{id:int}/bar")]
public void Foo()
{
int id = Int32.Parse((string)RouteData.Values["id"]);
// ...
}