Muh*_*zim 7 c# middleware asp.net-core
我正在尝试创建一个可以记录响应正文以及全局管理异常的中间件,我成功了。我的问题是我放在异常中的自定义消息没有显示在响应中。
中间件代码 01:
public async Task Invoke(HttpContext context)
{
context.Request.EnableRewind();
var originalBodyStream = context.Response.Body;
using (var responseBody = new MemoryStream())
{
try
{
context.Response.Body = responseBody;
await next(context);
context.Response.Body.Seek(0, SeekOrigin.Begin);
var response = await new StreamReader(context.Response.Body).ReadToEndAsync();
context.Response.Body.Seek(0, SeekOrigin.Begin);
// Process log
var log = new LogMetadata();
log.RequestMethod = context.Request.Method;
log.RequestUri = context.Request.Path.ToString();
log.ResponseStatusCode = context.Response.StatusCode;
log.ResponseTimestamp = DateTime.Now;
log.ResponseContentType = context.Response.ContentType;
log.ResponseContent = response;
// Keep Log to text file
CustomLogger.WriteLog(log);
await responseBody.CopyToAsync(originalBodyStream);
}
catch (Exception ex)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
var jsonObject = JsonConvert.SerializeObject(My Custom Model);
await context.Response.WriteAsync(jsonObject, Encoding.UTF8);
return;
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果我这样编写中间件,我的自定义异常工作正常,但我无法记录我的响应正文。
中间件代码 02:
public async Task Invoke(HttpContext context)
{
context.Request.EnableRewind();
try
{
await next(context);
}
catch (Exception ex)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
var jsonObject = JsonConvert.SerializeObject(My Custom Model);
await context.Response.WriteAsync(jsonObject, Encoding.UTF8);
return;
}
}
Run Code Online (Sandbox Code Playgroud)
我的控制器操作:
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
throw new Exception("Exception Message");
}
Run Code Online (Sandbox Code Playgroud)
现在我想用我的中间件 01 显示我的异常消息,但它不起作用,但它在我的中间件 02 上工作。
所以我的观察是出现了读取上下文响应的问题。我的中间件 01 代码中是否遗漏了什么?
有没有更好的方法可以满足我的目的,即记录响应主体并全局管理异常?
我认为您的意思是此代码并未将其响应发送给客户端。
catch (Exception ex)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
var jsonObject = JsonConvert.SerializeObject(My Custom Model);
await context.Response.WriteAsync(jsonObject, Encoding.UTF8);
return;
}
Run Code Online (Sandbox Code Playgroud)
这样做的原因是它await context.Response.WriteAsync(jsonObject, Encoding.UTF8);不是写入原始正文流,而是写入可查找的内存流。因此,在写入之后,您必须将其复制到原始流中。所以我相信代码应该是这样的:
catch (Exception ex)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
var jsonObject = JsonConvert.SerializeObject(My Custom Model);
await context.Response.WriteAsync(jsonObject, Encoding.UTF8);
context.Response.Body.Seek(0, SeekOrigin.Begin); //IMPORTANT!
await responseBody.CopyToAsync(originalBodyStream); //IMPORTANT!
return;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7876 次 |
| 最近记录: |