Reputation: 1279
I have two VS projects : one exposing MVC5 controllers, the other being an angular client. I want the angular client to be able to query the controllers. I read numerous threads and tried the following :
I added this in the server's web config:
<system.webServer>
<httpProtocol>
<customHeaders>
<clear />
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
<system.webServer>
I created and used the the following filter on the controller's action:
public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
base.OnActionExecuting(filterContext);
}
}
In the angular client, I created the following interceptor :
app.factory("CORSInterceptor", [
function()
{
return {
request: function(config)
{
config.headers["Access-Control-Allow-Origin"] = "*";
config.headers["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS";
config.headers["Access-Control-Allow-Headers"] = "Content-Type";
config.headers["Access-Control-Request-Headers"] = "X-Requested-With, accept, content-type";
return config;
}
};
}
]);
app.config(["$httpProvider", function ($httpProvider) {
$httpProvider.interceptors.push("CORSInterceptor");
}]);
According to Firebug, this results in the following request :
OPTIONS //Login/Connect HTTP/1.1
Host: localhost:49815
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://localhost:50739
Access-Control-Request-Method: POST
Access-Control-Request-Headers: access-control-allow-headers,access-control-allow-origin,content-type
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
And the following response :
HTTP/1.1 200 OK
Allow: OPTIONS, TRACE, GET, HEAD, POST
Server: Microsoft-IIS/10.0
Public: OPTIONS, TRACE, GET, HEAD, POST
X-SourceFiles: =?UTF-8?B?RDpcVEZTXElVV2ViXEdhcE5ldFNlcnZlclxBU1BTZXJ2aWNlc1xMb2dpblxDb25uZWN0?=
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: *
Access-Control-Request-Headers: X-Requested-With, accept, content-type
Date: Tue, 01 Sep 2015 13:05:23 GMT
Content-Length: 0
And still, Firefox blocks the request with the following message :
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:49815//Login/Connect. (Reason: missing token 'access-control-allow-headers' in CORS header 'Access-Control-Allow-Headers' from CORS preflight channel).
Upvotes: 21
Views: 58091
Reputation: 3704
I had the same issue but other answers did not work for me, possibly due to working on a newer framework. Here is the official documentation from Microsoft for how to fix the issue as of 2023 https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-7.0 Below is a shorter explanation.
In the Program.cs file add the following code:
string myAllowSpecificOrigins = "myAllowSpecificOrigins";
builder.Services.AddCors(
options => {
options.AddPolicy(
name: myAllowSpecificOrigins, policy => {
policy.WithOrigins("https://localhost:44434")
.AllowAnyHeader()
.AllowAnyMethod();
}
);
}
);
app.UseCors(myAllowSpecificOrigins);
This will allow the specified port(s) to make a cross-origin request. Be sure to replace the localhost address with the port you're using if it's different. It is also important to get the placement of this code correct in your Program.cs file. UseCors
must be placed after UseRouting
and before MapControllers
(see link for more details and examples with context).
Upvotes: 0
Reputation: 88066
The problem is, some browsers don’t yet allow the *
wildcard for Access-Control-Allow-Headers
. Specifically, Firefox 69 and earlier doesn’t. See https://bugzilla.mozilla.org/show_bug.cgi?id=1309358.
So to ensure you get correct behavior in all browsers, the Access-Control-Allow-Headers
value you send back should explicitly list all the header names you actually need to access from your frontend code; e.g., in the case in the question: Access-Control-Allow-Headers: Content-Type
.
A way you can make that happen without needing to hardcode all the header names is: Have your server-side code take the value of the Access-Control-Request-Headers
request header the browser sends, and just echo that into the value of the Access-Control-Allow-Headers
response header your server sends back.
Or else use some existing library to CORS-enable your server. Echoing the Access-Control-Request-Headers
request-header value into the Access-Control-Allow-Headers
response-header value is something most CORS libraries will typically do for you.
Upvotes: 17
Reputation: 1
I tried in my .net c# mvc app and client app in angular 8 but it is not working. IN web.config, i added
<httpProtocol>
<customHeaders>
<clear />
<add name="Access-Control-Allow-Origin" value="http://localhost:4200" />
<add name="Access-Control-Allow-Headers" value="Content-Type"/>
</customHeaders>
</httpProtocol>
In global.axax.cs file also, i added
void MvcApplication_AuthenticateRequest(object sender, EventArgs e)
{
Context.Response.AddHeader("Access-Control-Allow-Origin", "http://localhost:4200");
}
but it is not working. In chrome in response header it does show as :
Access-Control-Allow-Headers: Content-Type Access-Control-Allow-Origin: http://localhost:4200 Access-Control-Allow-Origin: http://localhost:4200
but in request header it shows as
Access-Control-Request-Headers: access-control-allow-origin,content-type,x-iphoneclientid
whereas it needs to have like
x-iphoneclientid : 8E72FF50-548B
since x-iphoneclientid is the token i validate in my filter class as
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
if (request == null || request.RequestUri == null)
{
return null;
}
// Write your Authentication code here
IEnumerable<string> monsterApiKeyHeaderValues = null;
// Checking the Header values
if (request.Headers.TryGetValues("x-iphoneclientid", out monsterApiKeyHeaderValues))
and above condition does not find so it rejects it and it does not reach to controller.
I even have put following in my controller
[EnableCors("", "", "*")]
can you guide please
Thanks
Upvotes: 0
Reputation: 1279
Oftentimes, the threads that I read were suggesting several unecessary configuration steps, which created confusion. It's actually very simple...
For the simple purpose of sending a cross site request, from an angular client, to an ASP controller :
The only mandatory modification is to add this in the server's web.config
<system.webServer>
<httpProtocol>
<customHeaders>
<clear />
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type"/>
</customHeaders>
</httpProtocol>
</system.webServer>
Upvotes: 30