我有一个简单的actionmethod,它返回一些json。它在ajax.example.com上运行。我需要从另一个网站someothersite.com访问这个。

如果我尝试调用它,我会得到预期的…:

Origin http://someothersite.com is not allowed by Access-Control-Allow-Origin.

我知道有两种方法可以解决这个问题:JSONP和创建一个自定义HttpHandler 设置标题。

有没有更简单的办法?

对于一个简单的操作来说,是否不可能定义一个允许起源的列表-或者简单地允许所有人?也许是一个动作过滤器?

最理想的是……

return json(mydata, JsonBehaviour.IDontCareWhoAccessesMe);

对于普通ASP。NET MVC控制器

创建一个新属性

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

标记你的行动:

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

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

标记整个API控制器:

[AllowCrossSiteJson]
public class ValuesController : ApiController
{

或者单独的API调用:

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

对于Internet Explorer <= v9

IE <= 9不支持CORS。我已经写了一个javascript,将自动路由这些请求通过代理。这一切都是100%透明的(你只需要包括我的代理和脚本)。

使用nuget corsproxy下载它,并遵循附带的说明。

博客文章|源代码


如果您正在使用IIS 7+,您可以放置一个web。配置文件到根文件夹与此在系统中。网络服务器:

<httpProtocol>
   <customHeaders>
      <clear />
      <add name="Access-Control-Allow-Origin" value="*" />
   </customHeaders>
</httpProtocol>

参见:http://msdn.microsoft.com/en-us/library/ms178685.aspx 和http://enable-cors.org/ # how-iis7


我遇到了一个问题,当请求传入cookie时,浏览器拒绝提供它已经检索到的内容(例如,xhr有它的withCredentials=true),并且站点有Access-Control-Allow-Origin设置为*。(Chrome中的错误是,“当凭据标志为真时,不能在Access-Control-Allow-Origin中使用通配符。”)

基于@jgauffin的回答,我创建了这个,这基本上是一种绕过特定浏览器安全检查的方法,所以买者自负。

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

有时OPTIONS动词也会引起问题

简单: 更新你的网页。配置如下

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

用httpGet和httpOptions更新webservice/controller头

// GET api/Master/Sync/?version=12121
        [HttpGet][HttpOptions]
        public dynamic Sync(string version) 
        {

如果您正在使用API,请将这一行添加到您的方法中。

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

WebAPI 2现在有一个CORS包,可以使用以下方法安装: 安装- package Microsoft.AspNet.WebApi.Cors -pre -project webservice

安装完成后,代码如下所示:http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api


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

这非常简单,只需将其添加到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>

在Origin中输入所有可以访问你的网络服务器的域名, 在header中放入任何ajax HTTP请求可以使用的所有可能的header, 在方法中,把你允许的所有方法放在你的服务器上

的问候:)


本教程非常有用。简单总结一下:

使用Nuget上提供的CORS包:Install-Package Microsoft.AspNet.WebApi.Cors 在WebApiConfig.cs文件中,将config.EnableCors()添加到Register()方法中。 为你需要处理cors的控制器添加一个属性:

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


在网络上。输入以下命令

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

有不同的方式可以通过 Access-Control-Expose-Headers。

正如jgauffin所解释的,我们可以创建一个新属性。 正如LaundroMatt解释的那样,我们可以在网上添加。配置文件。 另一种方法是我们可以在webApiconfig.cs文件中添加如下代码。 配置。EnableCors(new EnableCorsAttribute("", headers: "", methods: "*",exposedHeaders: "TestHeaderToExpose") {SupportsCredentials = true});

或者我们可以在全局中添加以下代码。Asax文件。

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

我写的是期权。请根据您的需要修改。

快乐编码!!


如果您使用IIS,我建议尝试IIS CORS模块。 它易于配置,适用于所有类型的控制器。

下面是一个配置示例:

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

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

最后,我的MVC动作方法看起来像这样。这里重要的是还要提到Options HttpVerbs,否则preflight请求将失败。

[AcceptVerbs(HttpVerbs.Post | HttpVerbs.Options)]
[AllowCrossSiteJson]
public async Task<ActionResult> Create(MyModel model)
{
    return Json(await DoSomething(model));
}

我正在使用DotNet核心MVC,在与nuget包、Startup.cs、属性和这个地方战斗了几个小时后,我简单地将这个添加到MVC动作中:

Response.Headers.Add("Access-Control-Allow-Origin", "*");

我知道这是相当笨拙的,但这是我所需要的,没有其他想要添加这些头文件。我希望这能帮助到其他人!


使主答案工作在MVC 5。

使用System.Web.Mvc而不是System.Web.Http.Filters。

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

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
   ...
}