背景/背景:
我们有两条路线,它们的前缀不同:
/api
/api/partial
当前,我们对两个路由前缀使用相同的EdmModel。 (请参阅第一个代码段,名为“我们目前正在做什么”。)
我们想要的:
我们只需要为路由2:/api/partial
允许一部分API功能。当某人尝试访问“部分” EdmModel不可用的API时,我们想返回404
示例:
404
返回/api/parial/products
,其中在此“部分” API路由中未定义products
。/api/products
路由到控制器方法我们尝试的方法:
使用第二个EdmModel,该模型仅包含完整EdmModel中可用实体的子集。 (请参见第二个代码段,名为“我们想要做什么:”。)
问题:
服务启动时出现错误:
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'.)
我对发生的事情的最佳猜测是.NET OData库将扫描所有OData控制器,函数,动作,并期望它们在EdmModel中为每个路由显式定义。如果是这样,那么此解决方案(初始化新的EdmModel)将可能无法工作...
不支持此功能吗?如果没有,还有什么其他选择可以做到这一点?我们必须在控制器API函数中显式返回404吗?这将需要分析API函数中“ api / subset”的路径,在我看来,这很像黑客。
我们目前正在做什么:
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);
}
答案 0 :(得分:0)
您需要两个不同的模型或更多的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);
请参阅最后一行,然后必须针对两个块进行调整。 我从来没有关心过每个配置块上方的两行,所以主要的问题可能是并非所有变量都适合在一起,您必须检查所有细节。