2013-09-04 14 views
32

Mam klienta i serwer działający na różnych portach. Na serwerze działa Web API 2 (v5.0.0-rc1).Włącz CORS w Web API 2

Próbowałem zainstalować Microsoft ASP.NET Web API Cross-Origin Support package i włączyć go w WebApiConfig.cs. Daje mi to funkcję EnableCors(), więc pakiet został poprawnie zainstalowany.

Tutaj możesz zobaczyć moje Register() funkcję w WebApiConfig.cs:

public static void Register(HttpConfiguration config) 
{ 
    config.MapHttpAttributeRoutes(); 

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

GET wnioski działać prawidłowo. Ale podczas wysyłania POST, pojawia się następujący:

OPTIONS http://localhost:19357/api/v1/rooms? 404 (Not Found) angular.js:10159 
OPTIONS http://localhost:19357/api/v1/rooms? Origin http://localhost:8000 is not allowed by Access-Control-Allow-Origin. angular.js:10159 
XMLHttpRequest cannot load http://localhost:19357/api/v1/rooms. Origin http://localhost:8000 is not allowed by Access-Control-Allow-Origin. 

Zdaniem Skrzypka to tylko wysyła żądanie OPTIONS. Po upływie tego czasu nie wydaje on numeru POST.

Zgaduję, że config.EnableCors(cors); w WebApiConfig.cs nic nie robi, co prowadzi do odmowy klientowi/przeglądarce wysłania zapytania o numer POST.

Czy masz pojęcie, jak rozwiązać ten problem?

EDIT 09/05/13 ten został naprawiony w wersji 5.0.0-RTM-130905

+0

Dzięki za pytanie i odpowiedź, które zostały naprawione w wersji 5.0.0-rtm. Gdzie mogę uzyskać wersję RTM? – Jaans

+1

'Narzędzia -> Menedżer pakietów bibliotecznych -> Ustawienia menedżera pakietów" i dodaj następujący adres URL w sekcji "Źródła pakietów": http://www.myget.org/F/aspnetwebstacknightly/ – Gaui

Odpowiedz

5

Jestem zdecydowanie uderzanie this issue z atrybutem routingu. The issue był fixed od 5.0.0-rtm-130905. Ale nadal możesz wypróbować wersję nightly builds, która z pewnością będzie miała poprawkę.

Aby dodać nightly do źródła pakietu Nuget, przejdź do Tools -> Library Package Manager -> Package Manager Settings i dodaj następujący adres URL pod Package Sources: http://myget.org/F/aspnetwebstacknightly

32

CORS działa absolutnie w porządku w Microsoft.AspNet.WebApi.Cors wersji 5.2.2. Poniższe kroki skonfigurowany CORS jak urok dla mnie:

  1. Install-Package Microsoft.AspNet.WebApi.Cors -Version "5.2.2" // run z konsoli menedżera pakietów
  2. W Global.asax dodaj następujący wiersz: przed jakimkolwiek MVC DROGA REJESTRACJE

    GlobalConfiguration.Configure(WebApiConfig.Register); 
    
  3. W sposobie WebApiConfig Register mają następujące oznaczenia:

    public static void Register(HttpConfiguration config) 
    { 
        config.EnableCors(); 
        config.MapHttpAttributeRoutes(); 
    } 
    

W web.config następujący przewodnik musi być pierwszy w rurociągu:

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

W regulatorze pochodzącego z ApiController dodaj EnableCorsAttribute:

[EnableCors(origins: "*", headers: "*", methods: "*")] // tune to your needs 
[RoutePrefix("")] 
public class MyController : ApiController 

Że powinien Cię ładnie ustawić!

+0

Tak jak powiedziałem, zostało to naprawione w wersji 5.0. 0-rtm-130905 :) – Gaui

+0

Pewnie, właśnie dodałem kroki do kompletności :) – dotnetguy

+0

OK dziękuję :) – Gaui

4

Późna odpowiedź na przyszłość. To, co dla mnie działało, to włączenie go przez nuget, a następnie dodanie niestandardowych nagłówków do pliku web.config.

