.NET Core 6从DI容器获取请求头实现自定义BadRequest响应
解答
完全可以,你当前这个场景甚至不需要手动从DI容器解析服务,InvalidModelStateResponseFactory的入参c是ActionContext类型实例,本身就携带当前请求的HttpContext对象,可以直接访问请求头。
具体实现
直接替换你代码里读取CorrelationId的注释部分即可,记得加容错处理(比如请求头不存在CorrelationId时的降级逻辑),另外你原代码里correlatinId存在拼写错误,修正后代码如下:
services.AddControllers() .ConfigureApiBehaviorOptions(o => { o.InvalidModelStateResponseFactory = c => { var keys = c.ModelState.Where(l => l.Value.Errors.Count > 0).Select(k => k.Key).ToList(); string error = string.Empty; if (keys != null && keys.Any()) { // 原逻辑当错误字段大于1个时固定取第2个,建议按需调整,比如始终取第一个错误字段 error = keys[0]; error = error.Replace("$.", string.Empty); } var firstError = c.ModelState.Values.FirstOrDefault(v => v.Errors.Count > 0)?.Errors[0].ErrorMessage; error = $"Field: {error}. Message: {firstError ?? "参数校验失败"}"; // 直接从ActionContext携带的HttpContext读取请求头 string correlationId = string.Empty; c.HttpContext.Request.Headers.TryGetValue("CorrelationId", out var correlationIdVals); correlationId = correlationIdVals.FirstOrDefault() ?? string.Empty; // 业务要求无CorrelationId时自动生成则放开以下注释 // if (string.IsNullOrWhiteSpace(correlationId)) correlationId = Guid.NewGuid().ToString(); Response response = new(); response.Fail(correlationId, error); return new BadRequestObjectResult(response); }; }) .AddFluentValidation(o => { o.ImplicitlyValidateChildProperties = true; o.ImplicitlyValidateRootCollectionElements = true; o.RegisterValidatorsFromAssemblyContaining<LogErrorValidation>(); });
补充说明
- 如果你是在自定义的全局服务、没有直接传入
ActionContext/HttpContext的场景下要访问请求上下文,才需要提前在DI容器注册IHttpContextAccessor,注册代码为services.AddHttpContextAccessor();,注册后即可通过构造函数注入IHttpContextAccessor实例,访问其HttpContext属性获取请求信息。 - 你当前所处的模型校验响应工厂是在请求管线执行阶段触发的,入参已经直接挂载了当前请求的HttpContext,直接使用比手动从DI解析服务性能更高,也无需额外注册依赖。
内容的提问来源于stack exchange,提问作者wulung_try
相关产品推荐
相关产品推荐

