我构建了一个非常简单的日志记录中间件,用于获取请求和响应正文。如果我从我的方法中返回IHttpActionResult
或Task<IHttpActionResult>
,那么一切正常,但当我将其更改为HttpResponseMessage
或Task<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();
异常显示在Visual Studio中,因此我甚至无法调试广告检查发生了什么。
该错误的原因是什么?任何线索都是受欢迎的。