如何在JsonConverter中注入或访问HttpContext?(ASP.NET Core 2场景)
解决ASP.NET Core 2中自定义JsonConverter注入HttpContext的问题
这个问题的核心在于ConfigureServices阶段还没有HttpContext实例,没法直接获取,但我们可以借助ASP.NET Core提供的IHttpContextAccessor服务,间接拿到当前请求的HttpContext,下面是具体的实现步骤:
1. 先注册IHttpContextAccessor服务
IHttpContextAccessor默认没被注册到DI容器里,所以得先在ConfigureServices中添加它:
public void ConfigureServices(IServiceCollection services) { // 注册HttpContext访问器,用来在运行时获取当前请求上下文 services.AddHttpContextAccessor(); // 其他服务注册代码... }
2. 实现支持依赖注入的自定义JsonConverter
创建你的转换器类,通过构造函数接收IHttpContextAccessor,这样在序列化时就能拿到当前请求的主机信息了:
public class PathWithHostConverter : JsonConverter { private readonly IHttpContextAccessor _httpContextAccessor; // 通过构造函数注入IHttpContextAccessor public PathWithHostConverter(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } // 指定只处理你需要的特定类型(比如你的自定义路径类型,或者直接处理string) public override bool CanConvert(Type objectType) { // 示例:这里假设我们处理的是string类型的路径,你可以改成自己的自定义类型 return objectType == typeof(string); } // 反序列化逻辑(如果不需要特殊处理,直接返回原始值即可) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { return existingValue ?? reader.Value; } // 核心:序列化时给路径添加主机名 public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var path = value as string; if (string.IsNullOrEmpty(path)) { writer.WriteNull(); return; } var httpContext = _httpContextAccessor.HttpContext; // 注意:非HTTP场景(比如后台任务)下HttpContext可能为null,要做降级处理 if (httpContext == null) { writer.WriteValue(path); return; } // 构造带主机名的完整路径(可以从Request中自动获取协议和主机) var fullUrl = $"{httpContext.Request.Scheme}://{httpContext.Request.Host}{path}"; writer.WriteValue(fullUrl); } }
3. 优雅注册转换器到MvcJsonOptions
直接在ConfigureServices里用BuildServiceProvider拿服务实例不是最佳实践,我们可以用IConfigureOptions来实现依赖注入式的配置:
第一步:创建MvcJsonOptions的配置类
public class ConfigureMvcJsonOptions : IConfigureOptions<MvcJsonOptions> { private readonly IHttpContextAccessor _httpContextAccessor; public ConfigureMvcJsonOptions(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } public void Configure(MvcJsonOptions options) { // 将自定义转换器添加到Json序列化配置中 options.SerializerSettings.Converters.Add(new PathWithHostConverter(_httpContextAccessor)); } }
第二步:把配置类注册到DI容器
回到ConfigureServices方法:
public void ConfigureServices(IServiceCollection services) { services.AddHttpContextAccessor(); // 注册MvcJsonOptions的配置类 services.AddSingleton<IConfigureOptions<MvcJsonOptions>, ConfigureMvcJsonOptions>(); services.AddMvc(); }
额外提醒
- 处理HttpContext为空的场景:如果你的代码会在非HTTP请求环境下序列化对象(比如定时任务、后台服务),一定要判断
HttpContext == null的情况,避免空引用异常。 - 针对特定类型优化:如果你的路径是自定义类型(比如
CustomPath),记得修改CanConvert方法返回对应的类型,在WriteJson中处理该类型的路径属性即可。
内容的提问来源于stack exchange,提问作者Felix K.
相关产品推荐
相关产品推荐

