OData 8.0.11自定义控制器:实现实体、资源、控制器名称独立配置
解决方案
可以实现该需求,核心是通过自定义OData路由逻辑打破默认的控制器与资源名绑定规则,以下提供两种可行方案:
方案一:自定义OData路由约束
通过实现IODataRoutingConstraint来指定资源与控制器的映射关系:
- 创建自定义约束类:
public class CustomODataControllerConstraint : IODataRoutingConstraint { public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection) { if (routeDirection == HttpRouteDirection.UriGeneration) return true; // 定义映射:访问"Person"资源时,指定控制器为CustomName2 if (values.TryGetValue("odataPath", out var odataPathObj) && odataPathObj is ODataPath odataPath) { var entitySetSegment = odataPath.Segments.FirstOrDefault(s => s is EntitySetSegment) as EntitySetSegment; if (entitySetSegment?.EntitySet.Name == "Person") { values["controller"] = "CustomName2"; return true; } } return false; } // 实现接口必填成员 public ODataPathRouteConstraint InnerConstraint { get; set; } = new ODataPathRouteConstraint(); public bool IsOptional => false; }
- 在WebApi配置中注册自定义约束:
public static class WebApiConfig { public static void Register(HttpConfiguration config) { // 配置EDM模型,需显式添加Person资源映射 var modelBuilder = new ODataConventionModelBuilder(); modelBuilder.EntitySet<Person>("CustomName1"); modelBuilder.EntitySet<Person>("Person"); var edmModel = modelBuilder.GetEdmModel(); // 注册OData路由并使用自定义约束 config.Routes.MapODataServiceRoute( routeName: "ODataRoute", routePrefix: "odata", model: edmModel, routeConstraint: new CustomODataControllerConstraint() ); } }
方案二:自定义OData路由约定
通过实现IODataRoutingConvention来灵活控制控制器选择逻辑,这是更推荐的方式:
- 创建自定义路由约定类:
public class CustomControllerRoutingConvention : IODataRoutingConvention { public string SelectController(ODataPath odataPath, HttpRequestMessage request) { // 匹配资源名称,返回对应控制器名 var entitySetSegment = odataPath.Segments.FirstOrDefault(s => s is EntitySetSegment) as EntitySetSegment; if (entitySetSegment?.EntitySet.Name == "Person") { return "CustomName2"; // 指定使用CustomName2Controller } // 其他资源沿用默认规则 return null; } public string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup<string, HttpActionDescriptor> actionMap) { // 动作选择交给OData默认逻辑处理 return null; } }
- 在配置中注册自定义约定:
public static void Register(HttpConfiguration config) { var modelBuilder = new ODataConventionModelBuilder(); modelBuilder.EntitySet<Person>("CustomName1"); modelBuilder.EntitySet<Person>("Person"); var edmModel = modelBuilder.GetEdmModel(); // 获取默认路由约定集合,插入自定义约定到最前面以优先执行 var routingConventions = ODataRoutingConventions.CreateDefault(); routingConventions.Insert(0, new CustomControllerRoutingConvention()); config.Routes.MapODataServiceRoute( "ODataRoute", "odata", edmModel, routingConventions: routingConventions ); }
关键注意点
- 必须在EDM模型中显式添加
modelBuilder.EntitySet<Person>("Person"),否则OData无法识别/odata/Person这个资源路径。 - 不要直接给OData控制器添加
RouteAttribute,因为OData路由系统优先级高于WebApi常规路由,单独添加不会生效。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

