Request.Body在将参数添加到路径时更改

时间:2016-10-03 23:26:53

标签: c# asp.net-core

我正在开发一个处理多部分POST请求的ASP.NET Core API。

今天我尝试在路线中添加一个参数,当我尝试在IOException上调用ReadNextSectionAsync时,该参数触发MultipartReader(意外的流结束)。

我在两种情况下都将(ObjectDumperMultipartReader转储到日志中,唯一的区别(显然除了边界)是内部流的字段。流是我直接从控制器传递的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的新手,所以我可能会遗漏一些重要的东西!

1 个答案:

答案 0 :(得分:1)

看起来向路径添加参数会触发ASP.NET模型绑定,该模型绑定会读取请求正文。之后,我无法阅读。

这让我有两个选择:

  1. 使用模型绑定也可以读取文件
  2. 根本不使用模型绑定,并找到另一种获取参数的方法。
  3. 我选择了第二个选项,写道:

    [HttpPost("{id:int}/bar")]
    public void Foo()
    {
        int id = Int32.Parse((string)RouteData.Values["id"]);
    
        // ...
    }