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.Пдбс зависимость) это работает:

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

10 ответов:

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

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

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

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

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

WebApiConfig.cs

ключевым методом для вашего здесь является EnableCrossSiteRequests метод. Это все что нужно делать. Элемент 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 атрибут, который мы применили глобально. Элемент 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.конфигурации

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

<?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.конфигурации

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

<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 все современные браузеры отвечают глаголом OPTION, а затем следует фактический запрос. Это должно использоваться для запроса пользователя на подтверждение в случае запроса 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.

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

конфигурация системы.веб-сервер:

<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, это действительно намного проще, просто написать пользовательский атрибут Filter:

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. В окне Свойства установите для параметра 'Анонимный Доступ' до включено !!!

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

Я только что испытал эту же проблему, пытаясь включить 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);

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

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

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

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

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

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

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