2013-01-23 29 views
12

Tôi có bộ điều khiển WebApi kết thúc bằng hậu tố "Api" trong tên của chúng (Ví dụ: StudentsApiController, InstructorsApiController). Tôi làm điều này để dễ dàng phân biệt các bộ điều khiển MVC của tôi từ bộ điều khiển WebApi. Tôi muốn các tuyến đường WebApi của tôi trông giống nhưTùy chỉnh định tuyến ASP.NET Web Api

http://localhost:50009/api/students/5 và không http://localhost:50009/api/studentsapi/5.

Hiện nay để đạt được điều này, tôi đang thiết lập các tuyến đường như

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

này được chuyển ra được rất cồng kềnh như tôi phải thêm một tuyến đường cho mỗi phương pháp trong điều khiển của tôi. Tôi hy vọng sẽ có một cách dễ dàng để thiết lập các mẫu tuyến đường tự động thêm hậu tố "api" vào tên bộ điều khiển trong khi xử lý các tuyến đường.

Trả lời

7

Tôi nghĩ điểm mở rộng bạn đang tìm là bộ chọn bộ điều khiển. Bạn có thể tạo một lớp có nguồn gốc từ DefaultHttpControllerSelector và ghi đè GetControllerName để loại bỏ phần "api". Sau đó bạn có thể đăng ký bộ chọn bộ điều khiển này trên Dịch vụ cấu hình dịch vụ của bạn.

+0

Âm thanh như một nơi tốt để nhìn vào. Tôi sẽ cung cấp cho một shot và cho bạn biết làm thế nào mà đi. – muruge

9

Theo chỉ dẫn của @Youssef Moussaoui, tôi đã kết thúc viết đoạn mã sau giải quyết được sự cố.

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

Và đăng ký nó trong Global.asax như

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

muruge, điều này sẽ dễ dàng hơn nhiều nếu bạn chỉ cần gọi base.GetControllerName và sau đó thêm "api" vào nó. Nhưng đó là ý tưởng đúng. Vui mừng khi thấy điều này làm việc ra :) –

+0

Tôi đồng ý, điều đó sẽ sạch hơn nhiều. Không tấn công tôi. :) – muruge

+0

Tôi phải thiếu một cái gì đó, điều này không làm việc cho tôi. Tôi thấy bộ điều khiển của tôi nhận được gọi và nó trở về với api ở cuối nhưng bộ điều khiển của tôi không bao giờ được gọi. –

7

Bây giờ ASP.NET Web API 2 là ra, có một cách ít rườm rà để làm định tuyến phức tạp hơn như bạn đề nghị, bằng cách sử dụng attribute routing.

Ở phía trên của điều khiển của bạn chỉ cần thêm thuộc tính sau:

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

Và rồi trước mỗi phương pháp API:

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

Có một chút về thiết lập cần thiết, nhưng những mặt tích cực làm định tuyến theo cách này rất nhiều. Đối với một, bạn có thể đặt định tuyến với các bộ điều khiển và phương pháp thực hiện công việc thực tế, vì vậy bạn không bao giờ tìm kiếm xung quanh tự hỏi liệu bạn có đúng tuyến đường hay không. Thứ hai và quan trọng hơn, việc định tuyến phức tạp hơn dễ dàng hơn nhiều, giống như việc có tên bộ điều khiển khác với tên tuyến đường (như bạn muốn) hoặc có các mẫu rất phức tạp để đối sánh.

+0

Nó vẫn cần hậu tố "Bộ điều khiển" với định tuyến thuộc tính. – angularsen

1

Sau comment Youssef về câu trả lời của muruug sẽ giống như thế này

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

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