Setting Access-Control-Allow-Origin in ASP.Net MVC

2018-12-31 23:29发布

问题:

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

回答1:

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



回答2:

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



回答3:

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


回答4:

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



回答5:

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


回答6:

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



回答7:

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

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


回答8:

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: \"*\")]



回答9:

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


回答10:

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>


回答11:

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