我正在开发一个新的 OData 项目,并且第一次尝试使用 Web API 2 来完成它。 OData 提要的安装非常简单,这与 WCF 相比非常棒。
我现在遇到的问题是我的 OData feed 将在“多租户”环境中使用,我想根据租户对 feed 使用“友好”URL。因此,理想情况下我需要的 feed URL 如下所示:
/store/tenant1/Products
/store/tenant2/Products
两个 URL 都指向相同的控制器并最终指向相同的数据集,但我想根据租户强制执行一些实体过滤。显然,这会很困难,并且与标准 Web API 路由有些不同,因为我只能指定路由前缀,而不能指定路由模板。
到目前为止,我已经修改了 OData 控制器以将租户名称作为参数,这在点击以下 url 时效果很好(这不完全是我想要的,请参阅上面的目标):
http://mydomainname/odata/Products?tenantName=test
使用此路由定义:
ODataConventionModelBuilder modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Product>("Products");
IEdmModel model = modelBuilder.GetEdmModel();
config.Routes.MapODataRoute(routeName: "OData", routePrefix: "odata", model: model);
这是我的控制器上的示例操作:
[Queryable]
public IQueryable<Product> GetPproducts(string tenantName)
{
return _products.Where(p=>p.TenantName == tenantName);
}
我不太确定这是否可行,我的最后手段是使用 URL 重写规则,但我宁愿避免这种情况,并以正确的方式将所有内容都放在代码中。
经过一番调查,我发现它的工作方式是这样的:只需将路由前缀名称应用于查询,例如:
public class MoviesController : ODataController
{
private MoviesContext _db = new MoviesContext();
public IHttpActionResult Get()
{
var routeName=Request.ODataProperties().RouteName;
ODataRoute odataRoute=Configuration.Routes[routeName] as ODataRoute;
var prefixName = odataRoute.RoutePrefix;
return Ok(_db.Movies.Where(m=>m.Title.StartsWith(prefixName)));
}
// Other methods here
}
注意:以上代码基于 https://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/OData/v4/ 中的 ODataActionsSample 现在 OData v4 已经成为 OASIS 的标准,但 v3 还没有,所以 v4 似乎是一个很好的起点。