2014-04-13 2 views
3

이전 프로젝트에서 WCF를 광범위하게 사용했습니다. 최근에 저는 RESTful 서비스를 만들 때 ASP.NET 웹 API를 사용하는 방법을 모색하고 있습니다. DO 및 RESTful 서비스의 DONT를 연구하고 실제적으로 시도한 후에도 나는 다소 직관적 인 질문을 가지고 있습니다.RESTful 서비스 모호함

가정하자 내가 가지고 UsersController 내가 3 GET 형 액션 메소드를 가질 필요로하는 곳에 (ApiController을 상속) :


    GetUsers() 
    GetUserById(string id) 
    GetUserByName(string name) 

한다고 가정 또한 에서 다음 경로


    config.Routes.MapHttpRoute(
     name: "Users", 
     routeTemplate: "api/users/{id}", 
     defaults: new { controller = "users", id = RouteParameter.Optional } 
    ); 

WebApiConfig이 http://localhost:<port>/api/users이 분명히 호출됩니다. GetUsers()

문제는 하나의 매개 변수를 취하는 두 가지 작업 방법 중 하나를 호출해야 할 때 발생합니다.

내가

http://localhost:<port>/api/users/5c6fe209-821e-475f-920d-1af0f3f52a82은 내가 대신 일어날 것으로 기대하는 것은 내가 오류 또는 단지를 얻을 수 있습니다 중 하나이다 GetUserByName(string name)

호출 GetUserById(string id)

http://localhost:<port>/api/users/jdoe를 호출하고 싶은

두 경우 모두 첫 번째 조치 메소드가 호출됩니다.

명확성을 위해 경로에 작업을 도입하면 순수 RESTful 서비스에서 벗어난 것으로 간주되므로 다른 URL에서 각각의 작업 방법을 호출하게하려면 어떻게해야합니까? 필자는 웹을 샅샅이 뒤졌고 RESTful 서비스의 대부분의 예제 (순수 주의자에 의한)는 모든 조치를 취하는 첫 번째 조치 메소드에서 중지하고 단일 항목을 검색하는 두 번째 조치를 중단한다.

답변

1

이것은보다 구체적인 제약 경로를 사용하여 수행 할 수 있습니다. 아래의 예는 당신이 달성하려고하는 것과 유사합니다

config.Routes.MapHttpRoute(
    name: "ById", 
    routeTemplate: "api/{controller}/{id}", 
    defaults: new { action = "GetById" }, 
    constraints: new { id = @"\d+" } 
); 

config.Routes.MapHttpRoute(
    name: "ByName", 
    routeTemplate: "api/{controller}/{name}", 
    defaults: new { action = "GetByName", }, 
    constraints: new { name = @"\w+" } 
); 

config.Routes.MapHttpRoute(
    name: "All", 
    routeTemplate: "api/{controller}", 
    defaults: new { action = "GetAll", } 
); 

제약은 MapHttpRoute가 다른 URL 매개 변수에 대한 정규식의 형태로 제약을 지정하는 패스 객체. 이 예제에서 ById 라우트의 경우 id 매개 변수가 숫자 인 경우에만 일치합니다. name 매개 변수가 알파 문자의 문자열 인 경우에만 ByName을 찾습니다. 매개 변수없이 모두 일치합니다. 각 정규식의 "+"는 빈 값을 지정하지 않습니다. 경로는 정의 된 순서대로 일치하므로 가장 구체적인 규칙을보다 구체적인 규칙 아래에 두어야합니다.

경우에 따라 사용중인 GUID 형식과 일치하는 정규식을 찾거나 쓰고이 식과 일치하도록 ById 경로를 제한해야합니다. 그런 다음 모든 문자열을 허용하는 아래에 ByName 경로를 정의 할 수 있습니다. 아래에 있기 때문에 입력 문자열이 GUID가 아닌 경우에만 호출됩니다.

이전에 MVC 경로로 작업하지 않았다면 매우 구체적이라고 덧붙여 야합니다. 내 매개 변수의 이름은 ById의 경우 {id}이고 ByName의 경우 {name}입니다. 이 매개 변수는 컨트롤러 메서드에서 입력 매개 변수의 정확한 이름과 일치해야합니다. 이는 라우터가 메서드 호출을 빌드하는 데 사용되기 때문입니다. 액션에 하나의 매개 변수 만 있어도 이름이 올바르게 매핑되지 않으면 오류가 발생합니다.

+0

스티브에게 감사드립니다.그냥 생각하면, 당신이 그것에 대해이 방법을 사용한다면 RESTful 서비스가 의도하는 유창함을 희생하지 않을 것인가? –

+0

사실, 복잡해지기를 원한다면 호출자가 액션 이름을 제공하도록하는 것이 더 낫지 않습니까? –

+0

2 개월 후 ... 나는 개인적으로/그/복잡하다고 생각하지 않는다. 그러나 암시 적 필터 동작을 사용하는 서비스를 사용하는 것이 더 간단하지만 서버 측을 작성하는 것이 더 어렵습니다. 다른 접근 방법을 선택하면 클라이언트를 복잡하게 전환하는 것입니다. 내가 말하고자하는 것은 사용자 이름이 숫자 (이 예에서는 거의 발생하지 않지만 다른 entite에서는 가능) 인 사용자가있는 경우 이름이 ID로 해석되므로 필터 메소드를 명시 적으로 지정해야하는 것은 아마 최선의 접근법. –