【发布时间】:2020-07-09 22:56:15
【问题描述】:
我正在尝试创建一个以某种方式更改请求的中间件。我能够阅读并更改内容,但我无法弄清楚如何正确设置流编写器以创建新正文。当我调用 normalized.WriteToAsync(jsonWriter) 时,MemoryStream 仍然为空,因此我收到 A non-empty request body is required. 异常。我在这里想念什么?这是我目前所拥有的:
public async Task Invoke(HttpContext context)
{
if (context.Request.ContentType == "application/json" && context.Request.ContentLength > 0)
{
using var scope = _logger.BeginScope("NormalizeJson");
try
{
using var requestReader = new HttpRequestStreamReader(context.Request.Body, Encoding.UTF8);
using var jsonReader = new JsonTextReader(requestReader);
var json = await JToken.LoadAsync(jsonReader);
var normalized = _normalize.Visit(json); // <-- Modify json and return JToken
// Create new Body
var memoryStream = new MemoryStream();
var requestWriter = new StreamWriter(memoryStream);
var jsonWriter = new JsonTextWriter(requestWriter);
await normalized.WriteToAsync(jsonWriter); // <-- At this point the MemoryStream has still 0 length.
var content = new StreamContent(memoryStream.Rewind()); // <-- Use helper extension to Seek.Begin = 0
context.Request.Body = await content.ReadAsStreamAsync();
}
catch (Exception e)
{
_logger.Scope().Exceptions.Push(e);
}
}
await _next(context);
}
演示用于 LINQPad 等:
async Task Main()
{
var token = JToken.FromObject(new User { Name = "Bob" });
var memoryStream = new MemoryStream();
var requestWriter = new StreamWriter(memoryStream);
var jsonWriter = new JsonTextWriter(requestWriter);
await token.WriteToAsync(jsonWriter);
memoryStream.Length.Dump(); // <-- MemoryStream.Length = 0
}
public class User
{
public string Name { get; set; }
}
【问题讨论】:
-
我想避免先将其转换为
string。 -
既然您要写信给
MemoryStream,为什么还要使用async? -
@dbc 我对此没有任何聪明的答案,但一致性。你会用别的东西代替吗?
-
是的,我会做
WriteTo(),宣布胜利并继续前进? -
@t3chb0t 当我在
jsonWriter上调用Flush()时,内存流会获取数据,因此您可能需要将编写器包装在using中
标签: c# asp.net-web-api request json.net asp.net-core-middleware