ASP.NET Web Api: el recurso solicitado no es compatible con el método http 'GET'

92

Tengo la siguiente acción en un ApiController:

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

Y he configurado mis rutas de la siguiente manera:

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

En la versión beta, esto funcionó bien, pero acabo de actualizar a la última versión candidata y ahora veo errores en llamadas como esta:

El recurso solicitado no es compatible con el método http 'GET'.

¿Por qué esto ya no funciona?

(Supongo que podría deshacerme de {action} y hacer un montón de controladores, pero eso se siente complicado).

Josh Schultz
fuente

Respuestas:

107

Si no ha configurado ningún HttpMethod en su acción en el controlador, se supone que es solo HttpPost en RC. En Beta, se asume que es compatible con todos los métodos: GET, PUT, POST y Delete. Este es un pequeño cambio de beta a RC. Puede decorar fácilmente más de un método http en su acción con [AcceptVerbs ("GET", "POST")].

dinesh ravva
fuente
acabo de encontrar esto, gracias por la solución, pero curioso, ¿por qué tengo que hacer esto con mis métodos personalizados, pero no con el método predeterminado "Get"? Tengo un método Get que fue creado por la plantilla para el controlador, pero no está decorado. ¿Es esto solo por convención debido al nombre Get?
SelAromDotNet
3
@Josh: ¡Sí! Cuando el nombre del método de acción comienza con "Obtener ...", no es necesario marcarlo como un método GET. Lea más aquí: asp.net/web-api/overview/web-api-routing-and-actions/…
Jenny O'Reilly
Hice lo sugerido en la respuesta, pero ahora mis dos llamadas, Obtener y Publicar, se redirigen a Obtener acción. ¿Alguna ayuda por favor?
Syed Ali Taqi
54

Toda la información anterior es correcta, también me gustaría señalar que la [AcceptVerbs()]anotación existe en los espacios de nombres System.Web.Mvc y System.Web.Http.

Desea utilizar System.Web.Http si es un controlador de API web.

Eric
fuente
@Eric. Impresionante, esta fue la razón por la que no funcionó para mí. Tenía el verbo en mi acción, pero se hacía referencia a él a través de Web.Mvc, por lo que no funcionaba.
dreza
Genial, me salvaste el día
Hossein Narimani Rad
Muchas gracias, porque System.Web.Mvc no fue bueno para mí.
Burak Karakuş
34

Aunque esta no es una respuesta al OP, tuve exactamente el mismo error por una causa raíz completamente diferente; así que en caso de que esto ayude a alguien más ...

El problema para mí fue un parámetro de método con un nombre incorrecto que hizo que WebAPI enrutara la solicitud inesperadamente. Tengo los siguientes métodos en mi ProgrammesController:

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

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

Las solicitudes DELETE a ... / api / programmes / 3 no se enrutaban a DeleteProgramme como esperaba, sino a GetProgrammeById, porque DeleteProgramme no tenía un nombre de parámetro de id. GetProgrammeById, por supuesto, rechazó el DELETE ya que está marcado como que solo acepta GET.

Entonces la solución fue simple:

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

Y todo va bien. Error tonto realmente pero difícil de depurar.

Carl Sharman
fuente
1
Si alguien está usando el enrutamiento de URL, intente hacer como [Route ("{programmeId = programmeId: int}")]
sree
1
Esto fue todo para mí. WebApiConfig -> MapHttpRoutes tenía -> routeTemplate: "api / {controller} / {id}", por lo que se tuvo que usar un parámetro de 'id'.
HockeyJ
1
su respuesta me señaló mi problema, que era un poco diferente. Cambié el nombre de un parámetro [FromUri] para el método y no lo actualicé en el lado del cliente
Matus
22

Si está decorando su método con HttpGet, agregue lo siguiente usingen la parte superior del controlador:

using System.Web.Http;

Si está utilizando System.Web.Mvc, entonces puede ocurrir este problema.

Sohail xIN3N
fuente
5
Esto es cierto y, ridículamente, .NET no muestra el mensaje con claridad.
Teoman shipahi
15

Este es sin duda un cambio de Beta a RC. En el ejemplo proporcionado en la pregunta, ahora necesita decorar su acción con [HttpGet] o [AcceptVerbs ("GET")].

Esto causa un problema si desea mezclar acciones basadas en verbos (es decir, "GetSomething", "PostSomething") con acciones no basadas en verbos. Si intenta utilizar los atributos anteriores, provocará un conflicto con cualquier acción basada en verbos en su controlador. Una forma de obtener un resultado sería definir rutas separadas para cada verbo y establecer la acción predeterminada en el nombre del verbo. Este enfoque se puede utilizar para definir recursos secundarios en su API. Por ejemplo, el siguiente código admite: "/ resource / id / children" donde id y children son opcionales.

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

Es de esperar que las versiones futuras de la API web tengan un mejor soporte para este escenario. Actualmente, hay un problema registrado en el proyecto de codeplex aspnetwebstack, http://aspnetwebstack.codeplex.com/workitem/184 . Si esto es algo que le gustaría ver, vote sobre el tema.

Jeremy
fuente
8

Tiene la misma configuración que OP. Un controlador con muchas acciones ... menos "desordenado" :-)

En mi caso, olvidé "[HttpGet]" al agregar una nueva acción.

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

Mismo problema que el anterior, pero raíz muy diferente. Para mí, fue que estaba llegando a un punto final con una regla de reescritura https. Golpearlo en http causó el error, funcionó como se esperaba con https.

Vern D.
fuente
3

Reemplace el siguiente código en esta ruta

Camino :

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
fuente
1

No sé si esto puede estar relacionado con la publicación del OP, pero me faltaba la anotación [HttpGet] y eso era lo que estaba causando el error, como lo indica @dinesh_ravva, se supone que los métodos son HttpPost por defecto.

Pierrick Martellière
fuente
0

Mi problema fue tan simple como tener una referencia nula que no apareció en el mensaje devuelto, tuve que depurar mi API para verlo.

Niños
fuente