2017-09-11 3 views
1

J'ai des contrôleurs WebApi 2 fonctionnant côte à côte avec un seul contrôleur OData dans le même projet. Essayer de définir la configuration de routage nécessaire:Quelle est la bonne façon d'étendre les méthodes OData à un seul contrôleur?

  • toute demande /api doit être mis en correspondance avec ce ODataController
  • toutes les autres demandes doivent être adressées aux contrôleurs de api Web ordinaire

Lorsque je tente à la carte /api route vers OData contoller comme ceci:

class WebApiConfig 
{ 
    public static void Register(HttpConfiguration configuration) 
    { 
    configuration.Routes.MapHttpRoute("API Default", "api/{action}/{id}", 
     new { controller = "ApiOdata", id = RouteParameter.Optional }); 

    ODataModelBuilder builder = new ODataConventionModelBuilder(); 
    builder.EntitySet<Organization>("Organizations"); 
    configuration.Routes.MapODataServiceRoute(
     routeName: "ODataRoute", 
     routePrefix: "Api", 
     model: builder.GetEdmModel()); 
    } 
} 

tous les appels de méthode fonctionnent correctement à la fois pour les contrôleurs Web Api et OData, mais ces requêtes telles que /api/$ metadata ne fonctionnent pas.

Lorsque je supprime la route "par défaut API" - demande aux méthodes de régulation OData telles /api/Organisations cesse de travailler (retour 404) mais /api/métadonnées $ commence à.

Message détaillé erreur 404:

<Error> 
<Message> 
    No HTTP resource was found that matches the request URI 'http://localhost:53576/api/Organizations'. 
</Message> 
<MessageDetail> 
    No type was found that matches the controller named 'Organizations'. 
</MessageDetail> 
</Error> 

Quelle est la bonne façon de retrouver tous les OData appelle à des actions de contrôleur unique?

Répondre

0

Enfin fini avec des conventions de routage personnalisées. classe ajoutée pour elle:

public class CustomControllerRoutingConvention : IODataRoutingConvention 
{ 
    public string SelectAction(System.Web.OData.Routing.ODataPath odataPath, HttpControllerContext controllerContext, ILookup<string, HttpActionDescriptor> actionMap) 
    { 
     if (odataPath.PathTemplate.StartsWith("~/entityset") 
      || odataPath.PathTemplate.StartsWith("~/unboundfunction")) 
     { 
      return odataPath.Segments[0].Identifier; 
     } 
     // Not a match. 
     return null;  
    } 

    public string SelectController(System.Web.OData.Routing.ODataPath odataPath, HttpRequestMessage request) 
    { 
     if (!odataPath.PathTemplate.Contains("$metadata")) 
     { 
      if (odataPath.PathTemplate != "~") 
      { 
       return "ApiOdata"; 
      } 
     } 
     return null; 
    } 
} 

et l'utiliser dans la méthode Registre des WebApiConfig.cs:

public static void Register(HttpConfiguration configuration) 
{ 
    ... 
    IList<IODataRoutingConvention> routingConventions = ODataRoutingConventions.CreateDefault(); 
    routingConventions.Insert(0, new CustomControllerRoutingConvention()); 

    configuration.MapODataServiceRoute(
     routeName: "ODataRoute", 
     routePrefix: "Api", 
     pathHandler: new DefaultODataPathHandler(), 
     routingConventions: routingConventions, 
     model: builder.GetEdmModel()); 
} 

Ce n'est pas solution parfaite et ne sert pas à chaque demande OData (seules les métadonnées, entitysets et les fonctions non liées, comme "api/Organisations") mais c'est assez pour travailler avec des clients comme o.js et Simple.Odata.Client. En outre, cela a permis d'éviter d'endommager le contrôleur et de gonfler mon projet.