【发布时间】:2015-06-13 10:11:00
【问题描述】:
使用 Web Api 我有一个 OData 端点,它可以从数据库返回产品。
我有多个具有相似架构的数据库,并且想在 URL 中传递一个参数来确定 Api 应该使用哪个数据库。
当前 Odata 端点:
http://localhost:62999/Products
我想要什么:
http://localhost:62999/999/Products
在新的 Url 中,我传入 999(数据库 ID)。
数据库 ID 用于指定从哪个数据库加载产品。例如,localhost:62999/999/Products('ABC123') 将从数据库 999 加载产品“ABC123”,但下一个请求 localhost:62999/111/Products('XYZ789') 将从数据库 111 加载产品“XYZ789”。
下面的网址可以用,但我不喜欢它。localhost:62999/Products('XYZ789')?database=111
这是控制器的代码:
public class ProductsController : ErpApiController //extends ODataController, handles disposing of database resources
{
public ProductsController(IErpService erpService) : base(erpService) { }
[EnableQuery(PageSize = 50)]
public IQueryable<ProductDto> Get(ODataQueryOptions<ProductDto> queryOptions)
{
return ErpService.Products(queryOptions);
}
[EnableQuery]
public SingleResult<ProductDto> Get([FromODataUri] string key, ODataQueryOptions<ProductDto> queryOptions)
{
var result = ErpService.Products(queryOptions).Where(p => p.StockCode == key);
return SingleResult.Create(result);
}
}
我使用 Ninject 通过绑定到服务提供者来解析将哪个 IErpService 实现注入到控制器中:
kernel.Bind<IErpService>().ToProvider(new ErpServiceProvider());
而ErpServiceProvider 会检查 url 以识别此请求所需的 databaseId:
public class ErpServiceProvider : Provider<IErpService>
{
protected override IErpService CreateInstance(IContext context)
{
var databaseId = HttpContext.Current.Request["database"];
return new SageErpService(new SageContext(GetDbConnection(databaseId)));
}
}
我坚持的一点是如何在 OData 路由配置中定义 Url 参数。
普通的 WebApi 路由可以有如下定义的参数:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
但是如何在 OData 路由配置中定义参数呢?
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<ProductDto>("Products");
builder.EntitySet<WorkOrderDto>("WorkOrders");
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: null,
model: builder.GetEdmModel());
这甚至是我应该定义 Url 参数的地方吗? 我也考虑过使用消息处理程序,但我也不确定如何实现。
更新
这个问题试图和我做同样的事情:How to declare a parameter as prefix on OData
但不清楚如何从 url 中读取参数。 var databaseId = HttpContext.Current.Request["database"]; 当前返回 null。
即使将路由配置更新为以下内容:
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "ErpApi",
routeTemplate: "{database}/{controller}"
);
// Web API configuration and services
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<ProductDto>("Products");
builder.EntitySet<WorkOrderDto>("WorkOrders");
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: "{company}/",
model: builder.GetEdmModel());
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
【问题讨论】:
-
澄清一下...您是要使用 ID 来指定从数据库中选择哪个单一产品,还是从哪个数据库中选择所有产品?
-
它旨在指定从哪个数据库加载产品。例如,
localhost:62999/999/Products('ABC123')将从数据库 999 加载产品“ABC123”,但下一个请求localhost:62999/111/Products('XYZ789')将从数据库 111 加载产品“XYZ789”。 -
嗨,philreed,您的问题解决了吗?我已经为您的问题提出了解决方案
-
抱歉,还没有。我尝试了您的解决方案,但路由仍然无法正常工作。明天我会再花更多的时间来解决这个问题。
标签: c# asp.net asp.net-web-api odata