如何通过代码为ControllerModel的每个Action添加两个RouteAttribute路由?
解决Action自动添加双路由的问题
要实现AppStore控制器的每个Action同时拥有api/services/app/{ActionName}和api/services/AppStore/{ActionName}两个路由,核心是给每个Action添加多个独立的Selector(每个Selector对应一条路由规则),而不是修改现有Selector或者拼接路由字符串。
修改后的实现代码
public static void Map(ControllerModel model) { // 初始化基础路由前缀列表,所有控制器默认都有app前缀 var routePrefixes = new List<string> { "api/services/app" }; // 如果是AppStore控制器,额外添加AppStore前缀 if (AppStore.Contains(model.ControllerName)) { routePrefixes.Add("api/services/AppStore"); } foreach (var action in model.Actions) { // 获取当前Action的约定HTTP动词(比如GET/POST等) var httpVerb = ProxyScriptingHelper.GetConventionalVerbForMethodName(action.ActionName); var methodConstraint = new HttpMethodActionConstraint(new List<string> { httpVerb }); // 清空Action默认的Selector,避免默认路由干扰我们的自定义规则 action.Selectors.Clear(); // 为每个前缀创建独立的Selector,对应一个路由 foreach (var prefix in routePrefixes) { var newSelector = new SelectorModel(); // 添加HTTP方法约束,确保路由只响应指定动词 newSelector.ActionConstraints.Add(methodConstraint); // 设置完整路由模板 var routeTemplate = $"{prefix.EnsureEndsWith('/')}{model.ControllerName}/{action.ActionName}"; newSelector.AttributeRouteModel = new AttributeRouteModel(new RouteAttribute(routeTemplate)); // 将新Selector添加到Action的路由选择器集合中 action.Selectors.Add(newSelector); } } }
关键思路说明
- 多Selector对应多路由:ASP.NET Core中,一个Action可以通过多个
SelectorModel绑定多个独立路由,每个Selector就是一条独立的路由规则。 - 前缀列表化处理:把需要的路由前缀放到列表中,遍历列表为每个前缀生成对应的Selector,后续要添加更多前缀只需扩展列表即可,扩展性更强。
- 清空默认Selector:避免Action自带的默认路由(比如基于控制器/Action名称的默认路由)和我们的自定义路由冲突,确保只有我们设置的路由生效。
为什么AttributeRouteModel.CombineAttributedRouteModel不符合需求
这个方法的作用是拼接路由模板,比如原有路由是api/services/app/xxx,Combine新的api/services/AppStore/xxx后,最终会得到api/services/app/xxx/api/services/AppStore/xxx这种拼接后的错误路由,完全不是我们想要的“同时拥有两个独立路由”的效果,所以不能用它来实现需求。
内容的提问来源于stack exchange,提问作者highboi
相关产品推荐
相关产品推荐

