CORS development in localhost
Visual studio IDE comes up with built-in web server - IIS express(Casini), that allows to run the web application run with no special configurations on localhost
(127.0.0.1
). This speeds up the web application development and also removes the burden of configuring each developer's machine.
But still for certain application development scenarios like CORS headers, it would require manual addition of headers to the IIS Express configuration file.
Whenever an application is launched in IISExpress, it creates .vs
folder in the same level usually project root folder where .sln
file exists. Browsing the /.vs
folder will contain the configuration files created by Visual Studio to help launching the web server. For modifying the IIS Express configuration, navigate inside /config
folder and open applicationhost.config
in any text editor (notepad or notepad++). You can add your CORS headers as part of the customHeaders
within httpProtocol
.
For an application that should access the images, scripts and make HTTP GET
, POST
, PUT
, DELETE
etc., without need for authentication. Then you can simply add *
to the CORS header Access-Control-Allow-Origin
. This will allow any domain to access other domain's resource. e.g., http://localhost:8081 can access the APIs on http://localhost:8082.
<httpProtocol>
<customHeaders>
<clear />
<add name="X-Powered-By" value="ASP.NET" />
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol>
Sharing credentials between subdomains (or localhost with different port numbers):
In case your application, needs to share the cookies/credentials between sub-domains i.e., a.domain.com
and b.domain.com
OR in localhost environment between http://localhost:8081
and http://localhost:8082
.
For example, The authentication endpoint exists on :8081
, and application on :8082
raises a cross origin request for authentication to 8081. After successful authentication, the cookies (domain name specified as 'localhost
') that are set by the authentication endpoint on 8081
, will not be accessible to the application on 8082
which also exists on localhost
i.e., As a result, when subsequent XMLHttpRequest (AJAX) made by 8082 will fail with HTTP status 403 (Forbidden). The browser will not attach the cookie even-though the domain name are same - localhost. This is due to the difference in the port number that set the cookie. Browser agents are so strict that they won't attach the cookies when the origin differs.
So for this situation, we need to set an additional CORS header Access-Control-Allow-Credentials
with value true
, and also amend out Access-Control-Allow-Origin
header with the exact domain name, protocol and port number as follows
<httpProtocol>
<customHeaders>
<clear />
<add name="X-Powered-By" value="ASP.NET" />
<remove name="Access-Control-Allow-Origin" />
<!-- <add name="Access-Control-Allow-Origin" value="*" /> -->
<add name="Access-Control-Allow-Origin" value="http://localhost:8082" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Credentials" value="true" />
</customHeaders>
</httpProtocol>
This will allow us to do the development, when the services/api
with authentication and the client application existing on 2 different domains.
Firing of duplicate API / AJAX requests:
Whenever CORS is enabled, the browser will first send a preflight OPTIONS request to the cross-domain. As a result, you will notice that the actions or your endpoints are getting triggered twice.
In order to prevent duplicated action execution. You need to check if the HTTP request type = OPTIONS
and for that specific request, just set the required CORS
headers and send a blank response without executing the controller actions. This will allow the browsers to continue with the actual Cross-Origin request much faster and make effective use of server resource.
Further you can specify the number of seconds, the CORS response can be cached using Access-Control-Max-Age
header, so that preflight will not be attempted by the user-agent(browsers) within that duration.