内容简介:翻译自: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
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 【 数据集合】并集、交集、差集、子集
- 微服务不是全部,只是特定领域的子集
- R中的子集选取运算符
- 常用算法思想之动态规划的区间子集思想
- 算法 - 找出数组中子集乘积的最大值
- Python编程实现从字典中提取子集的方法分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。