2017-09-11 6 views
1

Ich habe WebApi 2-Controller Seite an Seite mit einzelnen OData-Controller im selben Projekt arbeiten. Der Versuch, benötigt Routing-Konfiguration einzurichten:Was ist der richtige Weg, um OData-Methoden auf einen einzelnen Controller zu beschränken?

  • alle Anforderung an /api sollte sollte
  • zu gewöhnlichen Web Api-Controller gerichtet auf diese ODataController
  • alle anderen Anforderungen abgebildet werden werden

Wenn ich versuche, /api Route zu OData contoller wie diese zur Karte:

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()); 
    } 
} 

Alle Methodenaufrufe funktionieren sowohl für den Web Api als auch für den OData Controller, aber solche Anfragen wie /api/$ Metadaten funktionieren nicht.

Wenn ich "API Default" Route entfernen - Anfragen an OData-Controller Methoden wie /api/Organisationen nicht mehr funktioniert (Rückkehr 404), aber /api/$ Metadaten beginnt.

Detaillierte 404-Fehlermeldung:

<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> 

Was ist der richtige Weg, um alle OData abzubilden Anrufe an einzelne Controller-Aktionen?

Antwort

0

Schließlich endete mit benutzerdefinierten Routing-Konventionen. Hinzugefügt Klasse für sich:

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; 
    } 
} 

und verwenden Sie es in Register-Methode von 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()); 
} 

Es ist nicht perfekt Lösung und dient nicht jede OData Anfrage (nur Metadaten, entitysets und ungebundene Funktionen, wie "api/Organizations"), reicht aber für die Arbeit mit Clients wie o.js und Simple.Odata.Client. Auch erlaubt es Controller zu vermasseln und Blähungen für mein Projekt zu vermeiden.

Verwandte Themen