ASP.NET Core 6 Web API如何通过URL参数而非路径值实现路由?
动态路由转发实现方案
需求说明
客户端仅能请求固定URL:http://exampleDomain.com/ControllerDemo/HubActions?ActionName={ActionName},需根据ActionName参数值,将请求路由至对应的/ControllerDemo/{ActionName}接口(如ActionName=ActionA则路由到/ControllerDemo/ActionA)。
实现方式
方式一:在目标Controller方法内转发(适用于ASP.NET Web API)
直接在ControllerDemoController的HubActions方法中,根据参数构造目标URL并转发请求:
public class ControllerDemoController : ApiController { public async Task<HttpResponseMessage> HubActions(string actionName) { // 构造目标请求URL var targetUri = new Uri(Request.RequestUri.AbsoluteUri.Replace( "HubActions?ActionName=" + actionName, actionName )); // 创建转发请求并发送 var forwardRequest = new HttpRequestMessage(Request.Method, targetUri); return await Configuration.Services.GetHttpClient().SendAsync(forwardRequest); } }
方式二:自定义路由约束(ASP.NET Web API优雅方案)
通过自定义路由约束,在路由层面直接将请求导向目标Action,无需在方法内写转发逻辑:
- 配置自定义路由(WebApiConfig.cs):
public static void Register(HttpConfiguration config) { // 匹配HubActions请求的自定义路由 config.Routes.MapHttpRoute( name: "HubActionRoute", routeTemplate: "ControllerDemo/HubActions", defaults: new { controller = "ControllerDemo", action = "HubActions" }, constraints: new { actionName = new HubActionRouteConstraint() } ); // 常规API路由 config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "{controller}/{action}", defaults: new { id = RouteParameter.Optional } ); }
- 实现自定义路由约束类:
public class HubActionRouteConstraint : IHttpRouteConstraint { public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection) { if (routeDirection != HttpRouteDirection.UriResolution) return false; // 从Query参数中提取ActionName var actionName = request.GetQueryNameValuePairs() .FirstOrDefault(p => p.Key.Equals("ActionName", StringComparison.OrdinalIgnoreCase)) .Value; if (!string.IsNullOrWhiteSpace(actionName)) { // 替换路由的Action值为目标ActionName values["action"] = actionName; return true; } return false; } }
方式三:ASP.NET Core中间件实现
在ASP.NET Core中,可通过中间件拦截请求并修改路径,实现路由转发:
- 编写中间件类:
public class HubActionMiddleware { private readonly RequestDelegate _next; public HubActionMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { var request = context.Request; // 匹配固定请求路径 if (request.Path.Equals("/ControllerDemo/HubActions", StringComparison.OrdinalIgnoreCase)) { var actionName = request.Query["ActionName"].FirstOrDefault(); if (!string.IsNullOrWhiteSpace(actionName)) { // 修改请求路径为目标Action路径 request.Path = $"/ControllerDemo/{actionName}"; } } // 传递请求到下一个中间件 await _next(context); } }
- 在Program.cs中注册中间件:
var app = builder.Build(); // 注册自定义中间件(需放在路由中间件之前) app.UseMiddleware<HubActionMiddleware>(); app.MapControllers(); app.Run();
内容的提问来源于stack exchange,提问作者Shire
相关产品推荐
相关产品推荐

