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

128

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;

        }      
    }
}
Noa Gani
la source
1
Partagez également votre code angulaire pour demander des cors
harishr
2
Il n'y a probablement aucun problème avec son code angulaire puisque la plupart des problèmes CORS ne sont dus qu'à la configuration du serveur
sam
J'ai le même type de configuration, j'ai remarqué que lorsque je demande une action inexistante sur l'API et que WebApi renvoie un 404, l'en-tête CORS est manquant et le navigateur se plaint. Alors, c'est peut-être aussi simple que ça.
Robin van der Knaap

Réponses:

296

Vous devez activer CORS dans votre API Web . La manière la plus simple et la plus préférée d'activer CORS globalement consiste à ajouter ce qui suit 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 toutes spécifiées individuellement, au lieu d'être utilisées *. C'est parce qu'un bogue se produit lors de l'utilisation *.

Vous pouvez également activer CORS par code.

Mise à jour
ci - dessous NuGet package est requis: Microsoft.AspNet.WebApi.Cors.

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

        // ...
    }
}

Ensuite, vous pouvez utiliser l' [EnableCors]attribut 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 les Options demandes de contrôle en amont avec les HTTP OPTIONSdemandes.

Web APIdoit répondre à la Optionsdemande afin de confirmer qu'il est bien configuré pour prendre en charge CORS.

Pour gérer cela, tout ce que vous avez à faire est de renvoyer une réponse vide . Vous pouvez le faire 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 s'assurer que les anciens APIsqui ont été conçus pour accepter uniquement GETet les POSTdemandes ne seront pas exploités. Imaginez envoyer une DELETErequête à un APIdesign alors que ce verbe n'existait pas. Le résultat est imprévisible et les résultats peuvent être dangereux .

Mihai-Andrei Dinculescu
la source
4
Votre réponse m'a aidé. J'avais essayé tout ce que je pouvais avec les solutions de base de code. Je n'ai pas essayé l'option web.config avant d'avoir lu votre réponse. C'était le seul qui fonctionnait. Une idée pourquoi? J'utilise Web API 2 avec OData. Merci quand même! :)
Felipe Correa
1
Pour référence future, le package NuGet dont vous avez besoin pour cela est «Microsoft.AspNet.WebApi.Cors».
BrainSlugs83
2
J'ai suivi toutes vos réponses et j'ai deux questions: Où doit-on invoquer Application_BeginRequest ()? et deuxièmement, dans la même méthode, le .Contains ("Origin") ne se compile pas vraiment chez moi, d'où vient cette méthode, String.Contains, ou de Linq.Contains?
meJustAndrew
2
souvenez-vous qu'un port différent # constitue un domaine différent, ce qui peut être un piège. foo.com est un domaine différent de foo.com:8080
RyBolt
2
Vous sauvez ma vie;)
Paweł Groński
26

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

