如何替换已弃用的Microsoft.AspNetCore.Http及HttpContext
替代方案:使用ASP.NET Core现代请求处理方式
针对你原来基于Microsoft.AspNetCore.Http的请求处理逻辑,现在可以用ASP.NET Core的控制器或最小API来替代,这两种方式都是当前官方推荐的标准方案,完全替代旧的直接操作HttpContext的模式。
方案一:使用控制器(ControllerBase)
控制器是ASP.NET Core中结构化处理HTTP请求的主流方式,自动封装了请求响应的处理逻辑,无需直接操作原始HttpContext(如需获取,可通过HttpContextAccessor注入)。
转换后的示例代码
[ApiController] [Route("your-route")] public class YourController : ControllerBase { private readonly ILogger<YourController> _log; private readonly IDictionary<string, IService> _serv; private readonly CancellationToken _hostCancellationToken; private readonly ICache _cache; private readonly IResponseBuilder _responseBuilder; private bool Started { get; set; } // 通过构造函数注入依赖 public YourController(ILogger<YourController> log, IDictionary<string, IService> serv, IHostApplicationLifetime hostLifetime, ICache cache, IResponseBuilder responseBuilder) { _log = log; _serv = serv; _hostCancellationToken = hostLifetime.ApplicationStopping; _cache = cache; _responseBuilder = responseBuilder; } [HttpGet] public async Task<IActionResult> HandleRequest([FromRoute] long version) { if (!Started) { return StatusCode((int)HttpStatusCode.ServiceUnavailable); } var format = GetAcceptedFormat(Request, _serv.Keys); if (!_serv.TryGetValue(format, out var serv)) { return StatusCode((int)HttpStatusCode.NotImplemented, $"Requested Content-Type {format} is not supported with current configuration."); } try { Response.ContentType = format; using var cancellationSource = CancellationTokenSource.CreateLinkedTokenSource(_hostCancellationToken, HttpContext.RequestAborted); await Read(Response.Body, version, cancellationSource.Token); return Ok(); } catch (ParameterException e) { return BadRequest(e.Message); } catch (KeyNotFoundException) { return NotFound("Not found"); } catch (Exception e) { _log.LogError(e, "An exception occurred while writing the response"); return StatusCode((int)HttpStatusCode.InternalServerError, e.ToString()); } } public Task Read(Stream target, long version, CancellationToken ct) { return Task.Run(() => { _cache.InTransaction(() => { using var reader = _cache.GetReader(); var (lastVersion, items) = (reader.GetVersion(), ReadByType(reader, version)); _responseBuilder.WriteFrom(target, items, lastVersion, ct); }); }, ct); } // 保留你的GetAcceptedFormat方法逻辑 private string GetAcceptedFormat(HttpRequest request, IEnumerable<string> supportedFormats) { // 原逻辑实现 } }
关键替代点说明
- 路由参数获取:用
[FromRoute]特性直接绑定,替代context.GetRouteParameter<long>("version") - 响应状态码:使用
ControllerBase提供的方法(如BadRequest()、NotFound()、StatusCode())替代自定义的FailWith扩展 - 请求/响应访问:通过控制器的
Request、Response属性访问,无需直接传入HttpContext - 依赖注入:通过构造函数注入所需服务(如日志、缓存),替代手动维护实例
方案二:使用最小API
如果你的业务逻辑简单,不需要复杂的控制器结构,可以用轻量的最小API,直接在Program.cs中定义端点:
转换后的示例代码
var builder = WebApplication.CreateBuilder(args); // 注册依赖服务 builder.Services.AddSingleton<IDictionary<string, IService>>(yourServiceDictionary); builder.Services.AddSingleton<ICache>(yourCache); builder.Services.AddSingleton<IResponseBuilder>(yourResponseBuilder); var app = builder.Build(); var hostCancellationToken = app.Lifetime.ApplicationStopping; var log = app.Services.GetRequiredService<ILogger<Program>>(); var serv = app.Services.GetRequiredService<IDictionary<string, IService>>(); var cache = app.Services.GetRequiredService<ICache>(); var responseBuilder = app.Services.GetRequiredService<IResponseBuilder>(); bool started = false; app.MapGet("your-route/{version:long}", async (HttpContext context, long version) => { if (!started) { return Results.StatusCode((int)HttpStatusCode.ServiceUnavailable); } var format = GetAcceptedFormat(context.Request, serv.Keys); if (!serv.TryGetValue(format, out var service)) { return Results.StatusCode((int)HttpStatusCode.NotImplemented, $"Requested Content-Type {format} is not supported with current configuration."); } try { context.Response.ContentType = format; using var cancellationSource = CancellationTokenSource.CreateLinkedTokenSource(hostCancellationToken, context.RequestAborted); await Read(context.Response.Body, version, cancellationSource.Token, cache, responseBuilder); return Results.Ok(); } catch (ParameterException e) { return Results.BadRequest(e.Message); } catch (KeyNotFoundException) { return Results.NotFound("Not found"); } catch (Exception e) { log.LogError(e, "An exception occurred while writing the response"); return Results.StatusCode((int)HttpStatusCode.InternalServerError, e.ToString()); } }); app.Run(); // 提取Read方法为静态或注入服务 static Task Read(Stream target, long version, CancellationToken ct, ICache cache, IResponseBuilder responseBuilder) { return Task.Run(() => { cache.InTransaction(() => { using var reader = cache.GetReader(); var (lastVersion, items) = (reader.GetVersion(), ReadByType(reader, version)); responseBuilder.WriteFrom(target, items, lastVersion, ct); }); }, ct); } // 保留GetAcceptedFormat方法 static string GetAcceptedFormat(HttpRequest request, IEnumerable<string> supportedFormats) { // 原逻辑实现 }
关键替代点说明
- 端点定义:用
MapGet等方法直接绑定路由和处理逻辑 - 响应结果:使用
Results静态类提供的方法返回标准HTTP响应 - 依赖获取:通过
app.Services获取已注册的服务,或直接在端点委托中注入
核心注意事项
- 取消令牌处理:两种方案都保留了
CancellationTokenSource.CreateLinkedTokenSource的逻辑,结合主机停止令牌和请求中止令牌,确保请求能正确取消 - 错误处理:替代了自定义的
FailWith,使用框架内置的响应方法,符合ASP.NET Core的标准错误处理流程 - 内容类型设置:仍然可以通过
Response.ContentType设置响应的Content-Type,和原逻辑保持一致
内容的提问来源于stack exchange,提问作者user122222
相关产品推荐
相关产品推荐

