【问题标题】:HttpContext.Response.Body.Position = 0 - "Specified method is not supported" errorHttpContext.Response.Body.Position = 0 - “不支持指定的方法”错误
【发布时间】:2018-12-12 04:27:23
【问题描述】:

我已经设置了一些日志中间件,可以利用 HttpContext 抓取和记录信息。

为了读取整个流,我需要将 HttpResponse.Body 的位置设置为 0,但是,无论我尝试什么,它都会抛出“不支持指定的方法”并失败。

这对我来说很奇怪,因为位置是内置在 HttpResponse.Body 中的,而且我之前已经成功使用过它。

我也尝试使用 HttpResponse.Body.Seek 获得相同的结果。

此时我陷入困境,任何帮助将不胜感激。

更新:一旦我将 response.body 移动到一个新的内存流中,我就能够改变它的位置,但是,现在它返回一个空的 body。

public async Task Invoke(HttpContext context)
        {
            //Retrieve request & response
            var request = context.Request;
            var response = context.Response;

            if (request.Path != "/")
            {
                var reqBody = request.Body;
                var resBody = response.Body;
                string path = request.Path;
                string method = request.Method;
                string queryString = HttpUtility.UrlDecode(request.QueryString.ToString());
                int statusCode = context.Response.StatusCode;

                var buffer = new byte[Convert.ToInt32(request.ContentLength)];
                await request.Body.ReadAsync(buffer, 0, buffer.Length);
                var reqBodyText = Encoding.UTF8.GetString(buffer);
                request.Body = reqBody;

                var responseBodyStream = new MemoryStream();
                context.Response.Body = responseBodyStream;

                await _next(context);

                responseBodyStream.Seek(0, SeekOrigin.Begin);
                var resBodyText = new StreamReader(responseBodyStream).ReadToEnd();
                responseBodyStream.Seek(0, SeekOrigin.Begin);
                await responseBodyStream.CopyToAsync(context.Response.Body);

                ...
            }
        }

【问题讨论】:

  • 你什么时候调用这个方法?
  • 响应流只转发。一读就是这样。用您控制的方式替换流。这个中间件用的是什么平台?
  • @Badulake 每次有 HTTP 请求时都会调用它。
  • @Nksoi 这是在 .Net Core 中。我不确定您所说的“用您控制的方式替换流”是什么意思
  • 我需要更多信息才能知道确切的执行时间。 appstart方法,页面加载?ihttphandler?when??

标签: c# httpresponse httpcontext


【解决方案1】:

您可能在响应正文准备好之前访问它。 将 Task Invoke(HttpContext 上下文)的执行推迟到执行管道中更晚的步骤(当它准备好时)

【讨论】:

    【解决方案2】:

    我能够解决这个问题:

    首先,我将响应设置为自己的内存流,并在设置流后调用 await _next(context):

    var responseBodyStream = new MemoryStream();
    context.Response.Body = responseBodyStream;
    
    await _next(context);
    

    然后,一旦我这样做了,我注意到我得到了一个空的身体,这是由于试图将一个空的身体设置为响应上下文:

    await responseBodyStream.CopyToAsync(context.Response.Body);
    

    我删除了这条线,一切都开始正常工作了。

    【讨论】:

      【解决方案3】:

      我今天在我的 Asp.Net 核心 API 中遇到了这个问题。

      问题是,我忘记将 [FromBody] 参数添加到我的 API。添加如下内容后,问题解决了。

      [HttpPost("merkliste/create")]
      public virtual async Task<IActionResult> MerklisteWorksheetCreate(string worksheetName, [FromBody] string elementDetailsArray)
      

      希望对你有帮助。

      【讨论】:

      • 在我的情况下,我的控制器操作中没有任何参数,因此可以用 [FromBody] 装饰任何东西
      【解决方案4】:

      根据解决此问题的评论GitHub issue,您需要启用缓冲

      为此,请将以下 sn-p 添加到您的 Startup.cs Configure 方法中:

      app.Use(async (context, next) =>
      {
          context.Request.EnableBuffering();
          await next();
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-09-09
        • 2013-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-26
        • 1970-01-01
        相关资源
        最近更新 更多