返回HttpResponseMessage时记录中间件无效,但与IHttpActionResult

时间:2016-10-19 10:24:01

标签: c# asp.net asp.net-web-api2

我构建了一个非常简单的日志记录中间件,用于获取请求和响应正文。如果我从我的方法中返回IHttpActionResultTask<IHttpActionResult>,那么一切正常,但当我将其更改为HttpResponseMessageTask<HttpResponseMessage>时,我得到System.AccessViolationException

我创建了一个简单的控制器来显示我的问题:

[RoutePrefix("test")]
public class TestController : BaseApiController
{
    [AllowAnonymous]
    [HttpGet]
    [Route("a")]
    public IHttpActionResult A()
    {
        return Ok("A");
    }

    [AllowAnonymous]
    [HttpGet]
    [Route("b")]
    public async Task<IHttpActionResult> B()
    {
        //some long running operation
        await Task.Delay(1);
        return Ok("B");
    }

    [AllowAnonymous]
    [HttpGet]
    [Route("c")]
    public HttpResponseMessage C()
    {
        const string xml = "<response><body>C</body></response>";
        return new HttpResponseMessage()
        {
            Content = new StringContent(xml, Encoding.UTF8, "application/xml")
        };
    }

    [AllowAnonymous]
    [HttpGet]
    [Route("d")]
    public async Task<HttpResponseMessage> D()
    {
        //some long running operation
        await Task.CompletedTask;
        const string xml = "<response><body>D</body></response>";
        return new HttpResponseMessage()
        {
            Content = new StringContent(xml, Encoding.UTF8, "application/xml")
        };
    }
}

和我的中间件:

public static class RequestLoggerMiddlewareExtensions
{
    public static void UseRequestLogger(this IAppBuilder app)
    {
        app.Use<RequestLoggerMiddleware>();
    }
}

internal class RequestLoggerMiddleware : OwinMiddleware
{
    public RequestLoggerMiddleware(OwinMiddleware next) : base(next)
    {
    }

    public override async Task Invoke(IOwinContext context)
    {
        Stream oldResponseBody;
        string ip = context.Request.RemoteIpAddress;

        var reqContentType = context.Request.ContentType;

        //get the response body and put it back for the downstream items to read
        var reqHeaders = string.Join(",",context.Request.Headers.Select(h=>"["+h.Key+"]"+h.Value[0]).ToArray());
        string reqBody = new StreamReader(context.Request.Body).ReadToEnd();
        byte[] requestData = Encoding.UTF8.GetBytes(reqBody);
        context.Request.Body = new MemoryStream(requestData);

        var queryString = context.Request.QueryString.ToString();

        //read the path and the request method
        string reqPath = context.Request.Path.ToUriComponent();
        string reqMethod = context.Request.Method;

        //buffer the response stream
        oldResponseBody = context.Response.Body;
        //create a memory stream replacement
        MemoryStream replacement = new MemoryStream();
        //assing the replacement to the resonse body
        context.Response.Body = replacement;

        //Do the next thing
        await Next.Invoke(context);

        //grab the response code
        int responseCode = context.Response.StatusCode;

        //grab the response stream buffer
        //move to the beginning
        //copy it to the old response stream 
        replacement.Seek(0, SeekOrigin.Begin);

        //**********************Put the response back on the request body - this sends it down stream to the caller!
        await replacement.CopyToAsync(oldResponseBody);

        //move back to the head of the memory stream
        replacement.Seek(0, SeekOrigin.Begin);
        //read the response for logging
        StreamReader sr = new StreamReader(replacement);
        string responseBody = sr.ReadToEnd();

        //grab the response phrase
        string responseReasonPhrase = context.Response.ReasonPhrase;
        var responseContentType = context.Response.ContentType;

        Debug.WriteLine("IP:{0}, REQ:{1},REQ_PATH:{2},REQ_METHOD:{3},REQ_CONTENT_TYPE:{4},RES_STATUS:{5},RES_REASON:{6},RES_CONTENT_TYPE:{7},RES_BODY:{8}", ip, reqBody, reqPath, reqMethod, reqContentType, responseCode, responseReasonPhrase, responseContentType, responseBody);
    }
}

我在添加app.UseRequestLogger();

的配置方法中在Startup.cs中添加此中间件

异常显示在Visual Studio中,因此我甚至无法调试广告检查发生了什么。

该错误的原因是什么?任何线索都是受欢迎的。

0 个答案:

没有答案