Jam*_*zba 9 .net c# odata asp.net-web-api asp.net-web-api-routing
背景/环境:
我们有两条路线,路线前缀不同:
/api
/api/partial
目前,我们对两个路由前缀使用相同的EdmModel.(参见第一个代码snippit,名为"我们目前正在做什么").
我们想要什么:
我们只需要为路由2允许API功能的子集:/api/partial
.404
当有人试图访问"部分"EdmModel不可用的API时,我们希望返回
例:
404
的/api/parial/products
,其中products
没有在这个"局部" API路线定义./api/products
到控制器方法我们尝试过的:
使用第二个EdmModel,它只包含完整EdmModel中可用实体的子集.(参见第二个代码snippit,名为"我们想做什么:".)
问题:
我们在服务启动时遇到错误:
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"的路径,这在我看来就像是一个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);
}
Run Code Online (Sandbox Code Playgroud)
我们想做什么:
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);
}
Run Code Online (Sandbox Code Playgroud)
您需要两个不同的模型或更多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);
Run Code Online (Sandbox Code Playgroud)
这是一个概念,我对该代码中的符号不太确定,因此您可能需要对其进行一些调整。
或者,如果您确实只想使用一种模型,请像这样尝试:
// 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);
Run Code Online (Sandbox Code Playgroud)
然后你可以使用该参数来实现任何条件或开关。
除此之外,您可能在底部所需的代码中存在错误:
// 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);
Run Code Online (Sandbox Code Playgroud)
请参阅最后一行,然后必须对两个块进行调整。我以前从未关心过每个配置块上方的两行,因此主要问题可能是并非所有变量都适合在一起,您必须检查所有细节。
归档时间: |
|
查看次数: |
197 次 |
最近记录: |