If you have NOT seen them before (and I doubt that you’re so lucky, because you’ve found this post after all…) – the symptom often appears in a browser when you try to load your web application and manifests by – superficially – the browser not seeming to load a resource. (Worst case it won’t load anything at all and also not give you an error message – so you’ll need to open the Console as part of the Developer Tools in the browser to confirm).
The whole thing is meant to make it more secure for a user to use a web browser without pulling stuff from random sources together, as far as I understand. (Mozilla Cross-Origin Resource Sharing (CORS) - HTTP | MDN )
After tearing a few handful of my - now grey - hair out and biting larg-ish chunks out of my desk, I also went to Geonet and found a few reassuring hints that confirmed that I wasn’t alone - like https://community.esri.com/message/840788-cors-is-not-allowing-wab-to-connect-to-my-agol-org?q=cors (a.k.a. don’t whitelist pages – if they haven’t been blacklisted)
Of course, I’ve consulted the Esri documentation, principally the developer site, a few examples being:
https://www.esri.com/arcgis-blog/products/js-api-arcgis/mapping/cross-origin-resource-sharing-cors-w... (from 2011 – so this is be no means a new thing – and this document should perhaps no longer appear in Google searches as it refers to outdated solutions/workarounds which may make things worse and don't apply to v4 API etc.)
And the above Esri 4.11 documentation, of course, still refers to https://enable-cors.org/server_iis7.html which (only) has links to IIS6 and IIS7. Hang on – IIS7, that was part of Window Vista and Windows Server 2008! We have Windows servers for all of our GIS, so what about my Windows 2016 server with IIS10, or even the Windows 2019 servers – does the same still apply? Looks as if I’ll just have to assume that it does for lack of a better source of information … so off I went I tried to comply:
Enable-cors.org states that for CORS on IIS7 you need to “Merge this into the web.config file at the root of your application or site” and gives you a bit of XML to insert.
I wasn’t quite sure where I would add it and, using trial and error, several IIS service restarts later, I seemed to have some successes: several times I was able to load a layer which it previously had refused to load. Then, other times, in other applications it would suddenly refuse to load them ( the error message had changed now and was saying something along the lines of “Access-Control-Allow-Credentials request not permitted when the rule is "Access-Control-Allow-Origin" value="*" or so.
Hm, yes, that’s the rule in the XML from enable-cors that I’ve added to the Web.config at the root of my IIS site. So why is it not working in this case?
Turns out that, apparently, while the above rule (XML) from enable-cors.org opens up the web server to allow all sorts of Cross-Origin-Requests being made, current browsers consider that to be too insecure to accept and refuse to load some secured layers (which are kind of requested using credentials, I believe). So we’ll need to be more specific and set up rules on the Web Server which allow making requests from a variety of sources that are getting mashed up in our application.
Okay, so let me try a proxy configuration (the Esri documentation says “Before CORS, it was necessary to work with a proxy page. This was helpful as it was used to bypass the issue many applications had when accessing resources that were not on the same origin.”)
The idea is that I’ll simply get the dotNet (ASP.NET) config from Esri’s GitHub https://github.com/Esri/resource-proxy/tree/master/DotNet – perhaps that’s easier?!
Yes. No. Kind of. I was able to specify some rules for some of the services and actually that eventually let me load my application with all it’s mashed-up services from different origins alright. But there are some intricacies: Because the Proxy acts as the middle-man between your application and the services that your application tries to load, there is a communication overhead – which slows things down (a bit). If you’ve got large numbers of features, for instance, that you’re trying to show on the screen, perhaps using the new feature binning, then the fact that all traffic has to be facilitated by the proxy page on your web server, will potentially slow down your application considerably (my application was very, very slow when using the proxy page). I also had just started to deploy my applications using netlify and github and didn't like the thought that some of our AppIDs might slip into a public repository along with a proxy page (that also netflify can't even use!)
So don't use a proxy page - unless you have to.
Back to the square one…
If you scroll down a bit the post says this:
The API will assume web servers support CORS. Here are the details behind how the API handled CORS until 4.8, and how it will change starting at 4.9.”
And here’s the crux: the API will assume that your web server supports CORS.
Well our IIS servers, in their default configuration, certainly didn’t support CORS. Why? Because it’s not the default when you install it (and no-one knew any better at the time of installation so nothing else was done to enable it, so it would become the new default.)
as a project manager once said to me.
And here’s the solution: there’s a module for IIS from Microsoft which can be installed and configured in a fine-grained way.
Here’s some documentation from Microsoft https://docs.microsoft.com/en-us/iis/extensions/cors-module/cors-module-configuration-reference#cors... and here’s where to download the module https://www.iis.net/downloads/microsoft/iis-cors-module
<?xml version="1.0" encoding="UTF-8"?>
<cors enabled="true" failUnlistedOrigins="true">
<add origin="*" />
<add header="header1" />
<add header="header2" />
<add method="DELETE" />
<add header="header1" />
<add header="header2" />
<add origin="http://*" allowed="false" />
CORS issues will be a steady companion if you do any development using services from multiple sources (and you most likely will). They’re relatively easy to get rid of with the above module (if, like we do, you use IIS on Windows) but it will need to be configured – almost always, as I venture to assume…
Make sure you revert all your efforts in various bits of application web.config files (e.g. from Web App Builder) once you’ve got your configuration ready in the IIS CORS Module configuration.
PS: In case you use netlify, use a netlify.toml file to define your rules - i've had some good success with that too (but it's similarly loose in the example below and you'll find that with some secured services from, say an Enterprise portal, it won't allow those services to be loaded).