ASP.NET Web Api: Żądany zasób nie obsługuje metody http „GET”

93

Mam następującą akcję na ApiController:

public string Something()
{
    return "value";
}

Skonfigurowałem moje trasy w następujący sposób:

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

W wersji beta działało to dobrze, ale właśnie zaktualizowałem do najnowszej wersji Release Candidate i teraz widzę błędy w wywołaniach takich jak ten:

Żądany zasób nie obsługuje metody http „GET”.

Dlaczego to już nie działa?

(Przypuszczam, że mógłbym pozbyć się {action} i po prostu stworzyć mnóstwo kontrolerów, ale wydaje mi się, że to bałagan.)

Josh Schultz
źródło

Odpowiedzi:

108

Jeśli nie skonfigurowałeś żadnego HttpMethod na swojej akcji w kontrolerze, zakłada się, że jest to tylko HttpPost w RC. W wersji Beta zakłada się, że obsługuje wszystkie metody - GET, PUT, POST i Delete. To niewielka zmiana z wersji beta na RC. Możesz łatwo odszyfrować więcej niż jedną metodę http w swojej akcji za pomocą [AcceptVerbs ("GET", "POST")].

dinesh ravva
źródło
właśnie to napotkałem, dzięki za poprawkę, ale ciekawi, dlaczego muszę to robić za pomocą moich niestandardowych metod, ale nie domyślnej metody „Get”? Mam metodę Get, która została utworzona przez szablon dla kontrolera, ale nie jest ozdobiona. czy to tylko przez konwencję z powodu nazwy Get?
SelAromDotNet
3
@Josh: Tak! Kiedy nazwa metody akcji zaczyna się od „Get ...”, nie musisz oznaczać jej jako metody GET. Przeczytaj więcej tutaj: asp.net/web-api/overview/web-api-routing-and-actions/…
Jenny O'Reilly
Zrobiłem tak, jak zasugerowałem w odpowiedzi, ale teraz oba moje połączenia, Get i Post, są przekierowywane do Get Action. Proszę o pomoc?
Syed Ali Taqi
55

Wszystkie powyższe informacje są poprawne, chciałbym również zwrócić uwagę, że [AcceptVerbs()]adnotacja istnieje zarówno w przestrzeni nazw System.Web.Mvc, jak i System.Web.Http.

Chcesz użyć System.Web.Http, jeśli jest to kontroler interfejsu API sieci Web.

Eric
źródło
@Eric. Świetnie, to był powód, dla którego to nie działało. Miałem czasownik na mojej akcji, ale odwoływał się do niego przez Web.Mvc, więc nie działał.
dreza
Świetnie, uratowałeś mi dzień
Hossein Narimani Rad
Dziękuję bardzo, ponieważ System.Web.Mvc nie był dla mnie dobry.
Burak Karakuş
34

Chociaż nie jest to odpowiedź na PO, miałem dokładnie ten sam błąd z zupełnie innej przyczyny; więc jeśli to pomoże komuś innemu ...

Moim problemem był nieprawidłowo nazwany parametr metody, który spowodował, że WebAPI nieoczekiwanie skierowało żądanie. Mam następujące metody w moim ProgrammesController:

[HttpGet]
public Programme GetProgrammeById(int id)
{
    ...
}

[HttpDelete]
public bool DeleteProgramme(int programmeId)
{
    ...
}

Żądania DELETE do ... / api / programy / 3 nie były kierowane do DeleteProgramme, jak się spodziewałem, ale do GetProgrammeById, ponieważ DeleteProgramme nie miało nazwy parametru id. GetProgrammeById oczywiście odrzucał wtedy DELETE, ponieważ jest oznaczony jako akceptujący tylko GET.

Więc poprawka była prosta:

[HttpDelete]
public bool DeleteProgramme(int id)
{
    ...
}

I wszystko w porządku. Naprawdę głupi błąd, ale trudny do debugowania.

