2013-01-23 17 views
12

Ich habe WebApi-Controller, die mit dem Suffix "Api" in ihren Namen enden (z. B. StudentsApiController, InstructorsApiController). Ich mache das, um meine MVC-Controller leicht von WebApi-Controllern zu unterscheiden. Ich möchte, dass meine WebApi-Routen ähnlich wieASP.NET Web Api Routing Anpassung

http://localhost:50009/api/students/5 und nicht http://localhost:50009/api/studentsapi/5 aussehen.

Zeit, dies zu erreichen, ist ich die Einrichtung Routen wie

routes.MapHttpRoute(
name: "GetStudents", 
routeTemplate: "api/students/{id}", 
defaults: new { controller = "StudentsApi", id = RouteParameter.Optional }); 

routes.MapHttpRoute(
name: "GetInstructors", 
routeTemplate: "api/instructors/{id}", 
defaults: new { controller = "InstructorsApi", id = RouteParameter.Optional }); 

Dies ist sehr umständlich zu drehen, wie ich eine Route für jede Methode in meinem Controller hinzuzufügen habe. Ich hoffe, es sollte eine einfache Möglichkeit geben, Routenvorlagen einzurichten, die beim Bearbeiten von Routen automatisch das "api" -Suffix des Controllernamens hinzufügen.

Antwort

7

Ich denke, der Erweiterbarkeitspunkt, nach dem Sie suchen, ist der Controller Selektor. Sie können eine Klasse erstellen, die von DefaultHttpControllerSelector abgeleitet ist und den GetControllerName überschreibt, um den "api" -Teil zu entfernen. Sie können diesen Controller-Selektor dann in den Konfigurationsdiensten Ihres Dienstes registrieren.

+0

Klingt wie ein guter Ort zu suchen. Ich werde das mal versuchen und euch wissen lassen, wie das geht. – muruge

9

Nach @Youssef Moussaoui Richtung schrieb ich den folgenden Code, der das Problem löste.

public class ApiControllerSelector : DefaultHttpControllerSelector 
{ 
    public ApiControllerSelector(HttpConfiguration configuration) 
     : base(configuration) 
    { 
    } 

    public override string GetControllerName(HttpRequestMessage request) 
    { 
     if (request == null) 
      throw new ArgumentNullException("request"); 

     IHttpRouteData routeData = request.GetRouteData(); 

     if (routeData == null) 
      return null; 

     // Look up controller in route data 
     object controllerName; 
     routeData.Values.TryGetValue("controller", out controllerName); 

     if (controllerName != null) 
      controllerName += "api"; 

     return (string)controllerName; 
    } 
} 

und registrieren Sie es in Global.asax als

GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector), 
      new ApiControllerSelector(GlobalConfiguration.Configuration)); 
+1

muruge, das wäre viel einfacher, wenn Sie einfach base.GetControllerName aufrufen und dann "api" hinzufügen. Aber das ist die richtige Idee. Freut mich zu sehen, dass dies funktioniert :) –

+0

Ich stimme zu, das wäre viel sauberer. Hat mich nicht geschlagen. :) – muruge

+0

Ich muss etwas verpassen, das funktioniert nicht für mich. Ich sehe, wie mein Controller Selector aufgerufen wird und am Ende mit api zurückkehrt, aber mein Controller wird nie aufgerufen. –

7

Nun, da ASP.NET Web API 2 ist, gibt es eine viel weniger umständlich Art und Weise ist, wie komplexere Routing zu tun, dass Sie vorgeschlagen, unter Verwendung von attribute routing.

An der Spitze des Controllers fügen Sie einfach das folgende Attribut:

[RoutePrefix("api/students")] 
public class StudentsApiController : ApiController 
{ 
    ... 
} 

Und dann vor jedem API-Methode:

[Route("{id}"] 
public HttpResponseMessage Get(int id) 
{ 
    ... 
} 

Es ist ein bisschen Setup erforderlich, aber das Positive zu tun Routing auf diese Weise sind viele. Zum einen können Sie das Routing mit den Controllern und Methoden, die die eigentliche Arbeit tun, setzen, so dass Sie nie suchen und fragen, ob Sie die richtige Route haben. Zweitens, und noch wichtiger, ist es viel einfacher, komplexeres Routing durchzuführen, etwa wenn der Controller-Name anders ist als der Routenname (wie Sie wollen) oder sehr komplexe Muster haben, mit denen verglichen werden soll.

+0

Es benötigt weiterhin das Suffix "Controller" mit Attribut-Routing. – angularsen

1

Kommentar des Youssef Im Anschluss an muruug Antwort würde in so etwas wie dies aussieht

public class ApiControllerSelector : DefaultHttpControllerSelector 
{ 
    public ApiControllerSelector (HttpConfiguration configuration) : base(configuration) { } 

    public override string GetControllerName(HttpRequestMessage request) 
    { 
     return base.GetControllerName(request) + "api"; 
    } 
}