web-dev-qa-db-fra.com

API Web MVC: aucun en-tête 'Access-Control-Allow-Origin' n'est présent sur la ressource demandée

J'ai essayé tout ce qui est écrit dans cet article: http://www.asp.net/web-api/overview/security/enabling-cross-Origin-requests-in-web-api , mais rien ne fonctionne. J'essaie d'obtenir des données de webAPI2 (MVC5) à utiliser dans un autre domaine en utilisant angularJS.

mon contrôleur ressemble à ceci:

namespace tapuzWebAPI.Controllers
{
    [EnableCors(origins: "http://local.tapuz.co.il", headers: "*", methods: "*", SupportsCredentials = true)]
    [RoutePrefix("api/homepage")]
    public class HomePageController : ApiController
    {
        [HttpGet]
        [Route("GetMainItems")]
        //[ResponseType(typeof(Product))]
        public List<usp_MobileSelectTopSecondaryItemsByCategoryResult> GetMainItems()
        {


            HomePageDALcs dal = new HomePageDALcs();
            //Three product added to display the data

            //HomePagePromotedItems.Value.Add(new HomePagePromotedItem.Value.FirstOrDefault((p) => p.ID == id));


            List<usp_MobileSelectTopSecondaryItemsByCategoryResult> items = dal.MobileSelectTopSecondaryItemsByCategory(3, 5);
            return items;

        }      
    }
}
99
Noa Gani

Vous devez activerCORSdans votre Web Api . Le moyen le plus simple et le plus pratique d’activer CORS globalement consiste à ajouter les éléments suivants dans web.config

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Access-Control-Allow-Origin" value="*" />
      <add name="Access-Control-Allow-Headers" value="Content-Type" />
      <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

Veuillez noter que les Méthodes sont tous spécifiés individuellement au lieu d'utiliser *. Cela est dû au fait qu’un bogue est survenu lors de l’utilisation de *.

Vous pouvez également activer CORS par code.

Mettre à jour
Le package NuGet suivant est requis: Microsoft.AspNet.WebApi.Cors.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.EnableCors();

        // ...
    }
}

Ensuite, vous pouvez utiliser l'attribut [EnableCors] sur des actions ou des contrôleurs comme celui-ci.

[EnableCors(origins: "http://www.example.com", headers: "*", methods: "*")]

Ou vous pouvez l'enregistrer globalement

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var cors = new EnableCorsAttribute("http://www.example.com", "*", "*");
        config.EnableCors(cors);

        // ...
    }
}

Vous devez également gérer le contrôle en amont Optionsrequest avec les demandes HTTP OPTIONS.

Web API doit répondre à la demande Options pour confirmer qu'il est bien configuré pour prendre en charge CORS.

Pour gérer cela, tout ce que vous avez à faire est d’envoyer une réponse empty. Vous pouvez faire cela dans vos actions, ou vous pouvez le faire globalement comme ceci:

# Global.asax.cs
protected void Application_BeginRequest()
{
    if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
    {
        Response.Flush();
    }
}

Cette vérification supplémentaire a été ajoutée pour garantir que les anciennes variables APIs conçues pour n'accepter que les demandes GET et POST ne seront pas exploitées. Imaginez que vous envoyez une demande DELETE à une API conçue lorsque ce verb n'existait pas. Le résultat est imprévisible et les résultats pourraient être dangereux.

256

La réponse de @ Mihai-Andrei Dinculescu est correcte, mais pour le bénéfice des chercheurs, il existe également un point subtil qui peut causer cette erreur. 

