Asp.Net WebApi2 включить CORS не работает с AspNet.Веб-API.Cors 5.2.3

Я попытался выполнить шаги в http://enable-cors.org/server_aspnet.html чтобы иметь Мой RESTful API (реализованный с ASP.NET WebAPI2) работа с запросами перекрестного происхождения (CORS включен). Он не работает, пока я не изменю сеть.конфиг.

Я установил зависимость WebAPI Cors:

install-package Microsoft.AspNet.WebApi.Cors -ProjectName MyProject.Web.Api

тогда в моем App_Start у меня есть класс WebApiConfig следующим образом:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var corsAttr = new EnableCorsAttribute("*", "*", "*");
        config.EnableCors(corsAttr);

        var constraintsResolver = new DefaultInlineConstraintResolver();

        constraintsResolver.ConstraintMap.Add("apiVersionConstraint", typeof(ApiVersionConstraint));
        config.MapHttpAttributeRoutes(constraintsResolver); 
        config.Services.Replace(typeof(IHttpControllerSelector), new NamespaceHttpControllerSelector(config));
        //config.EnableSystemDiagnosticsTracing(); 
        config.Services.Replace(typeof(ITraceWriter), new SimpleTraceWriter(WebContainerManager.Get<ILogManager>())); 
        config.Services.Add(typeof(IExceptionLogger), new SimpleExceptionLogger(WebContainerManager.Get<ILogManager>()));
        config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler()); 
    }
}

но после этого я запускаю приложение, я запрашиваю ресурс с Fiddler как: http://localhost:51589/api/v1/persons и в ответе я не вижу заголовки HTTP, которые я должен видеть, такие как:

  • Access-Control-Allow-Methods: POST, PUT, DELETE, GET, OPTIONS
  • Access-Control-Allow-Origin: *

я пропустил какой-то шаг? Я пробовал со следующей аннотацией на контроллере:

[EnableCors(origins: "http://example.com", headers: "*", methods: "*")]

тот же результат, без CORS включен.

однако, если я добавлю следующее в свой веб-сайт.конфигурации (без установки сеть САШ.Веб-API.CORS dependency) работает:

<system.webServer>

<httpProtocol>
  <!-- THESE HEADERS ARE IMPORTANT TO WORK WITH CORS -->
  <!--
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Methods" value="POST, PUT, DELETE, GET, OPTIONS" />
    <add name="Access-Control-Allow-Headers" value="content-Type, accept, origin, X-Requested-With, Authorization, name" />
    <add name="Access-Control-Allow-Credentials" value="true" />
  </customHeaders>
  -->
</httpProtocol>
<handlers>
  <!-- THESE HANDLERS ARE IMPORTANT FOR WEB API TO WORK WITH  GET,HEAD,POST,PUT,DELETE and CORS-->
  <!--

  <remove name="WebDAV" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,PUT,DELETE" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <remove name="TRACEVerbHandler" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
-->
</handlers>

любая помощь была бы очень признательна!

спасибо.

10 ответов


Я создал сокращенный демо-проект для вас.

вы можете попробовать выше API Link от вашего местного скрипача, чтобы увидеть заголовки. Вот объяснение.

глобальные.ascx и

все это вызывает WebApiConfig. Это всего лишь кодовая организация.

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        WebApiConfig.Register(GlobalConfiguration.Configuration);
    }
}

WebApiConfig.cs

основным методом для вот EnableCrossSiteRequests метод. Это все что нужно делать. The EnableCorsAttribute это атрибут CORS с глобальной областью видимости.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        EnableCrossSiteRequests(config);
        AddRoutes(config);
    }

    private static void AddRoutes(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "Default",
            routeTemplate: "api/{controller}/"
        );
    }

    private static void EnableCrossSiteRequests(HttpConfiguration config)
    {
        var cors = new EnableCorsAttribute(
            origins: "*", 
            headers: "*", 
            methods: "*");
        config.EnableCors(cors);
    }
}

Параметры Регулятора

в Get метод получает EnableCors атрибут, который мы применили глобально. The Another метод переопределяет глобальную EnableCors.

public class ValuesController : ApiController
{
    // GET api/values
    public IEnumerable<string> Get()
    {
        return new string[] { 
            "This is a CORS response.", 
            "It works from any origin." 
        };
    }

    // GET api/values/another
    [HttpGet]
    [EnableCors(origins:"http://www.bigfont.ca", headers:"*", methods: "*")]
    public IEnumerable<string> Another()
    {
        return new string[] { 
            "This is a CORS response. ", 
            "It works only from two origins: ",
            "1. www.bigfont.ca ",
            "2. the same origin." 
        };
    }
}

Web.config

вам не нужно добавлять ничего особенного в сеть.конфиг. На самом деле, это то, что веб-демо.конфигурация выглядит так - она пуста.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
</configuration>

демо

var url = "https://cors-webapi.azurewebsites.net/api/values"

$.get(url, function(data) {
  console.log("We expect this to succeed.");
  console.log(data);
});

var url = "https://cors-webapi.azurewebsites.net/api/values/another"