Carl Sharman
źródło
1
Jeśli ktoś używa routingu
adresów
1
To było to dla mnie. WebApiConfig -> MapHttpRoutes miał -> routeTemplate: „api / {kontroler} / {id}”, więc należało użyć parametru „id”.
HockeyJ
1
twoja odpowiedź wskazała mi mój problem, który był trochę inny Zmieniłem nazwę jednego parametru [FromUri] dla metody i nie zaktualizowałem go po stronie klienta
Matus
22

Jeśli dekorujesz swoją metodę za pomocą HttpGet, dodaj następujące elementy usingu góry kontrolera:

using System.Web.Http;

Jeśli używasz System.Web.Mvc, może wystąpić ten problem.

Sohail xIN3N
źródło
5
To prawda i śmiesznie. NET nie pokazuje jasno wiadomości.
Teoman shipahi
15

To z pewnością zmiana z wersji beta na RC. W przykładzie podanym w pytaniu musisz teraz udekorować swoją akcję za pomocą [HttpGet] lub [AcceptVerbs ("GET")].

Powoduje to problem, jeśli chcesz mieszać akcje oparte na czasownikach (np. „GetSomething”, „PostSomething”) z akcjami nieopartymi na czasownikach. Jeśli spróbujesz użyć powyższych atrybutów, spowoduje to konflikt z jakąkolwiek akcją opartą na czasowniku w kontrolerze. Jednym ze sposobów uzyskania arount, które polegałoby na zdefiniowaniu oddzielnych tras dla każdego czasownika i ustawieniu domyślnej akcji na nazwę czasownika. To podejście może służyć do definiowania zasobów podrzędnych w interfejsie API. Na przykład następujący kod obsługuje: „/ zasób / id / dzieci”, gdzie id i dzieci są opcjonalne.

        context.Routes.MapHttpRoute(
           name: "Api_Get",
           routeTemplate: "{controller}/{id}/{action}",
           defaults: new { id = RouteParameter.Optional, action = "Get" },
           constraints: new { httpMethod = new HttpMethodConstraint("GET") }
        );

        context.Routes.MapHttpRoute(
           name: "Api_Post",
           routeTemplate: "{controller}/{id}/{action}",
           defaults: new { id = RouteParameter.Optional, action = "Post" },
           constraints: new { httpMethod = new HttpMethodConstraint("POST") }
        );

Miejmy nadzieję, że przyszłe wersje interfejsu API sieci Web będą lepiej obsługiwać ten scenariusz. Obecnie w projekcie aspnetwebstack codeplex zarejestrowano problem, http://aspnetwebstack.codeplex.com/workitem/184 . Jeśli jest to coś, co chciałbyś zobaczyć, zagłosuj w tej sprawie.

Jeremy
źródło
8

Mają taką samą konfigurację jak OP. Jeden kontroler z wieloma akcjami ... mniej „bałaganu” :-)

W moim przypadku zapomniałem o "[HttpGet]" podczas dodawania nowej akcji.

[HttpGet]
public IEnumerable<string> TestApiCall()
{
    return new string[] { "aa", "bb" };
}
Shaakir
źródło
6

Ten sam problem, co powyżej, ale znacznie inny root. Dla mnie chodziło o to, że trafiałem na punkt końcowy z regułą przepisywania https. Naciśnięcie go na http spowodowało błąd, działało zgodnie z oczekiwaniami z https.

Vern D.
źródło
3

Zastąp następujący kod w tej ścieżce

Ścieżka:

App_Start => WebApiConfig.cs

Kod:

config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}/{Param}",
            defaults: new { id = RouteParameter.Optional,
                            Param = RouteParameter.Optional }
                          );
Kazem Maleki
źródło
1

Nie wiem, czy może to być związane z postem OP, ale brakowało mi adnotacji [HttpGet] i to właśnie było przyczyną błędu, jak stwierdzono w metodach @dinesh_ravva, domyślnie przyjmuje się, że jest to HttpPost.

Pierrick Martellière
źródło
0

Mój problem był tak prosty, jak posiadanie zerowego odwołania, które nie pojawiło się w zwróconym komunikacie, musiałem debugować mój interfejs API, aby go zobaczyć.

Ninos
źródło