代码之家  ›  专栏  ›  技术社区  ›  James Wierzba

仅为路由公开.NET OData API的子集(对于排除的API返回404)

  •  9
  • James Wierzba  · 技术社区  · 6 年前

    背景/背景:

    我们有两条路线,带有不同的路线前缀:

    1. 路由1前缀: /api
    2. /api/partial

    目前,我们对两个路由前缀使用相同的EdmModel。(参见第一个代码snippit,名为“What we current do”)。

    我们只需要允许路由2的API功能的一个子集: /api/部分 . 我们想回来 404 当有人试图访问“部分”模型不可用的API时

    例子:

    1. 我们想回来 对于 /api/parial/products ,在哪里 products 未在此“部分”API路由中定义。
    2. 我们想继续走这条路 /api/products

    我们的尝试:

    使用第二个EdmModel,它只包含完整EdmModel中可用实体的子集。(参见第二个代码snippit,名为“What we want to do:”。)

    问题:

    The path template 'products' on the action 'Export' in controller 'Products' is not a valid OData path template. Resource not found for the segment 'products'.)

    我对正在发生的事情的最好猜测是,.NETOData库扫描所有OData控制器、函数和操作,并期望在EdmModel中为每个路由显式定义它们中的每一个。如果这是真的,那么这个解决方案(初始化一个新的EdmModel)很可能不起作用。。。

    我们目前的工作:

    private static IEdmModel GetFullEdmModel()
    {
        var builder = new ODataConventionModelBuilder();
    
        var orders = builder.EntitySet<Order>("orders");
        orders.EntityType.HasKey(o => o.Id);
        orders.EntityType.Property(o => o.Id).Name = "id";
    
        var products = builder.EntitySet<Product>("products");
        products.EntityType.HasKey(p => p.Id);
        products.EntityType.Property(p => p.Id).Name = "id";
        products.EntityType.Action("Export").Returns<ExportResponse>();
    
        return builder.GetEdmModel();
    }
    
    protected override void Register(HttpConfiguration config)
    {
        base.Register(config);
    
        var model = GetFullEdmModel();
        var conventions = ODataRoutingConventions.CreateDefaultWithAttributeRouting(config, model);
    
        // Map route 1 to {model}
        config.MapODataServiceRoute(
            routeName: "route1",
            routePrefix: "/api",
            model: model, 
            pathHandler: new CustomBIODataPathHandler(), 
            routingConventions: conventions);
    
        // Map route 2 to {model}
        config.MapODataServiceRoute(
            routeName: "route2",
            routePrefix: "/api/partial", // different route prefix
            model: model, // but it uses the same model
            pathHandler: new CustomBIODataPathHandler(), 
            routingConventions: conventions);
    }
    

    我们要做的是:

    private static IEdmModel GetPartialEdmModel()
    {
        var builder = new ODataConventionModelBuilder();
    
        // Include only one entity
        var orders = builder.EntitySet<Order>("orders");
        orders.EntityType.HasKey(o => o.Id);
        orders.EntityType.Property(o => o.Id).Name = "id";
    
        return builder.GetEdmModel();
    }
    
    protected override void Register(HttpConfiguration config)
    {
        base.Register(config);
    
        // Map route 1 to {model}
        var model = GetFullEdmModel();
        var modelConventions = ODataRoutingConventions.CreateDefaultWithAttributeRouting(config, model);
        config.MapODataServiceRoute(
            routeName: "route1",
            routePrefix: "/api",
            model: model, // use standard full model
            pathHandler: new CustomBIODataPathHandler(), 
            routingConventions: conventions);
    
        // Map route 2 to a new partial model: {partialModel}    
        var partialModel = GetPartialEdmModel();
        var partialModelConventions = ODataRoutingConventions.CreateDefaultWithAttributeRouting(config, model);
        config.MapODataServiceRoute(
            routeName: "route2",
            routePrefix: "/api/partial", // different route prefix
            model: partialModel, // use a sparate, partial edm model ( a subset of the full edm model )
            pathHandler: new CustomBIODataPathHandler(), 
            routingConventions: conventions);
    }
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   David user10336229    6 年前

    你需要两个或更多不同的型号 intelligent products 不是在所有路径中都可用,但仅在 /api/products .


    // Map route 1 to {model}
    config.MapODataServiceRoute(
        routeName: "route1",
        routePrefix: "/api",
        model: GetApiModel(), 
        pathHandler: new CustomBIODataPathHandler(), 
        routingConventions: conventions);
    
    
    // Map route 2 to {model}
    config.MapODataServiceRoute(
        routeName: "route2",
        routePrefix: "/api/partial", // different route prefix
        model: GetApiPartialModel(),
        pathHandler: new CustomBIODataPathHandler(), 
        routingConventions: conventions);
    

    这是一个概念,我对代码中的符号不是很坚定,所以你可能需要调整一下。

    或者,如果您真的只想使用一个模型,可以这样尝试:

    // Map route 1 to {model}
    config.MapODataServiceRoute(
        routeName: "route1",
        routePrefix: "/api",
        model: GetFullEdmModel("/api"), 
        pathHandler: new CustomBIODataPathHandler(), 
        routingConventions: conventions);
    
    // Map route 2 to {model}
    config.MapODataServiceRoute(
        routeName: "route2",
        routePrefix: "/api/partial", // different route prefix
        model: GetFullEdmModel("/api/partial"), // but it uses the same model
        pathHandler: new CustomBIODataPathHandler(), 
        routingConventions: conventions);
    

    然后可以使用参数实现任何条件或开关。

    除此之外,您可能在底部的所需代码中有错误:

    // Map route 1 to {model}
    var model = GetFullEdmModel();
    var modelConventions = ODataRoutingConventions.CreateDefaultWithAttributeRouting(config, model);
    config.MapODataServiceRoute(
        routeName: "route1",
        routePrefix: "/api",
        model: model, // use standard full model
        pathHandler: new CustomBIODataPathHandler(), 
        routingConventions: modelConventions);
    

    请看最后一行,这两个块都需要调整。 我以前从来没有注意过每个配置块上面的两行,所以主要的问题可能是不是所有的变量都在一起,您必须检查所有的细节。