web-dev-qa-db-fra.com

La ressource demandée ne supporte pas la méthode http 'OPTIONS'.

Je fais la demande suivante à une méthode asp.net web api PUT auprès de mon client angular.js:

var org = {
                  OrgId: 111,
                  name: 'testing testing'
          };
$http.put("http://localhost:54822/api/data/putorganisation/1/", org).then(function(status) {
         console.log("success PUT");
         return status.data;
});

Cependant, obtenir le errormsg suivant (dans fiddler):

{"message":"The requested resource does not support http method 'OPTIONS'."}

Voici une partie de mon fichier asp.c web apon web.config:

 <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="Content-Type,x-xsrf-token,X-Requested-With" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
      </customHeaders>
    </httpProtocol>
    <validation validateIntegratedModeConfiguration="false" />
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
      <remove name="WebDAV" />
    </handlers>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="WebDAVModule" />
    </modules>
  </system.webServer>

contrôleur de données web api:

public HttpResponseMessage Options()
{
            var response = new HttpResponseMessage();
            response.StatusCode = HttpStatusCode.OK;
            return response;
}

public HttpResponseMessage PutOrganisation(int id, [FromBody]Organisation org)
{
  var opStatus = _Repository.UpdateOrganisation(org);
  if (opStatus.Status)
  {
     return Request.CreateResponse<Organisation>(HttpStatusCode.Accepted, org);
  }

return Request.CreateErrorResponse(HttpStatusCode.NotModified, opStatus.ExceptionMessage);
}

Voici ma question: Pourquoi est-ce que je reçois l'errormsg (voir ci-dessus) alors que je fais exactement la même demande dans fiddler (fonctionne) que dans angularclient (ne fonctionne pas)?

10
user603007

Je sais que c’est une vieille question, mais j’ai rencontré le même problème et je me suis dit que je pourrais aider les autres qui essaient de le comprendre.

Je l'ai résolu en supprimant 2 des configurations de gestionnaire dans le fichier Web.config:

<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <!--<remove name="OPTIONSVerbHandler" />-->
  <remove name="TRACEVerbHandler" />
  <!--<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />-->
</handlers>

Je ne sais pas exactement pourquoi cela a résolu le problème, mais ma théorie de travail est que <remove name="OPTIONSVerbHandler" /> interdit les requêtes OPTIONS par défaut. Lors de l'envoi de la demande par l'intermédiaire d'angular, il envoie d'abord une demande OPTIONS avant la demande PUT. Il ne parvient donc jamais à la demande PUT car la première demande OPTIONS a été refusée en tant que méthode HTTP non valide sur l'API.

En fiddler, je suppose qu’il n’envoie que la requête PUT (j’ai observé le même comportement en utilisant manuellement les requêtes de l’application Web Postman). Donc, il saute la requête OPTIONS interdite et réussit.

30
Nathan Hanna

J'ai également rencontré le même problème. Après quelques recherches, j'ai apporté les modifications suivantes aux fichiers web.config et Global.asax.cs.

<configuration>

  <system.webServer>
    <directoryBrowse enabled="true" />
    <validation validateIntegratedModeConfiguration="false" />
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, PATCH, DELETE, OPTIONS" />
        <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />

      </customHeaders>
    </httpProtocol>
    <handlers>
      <remove name="WebDAV" />
      <remove name="OPTIONSVerbHandler"/>
      <remove name="TRACEVerbHandler" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />

      <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="C:\windows\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="C:\windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="WebDAVModule" />
      <remove name="ApplicationInsightsWebTracking" />
      <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
    </modules>
  </system.webServer>

</configuration>

Ajoutez le code suivant: global.ascx.cs

protected void Application_BeginRequest()
{
    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
        HttpContext.Current.Response.End();
    }
}
6
Gehan Fernando

Andrew a raison, c'est très probablement un problème de la SCRO. Ce dont vous avez besoin est d’ajouter l’attribut EnableCors à votre classe de contrôleurs afin qu’il ressemble à ceci: 

 [EnableCors(origins: "https://example.com,http://example.org", headers: "*", methods: "*")]
    public class  TestController : ApiController
    {
         // your code 

L'autre façon de faire est mentionnée dans ce stack overflow post

1
Shekhar

C'est presque certainement un problème de la SCRO. Je voudrais d’abord lire à ce sujet pour vous assurer de bien comprendre en quoi cela consiste et pourquoi c’est important. Et je suppose que la configuration de votre serveur n’est pas correcte.

Malheureusement, je ne connais pas grand chose à propos de .net, mais ce le tutoriel CORS pour .net décrit bien ce que vous devriez faire.

Il semble qu'il manque une annotation EnableCors. Il semble que vous deviez ajouter quelque chose comme [EnableCors("*", "*", "*")] à votre contrôleur. Le traitement explicite des options n'est pas nécessaire. Bien entendu, en production, vous ne souhaitez pas utiliser de caractères génériques pour la gestion de votre CORS. Ils devraient être plus spécifiques, mais c'est très bien pour les tests.

1
Andrew Eisenberg

Oui, un vieux mais un goodie. J'avais le même problème et le même symptôme, mais ma résolution était auto-infligée. Je vais le partager quand même. La manière dont notre service a configuré le contrôleur utilisé dans tous les appels MapHttpRoute au démarrage incluait l'attribut [DisableCors]. Dès que j'ai reconfiguré le démarrage de ma machine locale pour utiliser un autre contrôleur, tout a fonctionné. Donc, si vous avez fait tout ce qui est indiqué ici, vérifiez votre contrôleur et assurez-vous de ne pas avoir fait quelque chose de stupide, comme je l'ai fait.

0

Apparemment, dans certains cas, une demande OPTIONS est envoyée avant la demande "réelle" pour déterminer si la demande réelle peut être envoyée en toute sécurité grâce à CORS. Voir l'article MS suivant à l'adresse: http://www.asp.net/web-api/overview/security/enabling-cross-Origin-requests-in-web-api et recherchez "Demandes de contrôle en amont".

Certaines des questions suivantes pourraient également aider:

0
djikay