+0

Dzięki! Instalowanie za pomocą konsoli zarządzania pakietami nie działało, więc spróbowałem go przez interfejs NuGet i zaktualizowałem referencje projektu automatycznie i teraz działa dobrze. – user441058

9

Nie trzeba instalować żadnego pakietu. Wystarczy prosta zmiana w pliku web.config twojego projektu WebAPI jest wielka praca:

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

zasługa: Using CORS in ASP.NET WebAPI Without Being a Rocket Scientist

+3

To działa, ale nie działa, jeśli chcesz określić CORS na podstawie kontrolera/trasy. – Gaui

+1

Jak sugerujesz tę samą sztuczkę, której użyłem do mojego projektu, +1! Nienawidzę pakietu Nuget, całkowicie zbędnego! Happy Coding bro! –

+0

Oto kolejna uwaga dla tego podejścia: dzięki OWIN/Katana możesz nie być hostem w IIS, w takim przypadku nie ma web.config - dlatego pakiet Microsoft.AspNet.WebApi.Cors jest do zrobienia. – dotnetguy

2

Dla odniesienia, stosując podejście [EnableCors()] nie będzie działać, jeśli przechwycić wiadomość Pipeline użyciu DelegatingHandler. W moim przypadku sprawdzałem nagłówek Authorization w żądaniu i postępowałem z nim odpowiednio przed wywołaniem routingu, co oznaczało, że moje zgłoszenie zostało przetworzone wcześniej w przygotowaniu, więc [EnableCors()] nie przyniosło efektu.

W końcu znalazłem przykład CrossDomainHandler class(kredyt do shaunxu dla Gist) który obsługuje ten CORS dla mnie w rurociągu i wykorzystać go jest tak proste jak dodanie kolejnego obsługi wiadomość do rurociągu.

public class CrossDomainHandler : DelegatingHandler 
    { 
     const string Origin = "Origin"; 
     const string AccessControlRequestMethod = "Access-Control-Request-Method"; 
     const string AccessControlRequestHeaders = "Access-Control-Request-Headers"; 
     const string AccessControlAllowOrigin = "Access-Control-Allow-Origin"; 
     const string AccessControlAllowMethods = "Access-Control-Allow-Methods"; 
     const string AccessControlAllowHeaders = "Access-Control-Allow-Headers"; 

     protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
     { 
      bool isCorsRequest = request.Headers.Contains(Origin); 
      bool isPreflightRequest = request.Method == HttpMethod.Options; 
      if (isCorsRequest) 
      { 
       if (isPreflightRequest) 
       { 
        return Task.Factory.StartNew(() => 
        { 
         HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK); 
         response.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First()); 

         string accessControlRequestMethod = request.Headers.GetValues(AccessControlRequestMethod).FirstOrDefault(); 
         if (accessControlRequestMethod != null) 
         { 
          response.Headers.Add(AccessControlAllowMethods, accessControlRequestMethod); 
         } 

         string requestedHeaders = string.Join(", ", request.Headers.GetValues(AccessControlRequestHeaders)); 
         if (!string.IsNullOrEmpty(requestedHeaders)) 
         { 
          response.Headers.Add(AccessControlAllowHeaders, requestedHeaders); 
         } 

         return response; 
        }, cancellationToken); 
       } 
       else 
       { 
        return base.SendAsync(request, cancellationToken).ContinueWith(t => 
        { 
         HttpResponseMessage resp = t.Result; 
         resp.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First()); 
         return resp; 
        }); 
       } 
      } 
      else 
      { 
       return base.SendAsync(request, cancellationToken); 
      } 
     } 
    } 

wykorzystać go dodać go do listy zarejestrowanych obsługą komunikatów

config.MessageHandlers.Add(new CrossDomainHandler()); 

Wszelkie inspekcji wstępnych zapytań przez przeglądarkę są obsługiwane i przekazywane, co oznacza, że ​​nie należy wdrożyć [HttpOptions]IHttpActionResult metody na kontrolerze.

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

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