I have a simple actionmethod, that returns some json. It runs on ajax.example.com. I need to access this from another site someothersite.com.
If I try to call it, I get the expected...:
Origin http://someothersite.com is not allowed by Access-Control-Allow-Origin.
I know of two ways to get around this: JSONP and creating a custom HttpHandler to set the header.
Is there no simpler way?
Is it not possible for a simple action to either define a list of allowed origins - or simple allow everyone? Maybe an action filter?
Optimal would be...:
return json(mydata, JsonBehaviour.IDontCareWhoAccessesMe);
This question is related to
json
asp.net-mvc-3
cors
asp.net-ajax
Add this line to your method, If you are using a API.
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
WebAPI 2 now has a package for CORS which can be installed using :
Install-Package Microsoft.AspNet.WebApi.Cors -pre -project WebServic
Once this is installed, follow this for the code :http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api
If you are using IIS 7+, you can place a web.config file into the root of the folder with this in the system.webServer section:
<httpProtocol>
<customHeaders>
<clear />
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
See: http://msdn.microsoft.com/en-us/library/ms178685.aspx And: http://enable-cors.org/#how-iis7
I ran into a problem where the browser refused to serve up content that it had retrieved when the request passed in cookies (e.g., the xhr had its withCredentials=true
), and the site had Access-Control-Allow-Origin
set to *
. (The error in Chrome was, "Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true.")
Building on the answer from @jgauffin, I created this, which is basically a way of working around that particular browser security check, so caveat emptor.
public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// We'd normally just use "*" for the allow-origin header,
// but Chrome (and perhaps others) won't allow you to use authentication if
// the header is set to "*".
// TODO: Check elsewhere to see if the origin is actually on the list of trusted domains.
var ctx = filterContext.RequestContext.HttpContext;
var origin = ctx.Request.Headers["Origin"];
var allowOrigin = !string.IsNullOrWhiteSpace(origin) ? origin : "*";
ctx.Response.AddHeader("Access-Control-Allow-Origin", allowOrigin);
ctx.Response.AddHeader("Access-Control-Allow-Headers", "*");
ctx.Response.AddHeader("Access-Control-Allow-Credentials", "true");
base.OnActionExecuting(filterContext);
}
}
In Web.config enter the following
<system.webServer>
<httpProtocol>
<customHeaders>
<clear />
<add name="Access-Control-Allow-Credentials" value="true" />
<add name="Access-Control-Allow-Origin" value="http://localhost:123456(etc)" />
</customHeaders>
</httpProtocol>
public ActionResult ActionName(string ReqParam1, string ReqParam2, string ReqParam3, string ReqParam4)
{
this.ControllerContext.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin","*");
/*
--Your code goes here --
*/
return Json(new { ReturnData= "Data to be returned", Success=true }, JsonRequestBehavior.AllowGet);
}
I'm using DotNet Core MVC and after fighting for a few hours with nuget packages, Startup.cs, attributes, and this place, I simply added this to the MVC action:
Response.Headers.Add("Access-Control-Allow-Origin", "*");
I realise this is pretty clunky, but it's all I needed, and nothing else wanted to add those headers. I hope this helps someone else!
If you use IIS, I'd suggest trying IIS CORS module.
It's easy to configure and works for all types of controllers.
Here is an example of configuration:
<system.webServer>
<cors enabled="true" failUnlistedOrigins="true">
<add origin="*" />
<add origin="https://*.microsoft.com"
allowCredentials="true"
maxAge="120">
<allowHeaders allowAllRequestedHeaders="true">
<add header="header1" />
<add header="header2" />
</allowHeaders>
<allowMethods>
<add method="DELETE" />
</allowMethods>
<exposeHeaders>
<add header="header1" />
<add header="header2" />
</exposeHeaders>
</add>
<add origin="http://*" allowed="false" />
</cors>
</system.webServer>
Sometimes OPTIONS verb as well causes problems
Simply: Update your web.config with the following
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
</customHeaders>
</httpProtocol>
</system.webServer>
And update the webservice/controller headers with httpGet and httpOptions
// GET api/Master/Sync/?version=12121
[HttpGet][HttpOptions]
public dynamic Sync(string version)
{
This is really simple , just add this in web.config
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="http://localhost" />
<add name="Access-Control-Allow-Headers" value="X-AspNet-Version,X-Powered-By,Date,Server,Accept,Accept-Encoding,Accept-Language,Cache-Control,Connection,Content-Length,Content-Type,Host,Origin,Pragma,Referer,User-Agent" />
<add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, OPTIONS" />
<add name="Access-Control-Max-Age" value="1000" />
</customHeaders>
</httpProtocol>
</system.webServer>
In Origin put all domains that have access to your web server, in headers put all possible headers that any ajax http request can use, in methods put all methods that you allow on your server
regards :)
After struggling for a whole evening I finally got this to work. After some debugging I found the problem I was walking into was that my client was sending a so called preflight Options request to check if the application was allowed to send a post request with the origin, methods and headers provided. I didn't want to use Owin or an APIController, so I started digging and came up with the following solution with just an ActionFilterAttribute. Especially the "Access-Control-Allow-Headers" part is very important, as the headers mentioned there do have to match the headers your request will send.
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MyNamespace
{
public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpRequest request = HttpContext.Current.Request;
HttpResponse response = HttpContext.Current.Response;
// check for preflight request
if (request.Headers.AllKeys.Contains("Origin") && request.HttpMethod == "OPTIONS")
{
response.AppendHeader("Access-Control-Allow-Origin", "*");
response.AppendHeader("Access-Control-Allow-Credentials", "true");
response.AppendHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE");
response.AppendHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, X-RequestDigest, Cache-Control, Content-Type, Accept, Access-Control-Allow-Origin, Session, odata-version");
response.End();
}
else
{
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.Cache.SetNoStore();
response.AppendHeader("Access-Control-Allow-Origin", "*");
response.AppendHeader("Access-Control-Allow-Credentials", "true");
if (request.HttpMethod == "POST")
{
response.AppendHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE");
response.AppendHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, X-RequestDigest, Cache-Control, Content-Type, Accept, Access-Control-Allow-Origin, Session, odata-version");
}
base.OnActionExecuting(filterContext);
}
}
}
}
Finally, my MVC action method looks like this. Important here is to also mention the Options HttpVerbs, because otherwise the preflight request will fail.
[AcceptVerbs(HttpVerbs.Post | HttpVerbs.Options)]
[AllowCrossSiteJson]
public async Task<ActionResult> Create(MyModel model)
{
return Json(await DoSomething(model));
}
This tutorial is very useful. To give a quick summary:
Use the CORS package available on Nuget: Install-Package Microsoft.AspNet.WebApi.Cors
In your WebApiConfig.cs
file, add config.EnableCors()
to the Register()
method.
Add an attribute to the controllers you need to handle cors:
[EnableCors(origins: "<origin address in here>", headers: "*", methods: "*")]
There are different ways we can pass the Access-Control-Expose-Headers.
Another way is we can add code as below in the webApiconfig.cs file.
config.EnableCors(new EnableCorsAttribute("", headers: "", methods: "*",exposedHeaders: "TestHeaderToExpose") { SupportsCredentials = true });
Or we can add below code in the Global.Asax file.
protected void Application_BeginRequest()
{
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
//These headers are handling the "pre-flight" OPTIONS call sent by the browser
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "*");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://localhost:4200");
HttpContext.Current.Response.AddHeader("Access-Control-Expose-Headers", "TestHeaderToExpose");
HttpContext.Current.Response.End();
}
}
I have written it for the options. Please modify the same as per your need.
Happy Coding !!
Source: Stackoverflow.com