Méthode 405 non autorisée API Web

88

Cette erreur est très courante et j'ai essayé toutes les solutions et aucune n'a fonctionné. J'ai désactivé la publication WebDAV dans le panneau de configuration et ajouté ceci à mon fichier de configuration Web:

  <handlers>
  <remove name="WebDAV"/>
  </handlers>
  <modules runAllManagedModulesForAllRequests="true">
  <remove name="WebDAVModule"/>
  </modules>

L'erreur persiste toujours. Voici le contrôleur:

   static readonly IProductRepository repository = new ProductRepository();

    public Product Put(Product p)
    {
        return repository.Add(p);
    }

Mise en œuvre de la méthode:

 public Product Add(Product item)
    {
        if (item == null)
        {
            throw new ArgumentNullException("item");
        }
        item.Id = _nextId++;
        products.Add(item);
        return item;
    }

Et c'est là que l'exception est levée:

client.BaseAddress = new Uri("http://localhost:5106/");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));      
var response = await client.PostAsJsonAsync("api/products", product);//405 exception

Aucune suggestion?

Xardas
la source

Réponses:

61

Vous postez depuis le client:

await client.PostAsJsonAsync("api/products", product);

pas PUTing.

Votre méthode API Web n'accepte que les requêtes PUT.

Donc:

await client.PutAsJsonAsync("api/products", product);
Darin Dimitrov
la source
L'erreur 'HttpClient' ne contient pas de définition pour 'PostAsJsonAsync' est levée, lors de l'essai de votre code.
agileDev
61

J'ai eu la même exception. Mon problème était que j'avais utilisé:

using System.Web.Mvc; // Wrong namespace for HttpGet attribute !!!!!!!!!
[HttpGet]
public string Blah()
{
    return "blah";
}

DEVRAIT ÊTRE

using System.Web.Http; // Correct namespace for HttpGet attribute !!!!!!!!!
[HttpGet]
public string Blah()
{
    return "blah";
}
Llad
la source
18

J'ai essayé beaucoup de choses pour faire fonctionner la méthode DELETE (j'obtenais la méthode 405 non autorisée pour l'api Web), et finalement j'ai ajouté [Route ("api / scan / {id}")] à mon contrôleur et cela fonctionnait bien. J'espère que ce message aidera quelqu'un.

     // DELETE api/Scan/5
    [Route("api/scan/{id}")]
    [ResponseType(typeof(Scan))]
    public IHttpActionResult DeleteScan(int id)
    {
        Scan scan = db.Scans.Find(id);
        if (scan == null)
        {
            return NotFound();
        }

        db.Scans.Remove(scan);
        db.SaveChanges();

        return Ok(scan);
    }
user2662006
la source
Pour une raison quelconque, cela ne fonctionnait pas uniquement pour la suppression, pour la création et la mise à jour, cela fonctionnait bien. Eh bien, je viens d'ajouter [HttpPost] et cela a fonctionné. Mais merci, tu m'as mis sur la bonne voie et ne m'a coûté que 5 minutes maintenant :)
Rubenisme
1
Pourquoi n'ajoutez-vous pas simplement l'attribut [HttpDelete]?
johnny 5
14

Mon problème s'est avéré être le routage d'attributs dans WebAPI. J'ai créé un itinéraire personnalisé et il l'a traité comme un GET au lieu de WebAPI en découvrant qu'il s'agissait d'un POST

    [Route("")]
    [HttpPost] //I added this attribute explicitly, and it worked
    public void Post(ProductModel data)
    {
        ...
    }

Je savais que ça devait être quelque chose de stupide (qui consomme toute ta journée)

Nexxas
la source
Cela m'a sauvé la journée!
Phate01
6

Chrome essaie souvent de passer un OPTIONSappel avant de publier un message. Il le fait pour s'assurer que les en-têtes CORS sont dans l'ordre. Cela peut être problématique si vous ne gérez pas l' OPTIONSappel dans votre contrôleur API.

public void Options() { }
Nate Zaugg
la source
6

Cette erreur peut également se produire lorsque vous essayez de vous connecter à http alors que le serveur est sur https.

C'était un peu déroutant car mes requêtes get étaient correctes, le problème n'était présent qu'avec les post-requêtes.

FrankyHollywood
la source
4