$.get(url, function(data) {
  console.log(data);
}).fail(function(xhr, status, text) {
  console.log("We expect this to fail.");
  console.log(status);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

вам просто нужно изменить некоторые файлы. Это работает для меня.

глобальные.ascx и

public class WebApiApplication : System.Web.HttpApplication {
    protected void Application_Start()
    {
        WebApiConfig.Register(GlobalConfiguration.Configuration);
    } }

WebApiConfig.cs

все запросы должны вызывать этот код.

public static class WebApiConfig {
    public static void Register(HttpConfiguration config)
    {
        EnableCrossSiteRequests(config);
        AddRoutes(config);
    }

    private static void AddRoutes(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "Default",
            routeTemplate: "api/{controller}/"
        );
    }

    private static void EnableCrossSiteRequests(HttpConfiguration config)
    {
        var cors = new EnableCorsAttribute(
            origins: "*", 
            headers: "*", 
            methods: "*");
        config.EnableCors(cors);
    } }

Какой-То Контроллер

ничего не изменится.

Web.config

вам нужно добавить обработчики в вашем интернете.config

<configuration> 
  <system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>   
  </system.webServer> 
</configuration>

в случае запроса CORS все современные браузеры отвечают глаголом опции, а затем следует фактический запрос. Это должно использоваться для запроса подтверждения пользователем в случае запроса CORS. Но в случае API, если вы хотите пропустить этот процесс проверки, добавьте следующий фрагмент в Global.асакс

        protected void Application_BeginRequest(object sender, EventArgs e)
        {
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
            if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
            {
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE");

                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
                HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
                HttpContext.Current.Response.End();
            }
        }

здесь мы просто проходим проверку, проверяя глагол OPTIONS.


Я просто добавил пользовательские заголовки в Интернете.config и он работал как шарм.

On configuration-system.сервер:

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

У меня есть приложение переднего плана и бэкэнд на том же решении. Чтобы это работало, мне нужно установить проект веб-служб (Backend) по умолчанию для этого.

Я использовал ReST, не пробовал ни с чем другим.


после некоторых изменений в моей сети.config CORS внезапно перестала работать в моем проекте Web API 2 (по крайней мере, для запроса опций во время предполетного запуска). Кажется, что вам нужно иметь раздел, упомянутый ниже в вашем интернете.config или иначе (глобальных) нем не будет работать по запросам варианты. Обратите внимание, что это тот же самый раздел, который Visual Studio добавит в новый проект Web API 2.

<system.webServer>
  <handlers>
    <remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
    <remove name="OPTIONSVerbHandler"/>
    <remove name="TRACEVerbHandler"/>
    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/>
  </handlers>
</system.webServer>

ни один из этих ответов не работает. Как отмечали другие, пакет Cors будет использовать заголовок Access-Control-Allow-Origin только в том случае, если запрос имеет заголовок Origin. Но вы не можете просто добавить заголовок Origin в запрос, потому что браузеры могут попытаться регулировать это тоже.

Если вы хотите быстрый и грязный способ разрешить перекрестные запросы сайта к веб-api, на самом деле намного проще просто написать пользовательский атрибут фильтра:

public class AllowCors : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        if (actionExecutedContext == null)
        {
            throw new ArgumentNullException("actionExecutedContext");
        }
        else
        {
            actionExecutedContext.Response.Headers.Remove("Access-Control-Allow-Origin");
            actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
        }
        base.OnActionExecuted(actionExecutedContext);
    }
}

тогда просто используйте его на своем Действие контроллера:

[AllowCors]
public IHttpActionResult Get()
{
    return Ok("value");
}

Я не ручаюсь за безопасность этого в целом, но это, вероятно, намного безопаснее, чем установка заголовков в интернете.config, так как таким образом вы можете применять их только так конкретно, как вам нужно.

и конечно это просто модифицировать выше, чтобы разрешить только определенные истоки, методы и т. д.


WEBAPI2: РЕШЕНИЕ. глобальный.асакс.cs:

var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);

в обозревателе решений щелкните правой кнопкой мыши api-project. В окне Свойства установите для параметра 'Анонимный Доступ' to включено !!!

надеюсь, это поможет кому-то в будущем.


Я только что испытал эту же проблему, пытаясь включить CORS глобально. Однако я узнал это тут работе, однако только тогда, когда запрос содержит Origin значение заголовка. Если вы опустите origin значение заголовка, ответ не будет содержать Access-Control-Allow-Origin.

я использовал плагин Chrome под названием DHC чтобы проверить мой запрос GET. Это позволило мне добавить Origin легко заголовка.


Я нашел этот вопрос, потому что у меня были проблемы с запросом опций, который большинство браузеров отправляют. Мое приложение маршрутизировало запросы опций и использовало мой IoC для создания множества объектов, а некоторые по разным причинам создавали исключения для этого странного типа запроса.

в основном положить в игнорировать маршрут для всех запросов опций, если они вызывают у вас проблемы:

var constraints = new { httpMethod = new HttpMethodConstraint(HttpMethod.Options) };
config.Routes.IgnoreRoute("OPTIONS", "{*pathInfo}", constraints);

Подробнее: остановить параметры обработки Web API запросы


надеюсь, это поможет кому-то в будущем. Моя проблема заключалась в том, что я следовал тому же учебнику, что и OP, чтобы включить global CORS. Тем не менее, я также установил правило CORS действия в моем AccountController.cs файл:

[EnableCors(origins: "", headers: "*", methods: "*")]

и получал ошибки о происхождении не может быть null или пустой строкой. Но ошибка произошла в глобальном масштабе.асакс.cs файл всех мест. Решение состоит в том, чтобы изменить его на:

[EnableCors(origins: "*", headers: "*", methods: "*")]

обратите внимание на * в источниках? Скучаю, вот что было. вызывает ошибку в глобальном.асакс.cs файл.

надеюсь, это кому-то поможет.