ASP.NET WebAPI:OData端点的通用控制器

时间:2013-06-14 14:56:49

标签: asp.net-web-api odata

我目前正在使用ASP.NET MVC 4 Web API中的OData端点进行试验。我喜欢这个概念,并尝试在我们的项目中提出有效的方法。 我有一个问题如下:我们有一个能够返回IQueryable并将实体名称作为输入的服务:

public IQueryable GetAll(string entityName);

在标准Web API(与OData控制器相对)中,我可以创建一个通用控制器,可以以/ api / entities / {entityName}的形式调用并返回IQueryable。 对于OData控制器,我执行以下特定于实体的步骤:

  1. 在模型中注册实体。
  2. 为从EntitySetController<>派生的每个实体创建一个单独的Controller。
  3. 我想使用通用服务,尽可能避免实体特定的实现。如果服务可以返回实体列表和相应类型,则可以轻松地自动完成第一步。 这留下了第2步,因为到目前为止我需要为每个实体创建一个特定的控制器。我还想避免这种情况,并创建一个使用通用服务的通用控制器。

    任何人都可以通过影响OData路由推荐解决方案吗?

2 个答案:

答案 0 :(得分:11)

您可以创建自定义路由约定,无论实体集是什么,都会选择相同的控制器。例如,

public class CustomControllerRoutingConvention : IODataRoutingConvention
{
    public string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup<string, HttpActionDescriptor> actionMap)
    {
        return null;
    }

    public string SelectController(ODataPath odataPath, HttpRequestMessage request)
    {
        return "SomeFixedContrllerNameWithoutTheControllerSuffix";
    }
}

您可以使用以下代码

注册该路由约定
IList<IODataRoutingConvention> routingConventions = ODataRoutingConventions.CreateDefault();
routingConventions.Insert(0, new CustomControllerRoutingConvention());
config.Routes.MapODataRoute("OData", "odata", builder.GetEdmModel(), new DefaultODataPathHandler(), routingConventions);

答案 1 :(得分:6)

我遇到了同样的问题,最后编写了自定义IHttpControllerSelector而不是IODataRoutingConvention。如果您的通用控制器不需要泛型,IODataRoutingConvention看起来是个不错的选择。但由于IODataRoutingConvention.SelectController()只返回一个字符串,我看不出它如何用于实例化具有泛型类型参数的控制器。

我认为这个问题需要一个好的,通用的开源解决方案 - 所以我创建了一个:http://entityrepository.codeplex.com。现在是预发布,但我目前正在做很多工作。我认为除了选择正确的控制器之外还有更多内容,为共享控制器定义了一般模式,默认情况下,Web API OData需要强类型和强命名的导航属性,这使得创建可重用的实现变得具有挑战性。 / p>