Je recevais le 405 lors de mon appel GET, et le problème s'est avéré que j'avais nommé le paramètre dans la méthode côté serveur GET Get(int formId)et que j'avais besoin de modifier l'itinéraire ou de le renommer Get(int id).

Sako73
la source
4

Vous pouvez également obtenir l'erreur 405 si vous dites que votre méthode attend un paramètre et que vous ne le transmettez pas.

Cela ne fonctionne PAS (erreur 405)

Affichage HTML / Javascript

$.ajax({
         url: '/api/News',
         //.....

API Web:

public HttpResponseMessage GetNews(int id)

Ainsi, si la signature de la méthode est comme ci-dessus, vous devez faire:

Affichage HTML / Javascript

$.ajax({
         url: '/api/News/5',
         //.....
Tom Stickel
la source
Il semble que je rencontre des erreurs 405 pour diverses raisons, elles se résument toutes au fait qu'il tente de HITER la signature de la méthode et un problème de paramètre ou un problème de dénomination de convention ou un problème d'attribut, etc.
Tom Stickel
4

Je suis en retard à cette fête mais comme rien ci-dessus n'était viable ou fonctionnait dans la plupart des cas, voici comment cela a finalement été résolu pour moi.

Sur le serveur sur lequel le site / service était hébergé, une fonctionnalité était requise! ACTIVATION HTTP !!!

Gestionnaire de serveur> Gérer> Ajouter des rôles et des fonctionnalités> suivant suivant suivant jusqu'à ce que vous arriviez à Fonctionnalités> Sous .NET (chaque version) cochez Activation HTTP. Notez également qu'il y en a un caché sous> net> Services WCF.

Cela a ensuite fonctionné instantanément! Qui faisait fondre mon cerveau

Monolithcode
la source
4

Si vous avez un itinéraire comme

[Route("nuclearreactors/{reactorId}")]

Vous devez utiliser exactement le même nom de paramètre dans la méthode, par exemple

public ReactorModel GetReactor(reactorId)
{
 ...
}

Si vous ne passez pas exactement le même paramètre, vous risquez d'obtenir l'erreur «méthode 405 non autorisée» car la route ne correspondra pas à la demande et WebApi frappera une méthode de contrôleur différente avec une méthode HTTP autorisée différente.

Roylac
la source
Ce n'est pas non plus une réponse!
Divyang Desai
@Div "Méthode 405 non autorisée" peut être affiché dans le cas que j'ai partagé car la méthode n'attrapera pas l'appel api car la configuration de l'itinéraire n'est pas valide. L'appel api peut alors frapper une autre méthode involontaire qui pourrait avoir une action HTTP différente autorisée. Oui, je conviens que cette réponse n'est peut-être pas pertinente à 100% pour la question réelle, mais le titre de la question de Xardas n'est pas très spécifique et je pense que de nombreuses personnes qui débarquent ici à la recherche de réponses à la question comme indiqué par le titre peuvent trouve cette réponse utile.
roylac
3

Cela ne répond pas à votre question précise, mais lorsque j'ai eu le même problème, je me suis retrouvé ici et j'ai pensé que plus de gens pourraient faire de même.

Le problème que j'ai eu était que j'avais déclaré indélibérément ma méthode Get comme statique . J'ai manqué cela une matinée entière, et cela n'a causé aucun avertissement d'attributs ou similaires.

Incorrect:

public class EchoController : ApiController
{
    public static string Get()
    {
        return string.Empty;
    }
}

Correct:

public class EchoController : ApiController
{
    public string Get()
    {
        return string.Empty;
    }
}
Par Stolpe
la source
2

[HttpPost] est inutile!

[Route("")]
public void Post(ProductModel data)
{
    ...
}
user3963793
la source
1
Oui, la façon dont vous le faites est correcte en ce sens que vous n'avez pas besoin d'un [HttpPost] explicite, cependant il y a des gens qui ne suivent pas la convention (yikes) et donc quelque chose comme [Route ("MyMethodSaver"] public string MyMethodtoSave (int? id) -> qui aurait besoin d'un [HttpPost] et cela fonctionnerait alors
Tom Stickel
2

Je ne pourrais PAS résoudre ça. J'avais CORS activé et fonctionnait aussi longtemps que le POST retournait vide (ASP.NET 4.0 - WEBAPI 1). Lorsque j'ai essayé de renvoyer un HttpResponseMessage, j'ai commencé à obtenir la réponse HTTP 405.

Sur la base de la réponse de Llad ci-dessus, j'ai jeté un coup d'œil à mes propres références.

J'avais l'attribut [System.Web.Mvc.HttpPost] listé au-dessus de ma méthode POST.

J'ai changé cela pour utiliser:

[System.Web.Http.HttpPostAttribute]
[HttpOptions]
public HttpResponseMessage Post(object json)        
{
    ...
    return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
}

Cela a réglé mes problèmes. J'espère que ça aidera quelqu'un d'autre.

Par souci d'exhaustivité, j'avais ce qui suit dans mon web.config:

<httpProtocol>
    <customHeaders>
        <clear />
        <add name="Access-Control-Expose-Headers " value="WWW-Authenticate"/>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS, PUT, PATCH, DELETE" />
        <add name="Access-Control-Allow-Headers" value="accept, authorization, Content-Type" />
        <remove name="X-Powered-By" />
    </customHeaders>
</httpProtocol>
Spencer Sullivan
la source
Cela aura la méthode appelée sur la demande de pré-vol OPTIONS (ainsi que sur POST), à quel point jsonest probable nullpuisque les demandes de pré-vol n'ont généralement pas de charge utile, ou vous exécuterez l'action de publication deux fois.
glennsl
1

Nous avons eu un problème similaire. Nous essayions d'obtenir de:

[RoutePrefix("api/car")]
public class CarController: ApiController{

    [HTTPGet]
    [Route("")]
    public virtual async Task<ActionResult> GetAll(){

    }

}

Donc nous le ferions .GET("/api/car")et cela jetterait un 405 error.


Le correctif:

Le CarController.csfichier était dans le répertoire/api/car donc lorsque nous demandions ce point de terminaison d'API, IIS renvoyait une erreur car il semblait que nous essayions d'accéder à un répertoire virtuel auquel nous n'étions pas autorisés.

Option 1: changer / renommer le répertoire dans lequel se trouve le contrôleur
Option 2: changer le préfixe de la route en quelque chose qui ne correspond pas au répertoire virtuel.

Zze
la source
1

Dans mon cas, j'avais un dossier physique dans le projet avec le même nom que la route WebAPI (ex. Sandbox) et seule la demande POST était interceptée par le gestionnaire de fichiers statiques dans IIS (évidemment).

Obtenir une erreur 405 trompeuse au lieu du 404 plus attendu était la raison pour laquelle il m'a fallu beaucoup de temps pour dépanner.

Pas facile de tomber dedans, mais possible. J'espère que ça aide quelqu'un.

Panos Roditakis
la source
1

Pour ma part mon gestionnaire POST était de cette forme:

[HttpPost("{routeParam}")]
public async Task<ActionResult> PostActuality ([FromRoute] int routeParam, [FromBody] PostData data)

J'ai compris que je devais permuter les arguments , c'est-à-dire les données du corps d'abord puis le paramètre de route, comme ceci:

[HttpPost("{routeParam}")]
public async Task<ActionResult> PostActuality ([FromBody] PostData data, [FromRoute] int routeParam)
Alexandre Daubricourt
la source
0

archiver le fichier .csproj de votre projet et modifier

<IISUrl>http://localhost:PORT/</IISUrl>

à l'URL de votre site Web comme celle-ci

<IISUrl>http://example.com:applicationName/</IISUrl>
Ankit
la source
0

Un autre problème possible qui cause le même comportement est les paramètres par défaut dans le routage. Dans mon cas, le contrôleur a été localisé et instancié correctement, mais le POST a été bloqué en raison de l' Getaction par défaut spécifiée:

config.Routes.MapHttpRoute(
    name: "GetAllRoute",
    routeTemplate: "api/{controller}.{ext}"/*,
    defaults: new { action = "Get" }*/ // this was causing the issue
);
Eadel
la source
0

J'avais exactement le même problème. J'ai cherché pendant deux heures ce qui n'allait pas sans succès jusqu'à ce que je réalise que ma POSTméthode était à la privateplace public.

C'est drôle maintenant de voir que ce message d'erreur est un peu générique. J'espère que cela aide!

Gonzo345
la source
0

Assurez-vous que votre contrôleur hérite de la Controllerclasse.

Il pourrait même être plus fou que des choses fonctionnent localement, même sans cela.

RAM
la source