![](/img/trans.png)
[英]How to retrieve users info (and also roles) based on bearer token without web-api?
[英]How to retrieve cancellation token in web-api action that consumes multipart/* request (.Net 5)
我有一個 web.api 動作,通過流接受多部分/表單數據,所以它沒有任何 arguments:
[HttpPost("api/longrunning")]
[Consumes("multipart/form-data")]
public async Task<IActionResult> LongRunningAsync(){
string? boundary = MultipartRequestHelper.GetBoundary(
MediaTypeHeaderValue.Parse(Request.ContentType),
DefaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
MultipartSection? section = await reader.ReadNextSectionAsync(); // <---- exception thrown here if below argument is specified
// imagine the rest of below link is implemented here
// https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-5.0#upload-large-files-with-streaming
// tldr: it streams incoming files directly to disk, and some form-data in memory, each part is processed
// as a stream, so I can't use attributes like [FormData], because that would put everything in memory
// If I used [FormData] with a poco, and cancellation token as two arguments, it would probably work, but that doesn't support streaming
}
但是,這樣我就沒有任何可用的取消令牌。 所以我嘗試使用默認的.Net支持的取消:
public async Task<IActionResult> LongRunningAsync(CancellationToken cancellationToken){
在普通的 controller 中,這可以正常工作,但是在這種類型的 controller 中,由於 Multipartreader,我得到了一個異常:
Unexpected end of Stream, the content may have already been read by another component.
at Microsoft.AspNetCore.WebUtilities.MultipartReaderStream.<ReadAsync>d__36.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Microsoft.AspNetCore.WebUtilities.StreamHelperExtensions.<DrainAsync>d__3.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.WebUtilities.MultipartReader.<ReadNextSectionAsync>d__20.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at MyNamespace.MyController.<LongRunningAsync>d__8.MoveNext() in C:\Source\Project\MyController.cs:line 94
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.<Execute>d__0.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<<InvokeActionMethodAsync>g__Logged|12_1>d.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<<InvokeNextActionFilterAsync>g__Awaited|10_0>d.MoveNext()
那么我該如何解決呢? 通常當框架檢測到請求被取消或放棄時,內置的取消令牌就會觸發。 但在這種情況下,我不能使用它,但我真的很想讓 api 取消請求,這樣它就可以涓涓細流並取消所有適用的操作。
由於 in.Net web api 控制器派生自ControllerBase
,它們都具有HttpContext
實例屬性,您可以使用其RequestAborted
令牌。 相應的文檔
所以是這樣的:
[HttpPost("api/longrunning")]
[Consumes("multipart/form-data")]
public async Task<IActionResult> LongRunningAsync(){
var cancellationToken = this.HttpContext.RequestAborted;
string? boundary = MultipartRequestHelper.GetBoundary(
MediaTypeHeaderValue.Parse(Request.ContentType),
DefaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
MultipartSection? section = await reader.ReadNextSectionAsync(cancellationToken); // you can already start passing it to methods that support it
// ....
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.