请求在Asp.net核心自定义中间件中读取后为空

本文关键字:读取 中间件 自定义 Asp net 核心 请求 | 更新日期: 2023-09-27 18:18:14

我发现asp.net核心自定义中间件中的请求只能读取一次,之后我必须手动将请求设置回request . body。这是推荐的阅读请求的方式吗?

public async Task Invoke(HttpContext context)
{
    var request = context.Request;
    string xmlstring;
    using (System.IO.MemoryStream m = new System.IO.MemoryStream())
    {
        try
        {
            if (request.Body.CanSeek == true) request.Body.Position = 0;
            request.Body.CopyTo(m); 
            xmlstring = System.Text.Encoding.UTF8.GetString(m.ToArray());
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(xmlstring));
    await _next.Invoke(context);
}

我试着"copy"流到另一个,但没有帮助。我怀疑所有自定义中间件都有设置请求体的这一步,所以在这里问一下我是否以正确的方式做了。

请求在Asp.net核心自定义中间件中读取后为空

正确的步骤应该是:

  1. enablerewind
  2. 读取正文
  3. 做倒带

请注意:如果没有将set body返回到originalRequestBody,它将只工作一次,如果你试图再次调用相同的web api,它将失败。

请参见下面的示例代码

    public async Task Invoke(HttpContext context)
    {

        var originalRequestBody = context.Request.Body;
        context.Request.EnableRewind();
        try
        {

            using (System.IO.MemoryStream m = new MemoryStream())
            {
                context.Request.Body.CopyTo(m);
                var s = System.Text.Encoding.UTF8.GetString(m.ToArray());
            }
            //this line will rewind the request body, so it could be read again
            context.Request.Body.Position = 0;
            await _next(context);
        }
        catch (Exception ex)
        {
        }
        finally
        {
            //important, otherwise, even current request will succeed, following request will fail
            context.Request.Body = originalRequestBody;
        }
    }