我如何 return 在 asp.net 核心中自定义 http header?
How can I return custom http header in asp.net core?
再见,
我正在使用 aspnet core 开发一系列微服务。我想 return 自定义 http header 500 个响应。
我试图创建一个自定义 ASP.NET 核心中间件 来更新 context.Response.Headers 属性但它仅在响应为 200 时有效。
这是我的自定义中间件:
namespace Organizzazione.Progetto
{
public class MyCustomMiddleware
{
private readonly RequestDelegate _next;
public ExtractPrincipalMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
context.Response.Headers.Add("X-Correlation-Id", Guid.NewGuid());
await _next.Invoke(context);
return;
}
}
}
这是我的配置方法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMiddleware<MyCustomMiddleware>();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseMvc();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API");
});
}
我如何 return 我的自定义 header 对由未处理的异常(或可能对所有响应)引起的 500 响应?
非常感谢
您必须订阅 httpContext.Response.OnStarting
public class CorrelationIdMiddleware
{
private readonly RequestDelegate _next;
public CorrelationIdMiddleware(RequestDelegate next)
{
this._next = next;
}
public async Task Invoke(HttpContext httpContext)
{
httpContext.Response.OnStarting((Func<Task>)(() =>
{
httpContext.Response.Headers.Add("X-Correlation-Id", Guid.NewGuid().ToString());
return Task.CompletedTask;
}));
try
{
await this._next(httpContext);
}
catch (Exception)
{
//add additional exception handling logic here
//...
httpContext.Response.StatusCode = 500;
}
}
}
并注册您的 Startup
app.UseMiddleware(typeof(CorrelationIdMiddleware));
您可以使用全局过滤器:
public class CorrelationIdFilter : IActionFilter
{
/// <summary>
/// Called after the action executes, before the action result.
/// </summary>
/// <param name="context">The <see cref="T:Microsoft.AspNetCore.Mvc.Filters.ActionExecutedContext" />.</param>
public void OnActionExecuted(ActionExecutedContext context)
{
}
/// <summary>
/// Called before the action executes, after model binding is complete.
/// </summary>
/// <param name="context">The <see cref="T:Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext" />.</param>
/// <exception cref="InvalidOperationException"></exception>
public void OnActionExecuting(ActionExecutingContext context)
{
context.HttpContext.Response.Headers.Add("X-Correlation-Id", Guid.NewGuid().ToString());
}
}
如果您只在异常情况下执行相同操作,请使用 IExceptionFilter:
public class CorrelationIdFilter : IExceptionFilter, IAsyncExceptionFilter
{
private readonly ILogger<CorrelationIdFilter> _logger;
/// <summary>
/// Initialize a new instance of <see cref="CorrelationIdFilter"/>
/// </summary>
/// <param name="logger">A logger</param>
public CorrelationIdFilter(ILogger<CorrelationIdFilter> logger)
{
_logger = logger;
}
/// <summary>
/// Called after an action has thrown an <see cref="T:System.Exception" />.
/// </summary>
/// <param name="context">The <see cref="T:Microsoft.AspNetCore.Mvc.Filters.ExceptionContext" />.</param>
/// <returns>
/// A <see cref="T:System.Threading.Tasks.Task" /> that on completion indicates the filter has executed.
/// </returns>
public Task OnExceptionAsync(ExceptionContext context)
{
Process(context);
return Task.CompletedTask;
}
/// <summary>
/// Called after an action has thrown an <see cref="T:System.Exception" />.
/// </summary>
/// <param name="context">The <see cref="T:Microsoft.AspNetCore.Mvc.Filters.ExceptionContext" />.</param>
public void OnException(ExceptionContext context)
{
Process(context);
}
private void Process(ExceptionContext context)
{
var e = context.Exception;
_logger.LogError(e, e.Message);
context.HttpContext.Response.Headers.Add("X-Correlation-Id", Guid.NewGuid().ToString());
if (e is InvalidOperationException)
{
context.Result = WriteError(HttpStatusCode.BadRequest, e);
}
else if (e.GetType().Namespace == "Microsoft.EntityFrameworkCore")
{
context.Result = WriteError(HttpStatusCode.BadRequest, e);
}
else
{
context.Result = WriteError(HttpStatusCode.InternalServerError, e);
}
}
private IActionResult WriteError(HttpStatusCode statusCode, Exception e)
{
var result = new ApiErrorResult(e.Message, e)
{
StatusCode = (int)statusCode,
};
return result;
}
}
/// <summary>
/// Api error result
/// </summary>
/// <seealso cref="Microsoft.AspNetCore.Mvc.ObjectResult" />
public class ApiErrorResult : ObjectResult
{
private readonly string _reasonPhrase;
/// <summary>
/// Initializes a new instance of the <see cref="ApiErrorResult"/> class.
/// </summary>
/// <param name="reasonPhrase">The reason phrase.</param>
/// <param name="value">The value.</param>
public ApiErrorResult(string reasonPhrase, object value) : base(value)
{
_reasonPhrase = reasonPhrase;
}
/// <inheritdoc />
public override async Task ExecuteResultAsync(ActionContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var reasonPhrase = _reasonPhrase;
reasonPhrase = reasonPhrase.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)[0];
context.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = reasonPhrase;
await base.ExecuteResultAsync(context);
}
}
并使用 :
注册您的过滤器
services.AddMvc(configure =>
{
var filters = configure.Filters;
filters.Add<CorrelationIdFilter >();
})
再见,
我正在使用 aspnet core 开发一系列微服务。我想 return 自定义 http header 500 个响应。
我试图创建一个自定义 ASP.NET 核心中间件 来更新 context.Response.Headers 属性但它仅在响应为 200 时有效。
这是我的自定义中间件:
namespace Organizzazione.Progetto
{
public class MyCustomMiddleware
{
private readonly RequestDelegate _next;
public ExtractPrincipalMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
context.Response.Headers.Add("X-Correlation-Id", Guid.NewGuid());
await _next.Invoke(context);
return;
}
}
}
这是我的配置方法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMiddleware<MyCustomMiddleware>();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseMvc();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API");
});
}
我如何 return 我的自定义 header 对由未处理的异常(或可能对所有响应)引起的 500 响应?
非常感谢
您必须订阅 httpContext.Response.OnStarting
public class CorrelationIdMiddleware
{
private readonly RequestDelegate _next;
public CorrelationIdMiddleware(RequestDelegate next)
{
this._next = next;
}
public async Task Invoke(HttpContext httpContext)
{
httpContext.Response.OnStarting((Func<Task>)(() =>
{
httpContext.Response.Headers.Add("X-Correlation-Id", Guid.NewGuid().ToString());
return Task.CompletedTask;
}));
try
{
await this._next(httpContext);
}
catch (Exception)
{
//add additional exception handling logic here
//...
httpContext.Response.StatusCode = 500;
}
}
}
并注册您的 Startup
app.UseMiddleware(typeof(CorrelationIdMiddleware));
您可以使用全局过滤器:
public class CorrelationIdFilter : IActionFilter
{
/// <summary>
/// Called after the action executes, before the action result.
/// </summary>
/// <param name="context">The <see cref="T:Microsoft.AspNetCore.Mvc.Filters.ActionExecutedContext" />.</param>
public void OnActionExecuted(ActionExecutedContext context)
{
}
/// <summary>
/// Called before the action executes, after model binding is complete.
/// </summary>
/// <param name="context">The <see cref="T:Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext" />.</param>
/// <exception cref="InvalidOperationException"></exception>
public void OnActionExecuting(ActionExecutingContext context)
{
context.HttpContext.Response.Headers.Add("X-Correlation-Id", Guid.NewGuid().ToString());
}
}
如果您只在异常情况下执行相同操作,请使用 IExceptionFilter:
public class CorrelationIdFilter : IExceptionFilter, IAsyncExceptionFilter
{
private readonly ILogger<CorrelationIdFilter> _logger;
/// <summary>
/// Initialize a new instance of <see cref="CorrelationIdFilter"/>
/// </summary>
/// <param name="logger">A logger</param>
public CorrelationIdFilter(ILogger<CorrelationIdFilter> logger)
{
_logger = logger;
}
/// <summary>
/// Called after an action has thrown an <see cref="T:System.Exception" />.
/// </summary>
/// <param name="context">The <see cref="T:Microsoft.AspNetCore.Mvc.Filters.ExceptionContext" />.</param>
/// <returns>
/// A <see cref="T:System.Threading.Tasks.Task" /> that on completion indicates the filter has executed.
/// </returns>
public Task OnExceptionAsync(ExceptionContext context)
{
Process(context);
return Task.CompletedTask;
}
/// <summary>
/// Called after an action has thrown an <see cref="T:System.Exception" />.
/// </summary>
/// <param name="context">The <see cref="T:Microsoft.AspNetCore.Mvc.Filters.ExceptionContext" />.</param>
public void OnException(ExceptionContext context)
{
Process(context);
}
private void Process(ExceptionContext context)
{
var e = context.Exception;
_logger.LogError(e, e.Message);
context.HttpContext.Response.Headers.Add("X-Correlation-Id", Guid.NewGuid().ToString());
if (e is InvalidOperationException)
{
context.Result = WriteError(HttpStatusCode.BadRequest, e);
}
else if (e.GetType().Namespace == "Microsoft.EntityFrameworkCore")
{
context.Result = WriteError(HttpStatusCode.BadRequest, e);
}
else
{
context.Result = WriteError(HttpStatusCode.InternalServerError, e);
}
}
private IActionResult WriteError(HttpStatusCode statusCode, Exception e)
{
var result = new ApiErrorResult(e.Message, e)
{
StatusCode = (int)statusCode,
};
return result;
}
}
/// <summary>
/// Api error result
/// </summary>
/// <seealso cref="Microsoft.AspNetCore.Mvc.ObjectResult" />
public class ApiErrorResult : ObjectResult
{
private readonly string _reasonPhrase;
/// <summary>
/// Initializes a new instance of the <see cref="ApiErrorResult"/> class.
/// </summary>
/// <param name="reasonPhrase">The reason phrase.</param>
/// <param name="value">The value.</param>
public ApiErrorResult(string reasonPhrase, object value) : base(value)
{
_reasonPhrase = reasonPhrase;
}
/// <inheritdoc />
public override async Task ExecuteResultAsync(ActionContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var reasonPhrase = _reasonPhrase;
reasonPhrase = reasonPhrase.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)[0];
context.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = reasonPhrase;
await base.ExecuteResultAsync(context);
}
}
并使用 :
注册您的过滤器services.AddMvc(configure =>
{
var filters = configure.Filters;
filters.Add<CorrelationIdFilter >();
})