2016-10-03 63 views
1

我正在處理處理多部分POST請求的ASP.NET Core API。將參數添加到路由時Request.Body發生更改

今天我試圖給路由添加一個參數,當我試圖在MultipartReader上調用ReadNextSectionAsync時觸發IOException(意外的流結束)。

在這兩種情況下,我都將(使用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核心錯誤,但我是ASP.NET的新手,所以我可能會錯過重要的東西!

回答

1

它看起來像在路由中添加一個參數觸發了ASP.NET模型綁定,它讀取了請求主體。之後,我無法閱讀它。

這給我留下了兩個選項:

  1. 使用模型綁定來讀取文件以及
  2. 不使用模型綁定都找到獲取參數的另一種方式。

我選擇了第二個選項,寫這樣的:

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

    // ... 
}