如何从Program.cs将带动态路由的GET请求转发到自定义控制器?
问题描述
希望通过如下动态URL访问控制器方法:
http://127.0.0.1:4567/api/img/get/stuff/1/0/45/strings/numbers/andallkindsofstuff/2
其中仅api/img/get为静态路由部分,后续所有内容均为动态参数。需要将所有以api/img/get开头的GET请求路由到对应控制器方法,该方法用于生成并返回图片。
现有代码片段如下:
Program.cs 部分代码
// 业务逻辑已移除 var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.Use(async (context, next) => { if (!MyCache.Ready) return; // 正常忽略请求 // new CustomController().Get(content.Request.Path) await next(); // 调用控制器 }); app.UseMvc(); app.UseAuthorization(); app.MapControllers(); app.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
ImageController 代码
[Route("api/img")] [ApiController] public class ImageController : ControllerBase { [HttpGet] [Route("get")] public byte[] Get([FromQuery] string parameters) { // ... } }
解决方案
方案一:修改控制器路由(推荐,原生路由支持)
无需额外中间件,直接通过路由属性的通配符*捕获api/img/get之后的所有路径内容:
[Route("api/img")] [ApiController] public class ImageController : ControllerBase { // 用 * 捕获get之后的完整路径参数 [HttpGet("get/{*parameters}")] public byte[] Get(string parameters) { // parameters 会自动获取到 stuff/1/0/45/strings/numbers/andallkindsofstuff/2 // 此处可拆分、解析参数并生成图片 return new byte[0]; // 返回生成的图片字节数组 } }
配置完成后,所有以api/img/get/开头的GET请求都会自动匹配到该方法,无需额外中间件处理。
方案二:使用中间件手动路由调用控制器
如果必须通过中间件实现,可通过DI容器解析控制器实例,避免直接new导致依赖注入失效:
修改Program.cs中的中间件逻辑:
app.Use(async (context, next) => { if (!MyCache.Ready) return; var path = context.Request.Path.Value; // 判断是否为目标GET请求 if (context.Request.Method == HttpMethods.Get && path.StartsWith("/api/img/get", StringComparison.OrdinalIgnoreCase)) { // 从DI容器获取控制器实例 var imageController = context.RequestServices.GetRequiredService<ImageController>(); // 提取get之后的参数部分 var parameters = path["/api/img/get".Length..].TrimStart('/'); // 调用方法获取图片字节 var imageBytes = imageController.Get(parameters); // 设置响应头并返回图片 context.Response.ContentType = "image/png"; // 根据实际图片类型调整 await context.Response.Body.WriteAsync(imageBytes); return; // 终止后续中间件流程 } await next(); // 其他请求走正常路由流程 });
同时需确保控制器及依赖被注册到DI容器:
// 在builder.Build()之前添加 builder.Services.AddControllers(); // 若ImageController有构造函数依赖,需同步注册对应服务
内容的提问来源于stack exchange,提问作者Bitterblue
相关产品推荐
相关产品推荐

