ASP.NET Web Api: O recurso solicitado não oferece suporte ao método http 'GET'

92

Tenho a seguinte ação em um ApiController:

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

E eu configurei minhas rotas da seguinte maneira:

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

No beta, isso funcionou bem, mas acabei de atualizar para o Release Candidate mais recente e agora estou vendo erros em chamadas como esta:

O recurso solicitado não oferece suporte ao método http 'GET'.

Por que isso não funciona mais?

(Suponho que poderia me livrar de {action} e apenas fazer uma tonelada de controladores, mas isso parece uma bagunça.)

Josh Schultz
fonte

Respostas:

107

Se você não configurou nenhum HttpMethod em sua ação no controlador, presume-se que seja apenas HttpPost no RC. Em Beta, presume-se que ele suporte todos os métodos - GET, PUT, POST e Delete. Esta é uma pequena mudança de beta para RC. Você pode facilmente decore mais de um método http em sua ação com [AcceptVerbs ("GET", "POST")].

Dinesh Ravva
fonte
acabei de encontrar isso, obrigado pela correção, mas curioso, por que tenho que fazer isso com meus métodos personalizados, mas não com o método padrão "Get"? Eu tenho um método Get que foi criado pelo modelo para o controlador, mas não é decorado. isso é apenas por convenção por causa do nome Get?
SelAromDotNet
3
@Josh: Sim! Quando o nome do método de ação começa com "Get ...", você não precisa marcá-lo como um método GET. Leia mais aqui: asp.net/web-api/overview/web-api-routing-and-actions/…
Jenny O'Reilly
Fiz conforme sugerido na resposta, mas agora ambas as chamadas, Get e Post, estão sendo redirecionadas para Get Action. Alguma ajuda por favor?
Syed Ali Taqi
54

Todas as informações acima estão corretas. Também gostaria de salientar que a [AcceptVerbs()]anotação existe nos namespaces System.Web.Mvc e System.Web.Http.

Você deseja usar o System.Web.Http se for um controlador de API da Web.

Eric
fonte
@Eric. Incrível, esse era o motivo pelo qual não estava funcionando para mim. Eu tinha o verbo na minha ação, mas foi referenciado via Web.Mvc, então não estava funcionando.
dreza
Ótimo, você salvou meu dia
Hossein Narimani Rad
Muito obrigado, porque System.Web.Mvc não era bom para mim.
Burak Karakuş
34

Embora essa não seja uma resposta ao OP, tive exatamente o mesmo erro de uma causa raiz completamente diferente; então, caso isso ajude mais alguém ...

O problema para mim era um parâmetro de método nomeado incorretamente que fazia com que o WebAPI roteasse a solicitação inesperadamente. Eu tenho os seguintes métodos em meu ProgrammesController:

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

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

As solicitações DELETE para ... / api / programs / 3 não estavam sendo roteadas para DeleteProgramme como eu esperava, mas para GetProgrammeById, porque DeleteProgramme não tinha um nome de parâmetro de id. GetProgrammeById então, obviamente, rejeitou o DELETE, pois ele está marcado como apenas aceitando GETs.

Portanto, a solução foi simples:

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

E está tudo bem. Erro tolo, realmente, mas difícil de depurar.

Carl Sharman
fonte
1
Se alguém estiver usando o roteamento de url, tente fazer como [Route ("{programmeId = programmeId: int}")]
sree
1
Isso foi tudo para mim. WebApiConfig -> MapHttpRoutes had -> routeTemplate: "api / {controller} / {id}", então um parâmetro de 'id' teve que ser usado.
HockeyJ
1
sua resposta me apontou para o meu problema que era um pouco diferente. Eu mudei o nome de um parâmetro [FromUri] para o método e não o atualizei no lado do cliente
Matus
21

Se você estiver decorando seu método com HttpGet, adicione o seguinte usingna parte superior do controlador:

using System.Web.Http;

Se você estiver usando System.Web.Mvc, esse problema pode ocorrer.

Sohail xIN3N
fonte
5
Isso é verdade, e ridiculamente o .NET não está mostrando a mensagem com clareza.
Teoman shipahi
15

Esta é certamente uma mudança de Beta para RC. No exemplo fornecido na pergunta, agora você precisa decorar sua ação com [HttpGet] ou [AcceptVerbs ("GET")].

Isso causa um problema se você quiser misturar ações baseadas em verbos (ou seja, "GetSomething", "PostSomething") com ações não baseadas em verbos. Se você tentar usar os atributos acima, isso causará um conflito com qualquer ação baseada em verbo em seu controlador. Uma maneira de obter uma resposta seria definir rotas separadas para cada verbo e definir a ação padrão para o nome do verbo. Essa abordagem pode ser usada para definir recursos filhos em sua API. Por exemplo, o código a seguir suporta: "/ resource / id / children" em que id e children são opcionais.

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

Esperançosamente, versões futuras da API Web terão melhor suporte para este cenário. Atualmente, há um problema registrado no projeto codeplex aspnetwebstack, http://aspnetwebstack.codeplex.com/workitem/184 . Se isso é algo que você gostaria de ver, vote no assunto.

Jeremy
fonte
8

Tenha a mesma configuração do OP. Um controlador com muitas ações ... menos "bagunçado" :-)

No meu caso, esqueci o "[HttpGet]" ao adicionar uma nova ação.

[HttpGet]
public IEnumerable<string> TestApiCall()
{
    return new string[] { "aa", "bb" };
}
Shaakir
fonte
6

O mesmo problema acima, mas uma raiz muito diferente. Para mim, era que eu estava atingindo um endpoint com uma regra de reescrita https. Acertar em http causou o erro, funcionou como esperado com https.

Vern D.
fonte
3

Substitua o seguinte código neste caminho

Caminho:

App_Start => WebApiConfig.cs

Código:

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

Não sei se isso pode estar relacionado à postagem do OP, mas estava faltando a anotação [HttpGet] e era isso que estava causando o erro, conforme declarado por @dinesh_ravva, os métodos são considerados HttpPost por padrão.

Pierrick Martellière
fonte
0

Meu problema era tão simples quanto ter uma referência nula que não apareceu na mensagem retornada, eu tive que depurar minha API para vê-lo.

Ninos
fonte