9

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

public IQueryable GetAll(string entityName);

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

  1. 在模型中注册实体。
  2. 为从 EntitySetController<> 派生的每个实体创建一个单独的控制器。

我想使用通用服务并尽可能多地避免特定于实体的实现。如果服务可以返回实体列表和相应类型,那么第一步可以很容易地自动化。这留下了第 2 步,因为到目前为止我需要为每个实体创建一个特定的控制器。我也想避免这种情况并创建一个使用通用服务的通用控制器。

谁能推荐一个解决方案,也许是通过影响 OData 路由?

4

2 回答 2

12

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

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);
于 2013-06-15T10:44:06.143 回答
7

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

我认为这个问题需要一个好的、通用的、开源的解决方案——所以我创建了一个:https ://github.com/EntityRepository/ODataServer 。它现在是预发布版,但我目前正在做很多工作。我认为不仅仅是选择正确的控制器,还有为共享控制器定义的通用模式,并且默认情况下,Web API OData 需要强类型和强命名的导航属性,这使得创建可重用实现具有挑战性。

于 2013-09-02T04:10:03.437 回答