2014-09-22 3 views
0

웹 API 컨트롤러에서 리소스 표현에 대한 링크를 추가하는 것은 정말 쉽습니다. 이런 식으로, 당신은 경로 이름을 사용하여 링크의 HREF를 구축 할 수 있습니다 (UrlHelper 클래스이다) 컨트롤러의 Url 속성을 사용 :ASP.NET 웹 API로 경로 기반 템플릿이 적용된 외부 참조 만들기

var href = Url.Link("RouteName", new { id = 123 }); 
href의 값은 경로 구성을 기반으로 계산됩니다

- 같은이 경우 뭔가 http://example.org/api/products/123. 이것은 hrefs가 생성되는 모든 장소를 업데이트하지 않고도 라우트 구성을 조정할 수 있기 때문에 좋습니다. 생성 된 모든 링크는 새 구성을 따릅니다.

그러나이 또는 다른 유사한 경로 기반 기술을 사용하여 템플릿을 hrefs로 만들 수 있습니까? 예를 들어, HAL의 templated 링크 속성을 사용하여 임의의 제품에 일부 자원에서 링크를 만들려면 :

"_links": { 
    "self": { 
    "href": "http://example.org/api/productfinder" 
    }, 
    "product": { 
    "href": "http://example.org/api/products/{productId}", 
    "templated": true 
    } 
} 

(정말 자원을 호출 productfinder이없는 -이 질문에 대한 단지 인위적인 예를 들어).

템플릿의 문자열에 routeValues 매개 변수를 설정해 보았습니다. 예 :

var href = Url.Link("RouteName", new { id = "{productId}" }); 

이렇게하면 URL 인코딩 된 문자열 인 http://example.org/api/products/%7BproductId%7D가 생성됩니다. .Replace을 사용할 수 있지만이 방법은 다른 이유로 실패합니다. 경로 구성에 타입 제한이있는 경우. {id:int} 그러면 href가 null이됩니다.

routeValues에 null을 전달하려고했는데 템플릿 부분을 추가 할 수 있기를 바랍니다. Link()은 null을 반환하므로 href은 템플릿 부분으로 끝납니다. 더하기이 같은 복잡한 경로에 대해서는 작동하지 않습니다. api/{this}/something/{that}{?q}

이렇게 붙어 있습니다. 경로를 사용하여 템플리트 화 된 외부 구조를 생성 할 수 있습니까? 그렇다면 어떻게?

답변

2

좋아요, 시간이 좀 걸렸지 만 작동하는 것이 있습니다. 구성의 경로 테이블에서 RouteTemplate을 조회하는 것이 트릭입니다. 각 컨트롤러에는 구성에 대한 참조가 있습니다. 거기에서 그것은 꽤 쉬웠다.

확장 클래스를 ApiController으로 만들었습니다. 실제로 나는 ApiController을 서브 클래스화할 것이지만 그 아이디어는 동일합니다. 또한 .ToString() 대신 Uri 개체를 반환 할 수 있습니다. 나는 템플릿 href가 필요로 할 때 컨트롤러의 방법 내부와

public static class ApiControllerExtensions 
{ 
    public static string GetTemplatedHref(this ApiController controller, string routeName, string controllerName = "") 
    { 
     var routeTemplate = controller.Configuration.Routes[routeName].RouteTemplate; 

     var baseUri = new Uri(controller.Request.RequestUri.GetLeftPart(UriPartial.Authority)); 
     var templatedHref = new Uri(baseUri, routeTemplate).ToString(); 

     return string.IsNullOrEmpty(controllerName) ? 
      templatedHref : 
      templatedHref.Replace("{controller}", controllerName.ToLower()); 
    } 
} 

지금, 나는이 작업을 수행 할 수 있습니다

var href = this.GetTemplatedHref("RouteName"); 

이 경로의 속성을 잘 작동합니다.

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

그래서 내가 컨트롤러 이름을 제공 할 수 있으며이 같은 템플릿 href가 얻을 : 그것은 또한 예를 들어, 사전 구성된 경로 작동 내가 수정하고 조정할 수 있습니다 실제로 다시

var href = this.GetTemplatedHref("DefaultApi", "product"); 

을, 예 절대/상대 옵션 등을 추가합니다.그러나 경로 이름을 사용하여 템플릿을 가져 오는 핵심 문제가 해결되었습니다.

관련 문제