c# - mvc - net core web api cors
Habilitar CORS en Web API 2 (6)
Tengo un cliente y un servidor ejecutándose en diferentes puertos. El servidor ejecuta Web API 2 (v5.0.0-rc1) .
Intenté instalar el paquete de compatibilidad entre origen de la API web Microsoft ASP.NET y lo habilité en WebApiConfig.cs
. Me da la función EnableCors()
, por lo que el paquete se instaló correctamente.
Aquí puede ver mi función Register()
en WebApiConfig.cs
:
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
}
GET
solicitudes GET
funcionan bien. Pero al enviar POST
, obtengo lo siguiente:
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.
Según Fiddler, solo envía la solicitud OPTIONS
. No emite el POST
después.
Así que estoy adivinando el config.EnableCors(cors);
en el WebApiConfig.cs
no está haciendo nada, lo que lleva al servidor a negar al cliente / navegador para enviar una solicitud POST
.
¿Tienes alguna idea de cómo resolver este problema?
EDITAR 05.09.13 Esto ha sido reparado en 5.0.0-rtm-130905
Última respuesta para referencia futura. Lo que funcionó para mí fue habilitarlo por nuget y luego agregar encabezados personalizados en web.config.
CORS funciona absolutamente bien en Microsoft.AspNet.WebApi.Cors
versión 5.2.2. Los siguientes pasos configuraron CORS como un amuleto para mí:
-
Install-Package Microsoft.AspNet.WebApi.Cors -Version "5.2.2"
// se ejecuta desde la consola del administrador de paquetes En Global.asax, agregue la siguiente línea: ANTES DE CUALQUIER REGISTRO DE VUELO MVC
GlobalConfiguration.Configure(WebApiConfig.Register);
En el método de registro
WebApiConfig
, tenga el siguiente código:public static void Register(HttpConfiguration config) { config.EnableCors(); config.MapHttpAttributeRoutes(); }
En web.config, el siguiente controlador debe ser el primero en la lista:
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
En el controlador derivado de ApiController
, agregue el EnableCorsAttribute
:
[EnableCors(origins: "*", headers: "*", methods: "*")] // tune to your needs
[RoutePrefix("")]
public class MyController : ApiController
Eso debería prepararte muy bien!
Como referencia, utilizar el [EnableCors()]
no funcionará si intercepta la [EnableCors()]
mensajes utilizando DelegatingHandler
. En mi caso, buscaba un encabezado de Authorization
en la solicitud y lo manejaba en consecuencia incluso antes de invocar el enrutamiento, lo que significaba que mi solicitud se procesaba antes en la canalización, por lo que [EnableCors()]
no tuvo efecto.
Al final encontré un ejemplo de clase CrossDomainHandler
(crédito para shaunxu para el Gist ) que maneja los CORS para mí en la tubería y para usarlo es tan simple como agregar otro controlador de mensajes a la canalización.
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);
}
}
}
Para usarlo, agréguelo a la lista de manejadores de mensajes registrados
config.MessageHandlers.Add(new CrossDomainHandler());
Todas las solicitudes de verificación previa realizadas por el navegador se manejan y transmiten, lo que significa que no tuve que implementar un [HttpOptions]
IHttpActionResult
en el controlador.
Definitivamente estoy abordando este problema con el enrutamiento de atributos. El problema se fixed partir de 5.0.0-rtm-130905. Pero aún así, puedes probar las compilaciones nocturnas que seguramente tendrán la solución.
Para agregar nightlies a su origen de paquete NuGet, vaya a Tools -> Library Package Manager -> Package Manager Settings
y agregue la siguiente URL bajo Package Sources
: http://myget.org/F/aspnetwebstacknightly
No necesité instalar ningún paquete. Solo un simple cambio en el web.config de su proyecto WebAPI funciona a la perfección:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
</system.webServer>
El crédito va a: Usar CORS en ASP.NET WebAPI sin ser un científico de cohetes
var cors = new EnableCorsAttribute("*","*","*");
config.EnableCors(cors);
var constraints = new {httpMethod = new HttpMethodConstraint(HttpMethod.Options)};
config.Routes.IgnoreRoute("OPTIONS", "*pathInfo",constraints);