I have spent a bunch of time "fighting" with WebAPI CORS when suddenly I have understood that the problem is in AJAX call. This request executes successfully:
$.ajax({
url: "myserver:8081/User/Get",
data: {
"Id": 12
},
type: "POST",
dataType: "json",
// contentType: "application/json; encoding=utf-8"
});
According to jQuery.ajax() documentation
,
For cross-domain requests, setting the content type to anything other than application/x-www-form-urlencoded
, multipart/form-data
, or text/plain
will trigger the browser to send a preflight OPTIONS request to the server.
Browser is preflighting the request to look for CORS headers and discover if server allows cross-domain requests and making a real request is safe. If the request is acceptable, it will then send the real request.
A browser sends a preflight request is:
- HTTP method is not
GET
, POST
or HEAD
;
- or if
Content-Type
is not application/x-www-form-urlencoded
, multipart/form-data
or text/plain
;
- or if any custom HTTP headers are set.
So, Chrome sends OPTIONS
"preflight" request. Insofar as I allow only POST
and GET
requests at the server, the browser thinks that it is a CORS violation and denies request.
This StackOverflow question is directly related to this question and explains what is "preflight" request and why does a browser need to send it.
The solution was as simple as the problem cause - don't specify Content-Type in cross-domain AJAX calls.
If you need to specify custom headers or Content-Type
for your requests, you can implement a specal handler which will allow preflight requests. This StackOverflow article describes how to do this.
I hope that it will help someone to save time.