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

栏目: ASP.NET · 发布时间: 5年前

内容简介:翻译自:https://stackoverflow.com/questions/51314002/expose-only-a-subset-of-net-odata-apis-for-a-route-return-404-for-excluded-api

背景/环境:

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

>路由1前缀:/ api

>路由2前缀:/ api / partial

目前,我们对两个路由前缀使用相同的EdmModel. (参见第一个代码snippit,名为“我们目前正在做什么”).

我们想要什么:

我们只需要为Route 2允许API功能的子集:/ api / partial.当有人试图访问“部分”EdmModel不可用的API时,我们希望返回404

例:

>我们希望为/ api / parial / products返回404,其中产品未在此“部分”API路径中定义.

>我们仍希望将/ api / products路由到控制器方法

我们尝试过的:

使用第二个EdmModel,它只包含完整EdmModel中可用实体的子集. (参见第二个代码snippit,名为“我们想做什么:”.)

问题:

我们在服务启动时遇到错误:

控制器“产品”中操作“导出”的路径模板“产品”不是有效的OData路径模板.未找到该段“产品”的资源.)

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

这不受支持吗?如果没有,还有什么其他选择来实现这一目标?我们必须在控制器API函数中显式返回404吗?这需要分析API函数中“api / subset”的路径,这在我看来就像是一个hack.

我们目前的工作:

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);
}

您需要两种不同的型号或更具智能的型号,因为有权使用的产品并非在所有路径中都可用,而只能在/ 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);

查看最后一行,然后必须针对这两个块进行调整.

关于每个配置块上面的两行,我从来没有注意过,所以主要的问题可能是并非所有变量都适合在一起,你需要在所有细节中检查它.

翻译自:https://stackoverflow.com/questions/51314002/expose-only-a-subset-of-net-odata-apis-for-a-route-return-404-for-excluded-api


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

国际游戏设计全教程

国际游戏设计全教程

[美]迈克尔·萨蒙德 / 张然、赵嫣 / 中国青年出版社 / 2017-2 / 108.00元

你想成为一名电子游戏设计师吗?想知道《肯塔基0号路》《到家》《枪口》等独立游戏的制作理念及过程吗?想了解《戈莫布偶大冒险》《辐射3》《战争机器》中关卡设计的奥秘吗?本书用通俗易懂的文字介绍了在游戏开发与策划过程中,需要掌握的游戏设计原理和制作的基础知识,可以作为读者从“构思一个电子游戏”到“真正完成一个电子游戏”的完备指南。 本书以系统的游戏设计流程结合大量优秀的游戏设计案例进行讲解,让读者......一起来看看 《国际游戏设计全教程》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试