L'ajout d'un '/' à la fin de votre URL empêchera EnableCors de fonctionner dans tous les cas (par exemple depuis la page d'accueil).

Ie 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 le même si vous utilisez l'attribut EnableCors.

HockeyJ
la source
Merci!! Cela a été utile.
Ankit Sahrawat le
23

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

<remove name="OPTIONSVerbHandler" />

Je viens de le supprimer de Web.Config (il suffit de le commenter comme ci-dessous) et Cors fonctionne comme un charme

<handlers>
  <!-- remove name="OPTIONSVerbHandler" / -->
</handlers>
AlbertSY
la source
9

Cela peut être dû à l'installation des packages Cors Nuget.

Si vous rencontrez le problème après avoir installé et activé des cors de nuget, vous pouvez essayer de réinstaller l'API Web.

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

Bimal Das
la source
C'était exactement ça pour moi. J'ai installé System.Web.Http.Cors puis désinstallé, ce qui a laissé WebApi sur la mauvaise version (nouvellement mise à niveau) entre 5.2.2 et 5.2.3
TaeKwonJoe
7

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.

Andrei
la source
pour vérifier si cela fonctionne, il vaut mieux supprimer supportCredentials ainsi, il désactive les cors dans certaines conditions
harishr
Meilleure réponse car je ne veux pas activer CORS pour tout mon site, juste certains points de terminaison. config.EnableCors()est également nécessaire pour cela.
Csaba Toth
4

Pour que n'importe quel protocole CORS fonctionne, vous devez avoir une méthode OPTIONS sur chaque point de terminaison (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 enverra d'abord une requête OPTIONS pour `` tester '' votre serveur et voir les autorisations

sam
la source
2

J'attrape le cas suivant sur les cors. Peut-être que ce sera utile à quelqu'un. Si vous ajoutez la fonctionnalité 'WebDav Redirector' à votre serveur, les requêtes PUT et DELETE échouent.

Vous devrez donc supprimer 'WebDAVModule' de votre serveur IIS:

  • "Dans la configuration des modules IIS, bouclez le WebDAVModule, si votre serveur Web l'a, supprimez-le".

Ou ajoutez à votre configuration:

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

Andrey R
la source
2

Je sais que j'arrive très tard. Cependant, pour tous ceux qui recherchent, j'ai pensé publier ce qui a finalement fonctionné 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 avant le vol. La réponse de @ Mihai-Andrei Dinculescu m'a fourni l'indice. Tout d'abord, j'ai ajouté son code Application_BeginRequest () pour vider les demandes d'options. Cela n'a TOUJOURS pas fonctionné pour moi. Le problème est que WebAPI n'ajoutait toujours aucun des en-têtes attendus à la requête OPTIONS. Le rinçage seul n'a pas fonctionné - mais cela m'a donné une idée. J'ai ajouté les en-têtes personnalisés qui seraient autrement ajoutés via le web.config à la réponse pour la requête 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 requêtes OPTIONS. Tous les autres verbes sont gérés par la configuration CORS. S'il y a une meilleure approche à cela, je suis toute oreille. Cela me semble une triche 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.

John Groft
la source
1

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

  • Ajouter un <httpProtocol>dans la <system.webServer>section de web.config
  • Renvoyer une réponse vide pour les OPTIONSdemandes via le mentionné Application_BeginRequest()dansglobal.asax

Sauf que son chèque Request.Headers.AllKeys.Contains("Origin")n'a PAS fonctionné pour moi, car la requête contenait un origing, donc en minuscules. Je pense que mon navigateur (Chrome) l'envoie comme ça pour les requêtes CORS.

J'ai résolu cela de manière un peu plus générique en utilisant à la place une variante insensible à la casse de sa Containsvérification: if (culture.CompareInfo.IndexOf(string.Join(",", Request.Headers.AllKeys), "Origin", CompareOptions.IgnoreCase) >= 0) {

Bart
la source
0

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 de l'ajouter également

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

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

dans le fichier WebApiConfig du 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");
        }
    }`
Yagnesh Khamar
la source
0

Je sais que les gens trouveront probablement cela très évident au début, mais réfléchissez vraiment à cela. Cela peut souvent arriver si vous avez fait quelque chose de mal.

Par exemple, j'ai eu ce problème parce que je n'ai pas ajouté d'entrée d'hôte à mon fichier d'hôtes. Le vrai problème était la résolution DNS. Ou je viens de me tromper sur l'URL de base.

Parfois, j'obtiens cette erreur si le jeton d'identité provient d'un serveur, mais j'essaie de l'utiliser sur un autre.

Parfois, vous obtiendrez cette erreur si vous avez une mauvaise ressource.

Vous pourriez l'obtenir si vous placez le middleware CORS trop tard dans la chaîne.

Bluebaron
la source
0

Évitez les emplacements multiples en activant CORS, comme WebApiCOnfig.cs, la méthode GrantResourceOwnerCredentials dans le fournisseur et l'attribut d'en-tête de contrôleur, etc. Voici la liste qui provoque également l'origine du contrôle d'accès

  1. Web ayant truble dans l'interaction avec DB que vous avez utilisé.
  2. AWS Cloud Si le VPC de l'API Web et la base de données sont différents.

Le code ci-dessous est plus que suffisant pour fixer l'origine du contrôle d'accès. // Assurez-vous que app.UseCors doit être en haut de la ligne de code de la configuration.

   public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
            //All other configurations
        }
    }

Cela a ralenti mon problème.

Sharad
la source
0

Ce problème se produit lorsque vous essayez d'accéder à partir d'un domaine différent ou d'un port différent.

Si vous utilisez Visual Studio, accédez à Outils> Gestionnaire de package NuGet> Console du gestionnaire de package. Là, vous devez installer le package NuGet Microsoft.AspNet.WebApi.Cors

Install-Package Microsoft.AspNet.WebApi.Cors

Ensuite, dans PROJET> App_Start> WebApiConfig, activez CORS

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        
        //Enable CORS. Note that the domain doesn't have / in the end.
        config.EnableCors(new EnableCorsAttribute("https://tiagoperes.eu",headers:"*",methods:"*"));

        ....

    }
}

Une fois installé avec succès, créez la solution et cela devrait suffire

Tiago Martins Peres 李大仁
la source