Hola a todos, hoy vamos a intentar aclarar la problemática que surge al intentar acceder a recursos de un servicio desde otro dominio, problema que tiene fácil solución: La habilitación de CORS en la Web API.

En el ejempo, vamos a habilitarlo para permitir que se hagan llamadas AJAX embebidas en JavaScript, desde direcciones (dominios) diferentes a la del servidor. Lo cual es un agujero de seguridad y de privacidad en muchos casos, pero que es imprescindible para una API pública (se debería implementar seguridad de acceso, para evitar problemas).

Como funciona CORS

CORS se basa en dos peticiones fundamentales,  un cross-orgin-request y un preflight-request, los cuales expondremos de una forma sencilla a continuación.

 

Cross-Origin-Request consiste básicamente en el envío por parte de quien solicita un recurso compartido de una cabecer Origin, con el valor del cliente que desea consumir ese recurso. Por parte del servidor,  se hace la lectura de esa cabecera y se comprueba que puede utilizar un determinado recurso. Una vez comprobado, el servidor en la respuesta, envía una cabecera Access-Control-Allow-Origin con el valor del cliente admitido, valor no case sensitive que tienen que coincidir con el emisor. En realidad, este proceso se podría complicar un poco más incluyendo credenciales, no obstante, nosotros no lo utilizaremos, si alguien quiere ampliar la información puede hacerlo aquí.

 

Preflight-Request es un request utilizado para, a mayores de garantizar el origen , ver que métodos pueden utilizarse.

Atributos de EnableCors

 

Hay tres atributos pasar al EnableCors:

1.  Origins: Puede configurar más de un valor orígenes separados por comas.Se puede incluir un dominio o url(“www.dominio.com”) o poner *, lo que permite un acceso público.

2.   Solicitar Encabezados: Los especifica parámetros Solicitud de cabecera que se permiten Solicitar cabeceras. Para permitir que el encabezado de cualquier valor establecido en *

3.   Métodos de HTTP: Los parámetros métodos especifica que se permiten métodos HTTP para acceder al recurso. Para permitir acceso a todos los métodos, utilizan el valor”*”. Establecer lo contrario separada por comas nombre del método para permitir que un conjunto de métodos para acceder a los recursos.

Poniendo de que todos juntos, puede habilitar CORS de dos orígenes, para todas las cabeceras, y luego publicar y obtener operaciones, como se muestra en el listado a continuación:

 [EnableCors(origins: “http://localhost:5901,http://localhost:8768”, headers: “*”, methods: “post,get”)]

    public class ClassesController : ApiController

    {

CORS puede ser habilitado por action, por controlador o global para todos los controladores de la Web API.

Por Action

Para habilitar CORS para una sola action, coloque el atributo [EnableCors] por encima del metodo de la action. A continuacion se puede observar un ejemplo.

Luego agregue el atributo [EnableCors] al controlador deseado:

1

2

3

4

5

6

7

8

9

10

11

using System.Net.Http;

using System.Web.Http;

using System.Web.Http.Cors;

namespace WebService.Controllers

{

    [EnableCors(origins: “*”, headers: “*”, methods: “*”)]

    public class TestController : ApiController

    {

Por Controller

Para habilitar CORS a nivel del controller, debe colocar el attributo [EnableCors] por encima del nombre de la clase. Cuando habilita CORS en un controlador, este se aplica para todas sus actions. Para poder deshabilitar CORS en una action, coloque el parametro [DisableCors] en el action. Por ejemplo:

1

2

3

4

5

6

7

8

9

10

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

public class ItemsController : ApiController

{

    public HttpResponseMessage GetAll() { … }

    public HttpResponseMessage GetItem(int id) { … }

    public HttpResponseMessage Post() { … }

    [DisableCors]

    public HttpResponseMessage PutItem(int id) { … }

}

Globalmente

Para habilitar CORS para todos los controllers en la aplicación, pase una instancia deEnableCorsAttribute al metodo EnableCors del config:

1

2

3

4

5

6

7

8

9

public static class WebApiConfig

{

    public static void Register(HttpConfiguration config)

    {

        var cors = new EnableCorsAttribute(“www.example.com”, “*”, “*”);

        config.EnableCors(cors);

        // …

    }

}

 

 

Implementando CORS en Web API

 

1.   INSTALAR NUGET

La forma más sencilla de habilitar CORS es utilizando las capacidades de NuGet para localizar e instalar el código necesario. Así pulso con el botón derecho del ratón encima del icono de la solución y selecciono, en el menú contextual que obtengo, la opción de “Administrar paquetes NuGet de la solución…”.

En la ventana que se abre, escojo “Online” en las opciones del menú vertical de la izquierda y escribo en la casilla de búsqueda en la esquina superior derecha la palabra “cors”. Después de un ratito – dependiendo de la velocidad de conexión a la Red – me aparecen varios resultados de entre los cuales escojo “Microsoft ASP.NET Web API 2.x Cross-Origin Support”, y pulso en el botón de “Instalar”.

 

2.   Habilitar CORS en la solución

En el  proyecto WebApi, abrimos el archivo App_Start/WebApiConfig.cs, y agreguamos el siguiente codigo al metodo WebApiConfig.Register.

Luego agregue el atributo [EnableCors] al controlador deseado:

  1. using System.Net.Http;
  2. using System.Web.Http;
  3. using System.Web.Http.Cors;
  4. namespace WebService.Controllers
  5. {
  6.     [EnableCors(origins: “*”, headers: “*”, methods: “*”)]
  7.     public class TestController : ApiController
  8.     {

Para el parametro origins, utilice la URL que desea permitir que ejecute el controlador. Esto permite los requests cross-domain desde un cliente con otro dominio, en nuestro caso lo hemos dejado con acceso publico.

3.   Habilitar Cabeceras en el Controller.

 

 

 

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Net.Http;
  6. using System.Web.Http;
  7. using System.Web.Http.Cors;
  8. namespace WebApi.Controllers
  9. {
  10.  [EnableCors(origins: “http://localhost:53029”, headers: “*”, methods: “*”)]     public class TestController : ApiController     {
  11.       . . .