Ajouter un '/' à la fin de votre URL empêchera EnableCors de fonctionner dans toutes les instances (par exemple, à partir de la page d'accueil).

C'est à dire. Cela ne fonctionnera pas

var cors = new EnableCorsAttribute("http://testing.azurewebsites.net/", "*", "*");
config.EnableCors(cors);

mais cela fonctionnera:

var cors = new EnableCorsAttribute("http://testing.azurewebsites.net", "*", "*");
config.EnableCors(cors);

L'effet est identique si vous utilisez l'attribut EnableCors.

22
HockeyJ

J'ai suivi toutes les étapes indiquées ci-dessus par Mihai-Andrei Dinculescu .
Mais dans mon cas, j'avais besoin de 1 de plus étape car http OPTIONS était désactivé dans Web.Config par la ligne ci-dessous.

<remove name="OPTIONSVerbHandler" />

Je viens de le retirer de Web.Config (commentez-le comme ci-dessous) et Cors fonctionne comme un charme

<handlers>
  <!-- remove name="OPTIONSVerbHandler" / -->
</handlers>
17
AlbertSY

Cela peut être dû à l'installation de paquets Cors Nuget.

Si vous rencontrez le problème après avoir installé et développé des cors de nuget, essayez de réinstaller Web Api.

Depuis le gestionnaire de paquets, exécutez Update-Package Microsoft.AspNet.WebApi -reinstall

9
Bimal Das

Essayez ceci pour vous assurer que vous avez correctement configuré CORS:

[EnableCors(origins: "*", headers: "*", methods: "*")]

Ne fonctionne toujours pas? Vérifiez la présence des en-têtes HTTP.

5
Andrei

Pour que tout protocole CORS fonctionne, vous devez avoir une méthode OPTIONS sur chaque noeud final (ou un filtre global avec cette méthode) qui renverra ces en-têtes: 

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: content-type

La raison en est que le navigateur va d'abord envoyer une demande OPTIONS pour "tester" votre serveur et voir les autorisations.

4
sam

@ La réponse de Mihai-Andrei Dinculescu a fonctionné pour moi, par exemple:

  • Ajout d'un <httpProtocol> dans la section <system.webServer> de web.config
  • Renvoi d'une réponse vide pour les demandes OPTIONS via la Application_BeginRequest() mentionnée dans global.asax

Sauf que son chèque pour Request.Headers.AllKeys.Contains("Origin") ne fonctionnait PAS pour moi, car la demande contenait une origing, donc en minuscule. Je pense que mon navigateur (Chrome) l’envoie comme ceci pour les demandes CORS. 

J'ai résolu ce problème un peu plus génériquement en utilisant une casse variante de son contrôle Contains à la place: if (culture.CompareInfo.IndexOf(string.Join(",", Request.Headers.AllKeys), "Origin", CompareOptions.IgnoreCase) >= 0) {

1
Bart

Je sais que j'arrive très tard. Cependant, pour tous ceux qui recherchent, je pensais publier ce que FINALEMENT fonctionnait pour moi. Je ne prétends pas que c'est la meilleure solution - seulement que cela a fonctionné.

Notre service WebApi utilise la méthode config.EnableCors (corsAttribute). Cependant, même avec cela, il échouerait toujours sur les demandes de pré-vol. @ La réponse de Mihai-Andrei Dinculescu m'a fourni un indice. Tout d'abord, j'ai ajouté son code Application_BeginRequest () pour vider les requêtes d'options. Cela n'a pas fonctionné pour moi. Le problème est que WebAPI n'ajoutait toujours pas les en-têtes prévus à la demande OPTIONS. Faire rougir tout seul ne fonctionnait pas - mais cela me donnait une idée. J'ai ajouté les en-têtes personnalisés qui seraient autrement ajoutés via le fichier web.config à la réponse à la demande OPTIONS. Voici mon code:

protected void Application_BeginRequest()
{
  if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
  {
    Response.Headers.Add("Access-Control-Allow-Origin", "https://localhost:44343");
    Response.Headers.Add("Access-Control-Allow-Headers",
      "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
    Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
    Response.Headers.Add("Access-Control-Allow-Credentials", "true");
    Response.Flush();
  }
}

Évidemment, cela ne s'applique qu'aux demandes OPTIONS. Tous les autres verbes sont gérés par la configuration CORS. S'il y a une meilleure approche à ce sujet, je suis tout ouïe. Cela ressemble à une fraude pour moi et je préférerais que les en-têtes soient ajoutés automatiquement, mais c'est ce qui a finalement fonctionné et m'a permis de passer à autre chose.

1
John Groft

Je attrape le prochain cas sur cors. Cela sera peut-être utile à quelqu'un… .. Si vous ajoutez la fonctionnalité 'WebDav Redirector' à votre serveur, les requêtes PUT et DELETE échouent.

Donc, vous devrez supprimer 'WebDAVModule' de votre serveur IIS:

  • "Dans la configuration des modules IIS, bouclez le WebDAVModule, si votre serveur Web en dispose, puis supprimez-le".

Ou ajoutez à votre config:

<system.webServer>
<modules>
  <remove name="WebDAVModule"/>
</modules>
<handlers>
  <remove name="WebDAV" />
  ...
</handlers>

0
Andrey R

J'avais essayé tout ce que je pouvais trouver sur le net, y compris les méthodes qui ont été données pour cette réponse. Après avoir presque essayé de résoudre le problème toute la journée, j'ai trouvé la solution qui a fonctionné pour moi comme un charme.

dans le fichier WebApiConfig dans le dossier App_Start , commentez toutes les lignes de code et ajoutez le code suivant:

`public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        config.EnableCors();
        var enableCorsAttribute = new EnableCorsAttribute("*",
                                           "Origin, Content-Type, Accept",
                                           "GET, PUT, POST, DELETE, OPTIONS");
        config.EnableCors(enableCorsAttribute);
        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            //routeTemplate: "api/{controller}/{id}",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
        config.Formatters.Add(new BrowserJsonFormatter());
    }

    public class BrowserJsonFormatter : JsonMediaTypeFormatter
    {
        public BrowserJsonFormatter()
        {
            this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
            this.SerializerSettings.Formatting = Formatting.Indented;
        }

        public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
        {
            base.SetDefaultContentHeaders(type, headers, mediaType);
            headers.ContentType = new MediaTypeHeaderValue("application/json");
        }
    }`
0
Yagnesh Khamar

Si vous avez des nœuds security\requestFiltering dans votre Web.config, comme suit:

<security>
  <requestFiltering>
    <verbs allowUnlisted="false">
      <add verb="GET" allowed="true" />
      <add verb="POST" allowed="true" />
      <add verb="PUT" allowed="true" />
      <add verb="DELETE" allowed="true" />
      <add verb="DEBUG" allowed="true" />          
    </verbs>
  </requestFiltering>

assurez-vous d'ajouter ceci aussi

<add verb="OPTIONS" allowed="true" />
0
ozz