2013-03-28 17 views
8

chcę mieć dwa różne działania GET kwerendy danych przy nazwie i identyfikatorze,WebAPI Kontroler z dwóch GET działania

mam te trasy:

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

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

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

i te działania w kontrolerze:

[HttpGet] 
    public CompanyModel CompanyId(Guid id) 
    { 
      //Do something 
    } 


    [HttpGet] 
    public CompanyModel CompanyName(string name) 
    { 
      //Do something 
    } 

podczas rozmowy tak: http://localhost:51119/api/companies/CompanyId/3cd97fbc-524e-47cd-836c-d709e94c5e1e prac i dostaje się do 'CompanyId' metody,

podobne wezwanie do http://localhost:51119/api/companies/CompanyName/something dostaje mi 404 nie znaleziono

ale tym: „http://localhost:51119/api/companies/CompanyName/?name=something” działa dobrze

Może ktoś wyjaśnić to zachowanie i to, co robię źle?

Odpowiedz

10

Selektor trasy Web API nie ma możliwości sprawdzenia, czy ciąg na końcu adresu URL jest identyfikatorem GUID, czy nie. Dlatego nie chodzi o to, aby wybrać właściwą trasę dla odpowiedniej akcji GET.

Aby wybrać prawidłową trasę, należy dodać ograniczenie trasy dla szablonu GUID uri.

public class GuidConstraint : IHttpRouteConstraint 
    { 
     public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, 
          HttpRouteDirection routeDirection) 
     { 
      if (values.ContainsKey(parameterName)) 
      { 
       string stringValue = values[parameterName] as string; 

       if (!string.IsNullOrEmpty(stringValue)) 
       { 
        Guid guidValue; 

        return Guid.TryParse(stringValue, out guidValue) && (guidValue != Guid.Empty); 
       } 
      } 

      return false; 
     } 
    } 

A następnie dodaj ograniczenie do trasy, która będzie obsługiwać identyfikator GUID.

config.Routes.MapHttpRoute(
      name: "ActionApi", 
      routeTemplate: "api/{controller}/{action}/{id}", 
      defaults: new { id = RouteParameter.Optional }, 
      constraints: new { id = new GuidConstraint() } // Added 
     ); 

Ponieważ ta trasa jest bardziej szczegółowa niż ogólna trasa "ciąg", musi być umieszczona powyżej tej, która ma zamiar rozwiązać nazwę.

To powinno odpowiednio prowadzić do akcji.

Mam nadzieję, że to pomoże.

+0

Przyjmuję twoją odpowiedź, ponieważ działa to świetnie, ale wciąż nie rozumiem, dlaczego nie jest ona odwzorowana na właściwe działanie, w URI, który kieruję, jest raz na "CompanyName" i raz na "CompanyId", nie powinno to być wybierz odpowiednie działanie? –

+2

[To pytanie SO] (http://stackoverflow.com/questions/9569270/custom-method-names-in-asp-net-web-api) może pomóc wyjaśnić, dlaczego. Trasy Web API są domyślnie zgodne z konwencjami REST. Można więc zaobserwować inne zachowanie niż w przypadku zwykłych tras MVC. –

+0

Genialny! Web API jest tak dobrze przemyślany! –

Powiązane problemy