Why does esriRequest cause error 'No 'Access-Control-Allow-Origin' header is present on the requested resource?'

6440
7
07-28-2019 01:12 PM
JustinBridwell2
Occasional Contributor II

I have an API that uses Basic Authentication (Username, Password). I am trying to use this in an esriRequest to pull back the JSON data object from the GET request. To test this (and potentially avoid CORS issues), I am running this on my localhost (IIS). I have already set my IIS Default WebSite HTTP Response Headers to Access-Control-Allow-Origin: '*'. However, I am still getting the following error in my esriRequest :

Access to XMLHttpRequest at 'https://ria.azurewebsites.net/api/ria/event?Username=myUsername&Password=myPassword' from origin 'http://localhost' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

This error gets thrown in both Chrome and Firefox.I even tried adding withCredentials: true to my request, but it then throws an additional error:

Cross-Origin Read Blocking (CORB) blocked cross-origin response with MIME type application/json.

At the top of my code, I have also added: esriConfig.defaults.io.corsEnabledServers.push("ria.azurewebsites.net");, which has resolved this CORS issue for other APIs in my application, but not this one. I have tried several configurations, but my current code uses a precallback function and .setRequestPreCallback() method. As you can see in the commented out attributes, I've also tried to pass 'Username' and 'Password' as content too. I have tested the general GET Request in Swagger UI and it comes back just fine. Is there something I am missing here; something else I need to do in order for this to work?:

function floodCallbackFunction(ioArgs){    
   if (ioArgs.url.indexOf("https://ria.azurewebsites.net") > -1) {        
      ioArgs.headers.Username = "myUsername";        
      ioArgs.headers.Password = "myPassword"; // add custom headers        
   }        
   return ioArgs;    
}
....
esriRequest.setRequestPreCallback(floodCallbackFunction);
var evnts;
var eventRequest = esriRequest({    
   withCredentials: true,
   url: "https://ria.azurewebsites.net/api/ria/event",    
   content: {
        // "Username": "myUsername",
        // "Password": "myPassword"            
   },    
   dataType:"jsonp",    
   handleAs: "json"});
   eventRequest.then(function(resp) {    
      evnts = resp;    
      console.log(evnts);    
      console.log("Success: ", evnts);
   }, function(error) {    
      console.log("Error: ", error.message);
});
0 Kudos
7 Replies
VictorTey
Esri Contributor

Hi, there is a really good article about how cors works.

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

In short, your endpoint need to have CORS enable by adding Access-Control-Allow-Origin  in your response header in IIS. Value of * will allow all.

https://blogs.iis.net/iisteam/getting-started-with-the-iis-cors-module

Alternatively, you can go through Esri resource proxy

https://github.com/Esri/resource-proxy

Hope that helps

0 Kudos
JarkkoKuoppamäki
New Contributor III

Victor Tey‌, I think Justin Bridwell‌ wrote above that he has "already set my IIS Default WebSite HTTP Response Headers to Access-Control-Allow-Origin: '*'" but is still getting the error.

Justin, were you able to resolve this?

JustinBridwell2
Occasional Contributor II

I was not able to get the API to return solely with a client-side solution, nor using IIS alone. After speaking directly with the API creator, I determined that the only way to resolve the issue on our side was by adding server-side code. Once I placed the application within an Asp.Net/C# framework and created an .asmx file to serve WebServices/WebMethods,   I was able to authenticate and get the API to return correctly. I passed the user/password credentials in the Web.Config file first. I still have a javascript file that uses esriRequest, but it calls the WebService and WebMethod in my .asmx file and everything works. -JB 

0 Kudos
VictorTey
Esri Contributor

Thanks Jarkko Kuoppamäki‌ and my apologies Justin Bridwell for not reading the message clearly‌. This reply is probably very late in the game now. When the request is first fired off, its makes a preflight check of type OPTION. You can match the response headers against your requests header to understand why you are getting CORS. It might be due to content type mismatch. Or referral type mismatch. if you take a screenshot  I am happy to assist

0 Kudos
JustinBridwell2
Occasional Contributor II

Side note: I set up a proxy prior to placing everything in ASP.Net. That did not work either. -JB

0 Kudos
ThanHtetAung_EsriAu
Esri Regular Contributor

Hi Justin,

You shall need to change at the api level, you don't need the proxy, as asp.net has the capability to enable cors.

Which asp.net are you using for that api?

Short description of easiest steps for webapi type are

1. Add nuget package : Microsoft.AspNet.WebApi.Cors

2. Update App_Start\WebApiConfig.cs change like this

using System.Web.Http.Cors;


public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services

            // Web API routes

            var cors = new EnableCorsAttribute("*", "*", "*");
            cors.SupportsCredentials = true;
            config.EnableCors(cors);

.......

There are different coding based on the project type. 

Below is the guideline from microsoft for asp.net web api 2

Enabling Cross-Origin Requests in ASP.NET Web API 2 | Microsoft Docs 

Enable Cross-Origin Requests (CORS) in ASP.NET Core | Microsoft Docs 

Let me know how's go, I used to use that combination and have solved before.

0 Kudos
AdrianMarsden
Regular Contributor II