Setting Access-Control-Allow-Origin in ASP.Net MVC - simplest possible method

Jsonasp.net Mvc-3Corsasp.net Ajax

Json Problem Overview


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);

Json Solutions


Solution 1 - Json

For plain ASP.NET MVC Controllers

Create a new attribute

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
        base.OnActionExecuting(filterContext);
    }
}

Tag your action:

[AllowCrossSiteJson]
public ActionResult YourMethod()
{
    return Json("Works better?");
}

For ASP.NET Web API

using System;
using System.Web.Http.Filters;

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        if (actionExecutedContext.Response != null)
            actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");

        base.OnActionExecuted(actionExecutedContext);
    }
}

Tag a whole API controller:

[AllowCrossSiteJson]
public class ValuesController : ApiController
{

Or individual API calls:

[AllowCrossSiteJson]
public IEnumerable<PartViewModel> Get()
{
    ...
}

For Internet Explorer <= v9

IE <= 9 doesn't support CORS. I've written a javascript that will automatically route those requests through a proxy. It's all 100% transparent (you just have to include my proxy and the script).

Download it using nuget corsproxy and follow the included instructions.

Blog post | Source code

Solution 2 - Json

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

Solution 3 - Json

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);
    }
}

Solution 4 - Json

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 :)

Solution 5 - Json

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) 
        {

Solution 6 - Json

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

Solution 7 - Json

Add this line to your method, If you are using a API.

HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); 

Solution 8 - Json

This tutorial is very useful. To give a quick summary:

  1. Use the CORS package available on Nuget: Install-Package Microsoft.AspNet.WebApi.Cors

  2. In your WebApiConfig.cs file, add config.EnableCors() to the Register() method.

  3. Add an attribute to the controllers you need to handle cors:

[EnableCors(origins: "<origin address in here>", headers: "*", methods: "*")]

Solution 9 - Json

    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);
    }

Solution 10 - Json

> There are different ways we can pass the > Access-Control-Expose-Headers.

  • As jgauffin has explained we can create a new attribute.

  • As LaundroMatt has explained we can add in the web.config file.

  • 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 !!

Solution 11 - Json

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));
}

Solution 12 - Json

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!

Solution 13 - Json

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>

Solution 14 - Json

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>

Solution 15 - Json

To make the main answer work in MVC 5.

Use System.Web.Mvc instead of System.Web.Http.Filters.

using System;
using System.Web.Mvc;
// using System.Web.Http.Filters;

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
   ...
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKjensenView Question on Stackoverflow
Solution 1 - JsonjgauffinView Answer on Stackoverflow
Solution 2 - JsonLaundroMattView Answer on Stackoverflow
Solution 3 - JsonKen SmithView Answer on Stackoverflow
Solution 4 - JsonZvonimir TokicView Answer on Stackoverflow
Solution 5 - JsonBishoy HannaView Answer on Stackoverflow
Solution 6 - JsonTarunView Answer on Stackoverflow
Solution 7 - JsonGopichandarView Answer on Stackoverflow
Solution 8 - JsonGrandMasterFlushView Answer on Stackoverflow
Solution 9 - JsonPranav LabheView Answer on Stackoverflow
Solution 10 - JsonTrilok PathakView Answer on Stackoverflow
Solution 11 - Jsonpkmelee337View Answer on Stackoverflow
Solution 12 - JsonBen PowerView Answer on Stackoverflow
Solution 13 - JsonElvis SkensbergView Answer on Stackoverflow
Solution 14 - JsonolshView Answer on Stackoverflow
Solution 15 - Jsonmathfournier99View Answer on Stackoverflow