我正在更新一些netstandard2.0
代码,使其不同步从HttpRequest.Body
(Stream
(读取(这会引发异常netcoreapp3.0
除非您设置AllowSynchronousIO
选项,这显然不是一个好主意(。
我已经转换了 JSON 反序列化部分(使用System.Text.Json
(,但在此之前,它使用StreamReader
进行了偷偷摸摸的.Peek()
(以查看主体是对象还是数组(,我不确定在哪里寻找异步且不会消耗Stream
的现代替代方案。
using var reader = new StreamReader(stream);
switch (reader.Peek()) // TODO: Find an async equivalent!
{
case '{':
return await JsonSerializer.DeserializeAsync<GraphQLRequest>(stream);
case '[':
return await JsonSerializer.DeserializeAsync<GraphQLRequest[]>(stream);
default:
// ...
}
实际上,Peek
方法首先将流读入其缓冲区,然后从中为您提供值(查看dotnet运行时存储库(。所以它移动了流的位置。但是,如果不读取并因此查找流,则无法实现速览功能。
由于您无法返回 HttpRequestStream,因此更好的策略是读取整个内容,然后使用Utf8JsonReader
来确定请求是对象还是数组。请注意,Utf8JsonReader
不能在异步方法中声明,因此我不得不将其放在单独的非异步方法中。
private static JsonTokenType GetTokenType(byte[] bytes)
{
var reader = new Utf8JsonReader(bytes.AsSpan());
reader.Read();
return reader.TokenType;
}
var ms = new MemoryStream();
await Request.Body.CopyToAsync(ms);
var jsonBytes = ms.ToArray();
switch (GetTokenType(jsonBytes))
{
case JsonTokenType.StartObject:
return JsonSerializer.Deserialize<GraphQLRequest>(jsonBytes);
case JsonTokenType.StartArray:
return JsonSerializer.Deserialize<GraphQLRequest[]>(jsonBytes);
default:
// ...
}
由于我们的独特情况,在对此进行了反复讨论之后,我们(幸运的是!(得到了@davidfowl的帮助,他们使用PipeReader
为我们提供了一个示例,这是一种AdvanceTo
方法,可以查看令牌但不使用流,因此我们可以直接从流中使用Deserialize
。
完整的来源在这里。