You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core OData:重写实体集路由约定实现导航键路由

在.NET 6-8中实现OData的~/entityset/key/navigation/key路由

在非Core的Microsoft.AspNet.OData环境中,我们通过重写EntitySetRoutingConvention的SelectAction方法实现~/entityset/key/navigation/key格式的路由,但在.NET 6-8的Core环境下,Microsoft.AspNetCore.OData的路由约定实现逻辑有所不同,以下是具体的实现方案:

1. 自定义路由约定类

创建继承自NavigationRoutingConvention的自定义约定,匹配目标路径模板并提取路由参数:

using Microsoft.AspNetCore.OData.Routing.Conventions;
using Microsoft.OData.UriParser;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Abstractions;

public class NavigationKeyRoutingConvention : NavigationRoutingConvention
{
    public override string? SelectAction(ODataPath odataPath, HttpContext httpContext, ILookup<string, ActionDescriptor> actionMap)
    {
        // 匹配GET请求和指定路径模板
        if (httpContext.Request.Method == HttpMethod.Get.Method && odataPath.PathTemplate == "~/entityset/key/navigation/key")
        {
            var navigationSegment = odataPath.Segments[2] as NavigationPropertySegment;
            if (navigationSegment == null)
            {
                return null;
            }

            // 构造目标Action名称
            string actionName = $"Get{navigationSegment.NavigationProperty.Name}";
            if (actionMap.Contains(actionName))
            {
                // 提取主实体键并注入路由数据
                var keySegment = odataPath.Segments[1] as KeySegment;
                if (keySegment != null)
                {
                    httpContext.ODataFeature().RouteData.Add(ODataRouteConstants.Key, keySegment.Keys.FirstOrDefault().Value);
                }

                // 提取关联实体键并注入路由数据
                var relatedKeySegment = odataPath.Segments[3] as KeySegment;
                if (relatedKeySegment != null)
                {
                    httpContext.ODataFeature().RouteData.Add(ODataRouteConstants.RelatedKey, relatedKeySegment.Keys.FirstOrDefault().Value);
                }

                return actionName;
            }
        }

        // 不匹配时交给基类处理
        return base.SelectAction(odataPath, httpContext, actionMap);
    }
}

2. 注册自定义路由约定

在.NET 6+的Program.cs中,配置OData服务时注入自定义路由约定:

var builder = WebApplication.CreateBuilder(args);

// 添加OData控制器服务
builder.Services.AddControllers().AddOData(options =>
{
    // 创建默认路由约定集合
    var conventions = ODataRoutingConventions.CreateDefault();
    // 将自定义约定插入集合头部,确保优先匹配
    conventions.Insert(0, new NavigationKeyRoutingConvention());

    // 配置OData路由组件
    options.AddRouteComponents("odata", GetEDMModel(), services =>
    {
        services.AddSingleton<IODataRoutingConvention>(new DefaultODataRoutingConvention());
        services.AddRange(conventions);
    });

    // 启用所需的OData查询选项(按需配置)
    options.Select().Filter().OrderBy().Expand().Count().SetMaxTop(null);
});

var app = builder.Build();

// 配置中间件管道
app.UseRouting();
app.UseAuthorization();
app.MapControllers();

app.Run();

// 构建EDM模型的示例方法
private static IEdmModel GetEDMModel()
{
    var modelBuilder = new ODataConventionModelBuilder();
    // 注册实体集和导航属性,示例:
    modelBuilder.EntitySet<Customer>("Customers");
    modelBuilder.EntitySet<Order>("Orders");
    // 假设Customer包含单值导航属性Order
    return modelBuilder.GetEdmModel();
}

3. 编写对应的控制器Action

在实体控制器中添加匹配名称的Action,接收路由参数:

public class CustomersController : ODataController
{
    // 匹配路径:~/odata/Customers({key})/Order({relatedKey})
    public IActionResult GetOrder(int key, int relatedKey)
    {
        // 实现业务逻辑:根据key(Customer主键)和relatedKey(Order主键)查询数据
        var targetOrder = /* 数据查询逻辑 */;
        if (targetOrder == null)
        {
            return NotFound();
        }
        return Ok(targetOrder);
    }
}

关键差异说明

  • Core环境中,路由约定的基类改为NavigationRoutingConvention,SelectAction方法的上下文参数从HttpControllerContext变为HttpContext,需通过httpContext.ODataFeature().RouteData操作路由数据。
  • 注册方式从MapODataServiceRoute改为在AddOData的AddRouteComponents中配置约定集合。
  • 整体匹配逻辑与非Core版本一致,但API细节适配了ASP.NET Core的架构。

内容的提问来源于stack exchange,提问作者Oleg Shirokikh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 21:44:55