ASP.NET Web API - Criando um CRUD e consumindo em um domínio diferente. CORS, AJAX e JSONP [Parte 2]

Services & WebAPI

Neste post vamos conhecer alguns conceitos e entender o resultado de alguns testes bem como algumas limitações que nos levam ao uso de técnicas como CORS ou JSONP. Também vamos “tentar” consumir nosso serviço utilizando apenas HTML / JQuery, demonstrando como é possível realizar o consumo utilizando apenas código client side.

capa

 

Lembre-se, quando trabalhamos como WebAPI, estamos expondo dados via HTTP. Essa mecânica geralmente indica que nosso serviço vai ser utilizado por uma gama de diferentes clientes em potencial. Sendo assim, devemos entender algumas das nuances que envolvem o fornecimento e o consumo dentro deste cenário.

O cenário mais comum envolve a hospedagem do serviço em um determinado local (domínio) e o consumo do mesmo por clientes em locais (domínios) diferentes.

008

Para consumir nosso serviço que está exposto via HTTP, vamos trabalhar com requisições assíncronas no Ajax. Nada de diferente do utilizado atualmente.

Para exemplificar o que já foi dito, utilize a aplicação que construímos no post passado. Clique com o botão direito sobre o projeto e adicione um arquivo HTML chamado index.html. Com o arquivo criado insira o código abaixo:

006

Neste momento já estamos realizando a consulta dos dados utilizando Ajax. Note que estamos listando todos o Municípios lendo o retorno json de nossa requisição. O importante aqui é notar que nosso cliente (página HTML), está no mesmo domínio (localhost:56601) do serviço. Sendo assim estamos realizando o Request e Response de maneira transparente.

000

003

Agora utilize este mesmo arquivo HTML abrindo ele localmente. Você vai receber um erro como o descrito abaixo de presente.

002

Você pode pensar que o problema ocorre devido nossa página não estar hospedada em um servidor. OK, abra ela como uma projeto web site em uma nova instância do Visual Studio, ou crie na solução atual um novo projeto web e execute nosso exemplo.

001

Este erro indica erro indicando que o solicitante não é tem permissão para fazer o pedido. Vamos ver se o Fiddler tem algo mais a nos dizer:

localhost:56601

005

localhost:61139

004

Repare que ambas as chamadas retornam o resultado consultado, porém na chamada para o domínio diferente (localhost:61139) , nós temos um “Origin: null”.

 

Ajax

Estamos utilizando Ajax pois este tem a capacidade de realizar solicitações HTTP assíncronas utilizando o objeto HMLHttpRequest, ou seja, enquanto nossos usuários estão utilizando nossa interface estamos realizando o acesso a dados em segungo plano.

Estou tocando neste ponto pois é parte do cenário mais atual, onde nossos sites e aplicativos consomem cada vez mais recursos remotos, como nosso exemplo. No entanto, é aqui que as coisas complicam um pouco, já que vimos não ser possível realizar estas solicitações sem violar a política de segurança imposta pelos navegadores.

Isto ocorre devido um conceito em linguagens de programação do lado do cliente/navegador (como JavaScript), que permite o acesso a recursos no mesmo local (mesmo domínio), mas impede o acesso a recursos em diferentes domínios. Isso pode parecer sem sentido mas é um salva-vidas para proteger as nossas aplicações web contra uma variedade de ataques maliciosos.

007

Mesmo assim você pode querer expor sua WebAPI para outros sites, agora espere um pouco, se temos esta limitação o que fazer? Para solucionar nosso problema, vamos apelar para duas soluções: JSONP e CORS.

 

JSONP (JSON with Padding)

O JSONP nada mais é que um código javascript simples com prefixo que servirá de namespace para um objeto literal através de uma função. Ele aproveita que as tags <script> não sofrem restrição de domínio cruzado para solicitar o retorno dos dados dentro de uma nova tag <script>. Isto pode ser realizado utilizando o atributo src da tag para retornar um fluxo JSON.

Na verdade isso apenas inclui um monte de JSON em nossa página, o que não é muito útil se não for possível interagir com ele. É ai que entra o Padding. Pedimos para o servidor devolver nosso JSON em um wrapper (envolver) dentro de uma função utilizando callback.

Isso é muito bom, porém JSONP não trabalha com “os outros” verbos HTTP. Isso mesmo, apenas podemos utilizar JSONP para a realização de GET. Sendo assim vamos precisar implementar o CORS.

 

CORS (Cross Origin Resource Sharing)

Cross-origin resource sharing (CORS) ou compartilhamento de recursos de origem cruzada, é o mecanismo que permite ao JavaScript de uma página web para fazer um XMLHttpRequests para um domínio diferente do domínio de origem.

Tais pedidos "cross-domain" seriam proibidas pelo navegador web, por conta da política de segurança de origem. CORS define uma forma em que o navegador e o servidor podem interagir para determinar se devem ou não permitir o pedido de origem cruzada.

 

Implementação

Bom, vamos utilizar um simples site em HTML que está disponível para download CLICANDO AQUI!

Nosso site possui a seguinte estrutura de páginas:

    • index.html [Tela inicial, lista todos os municípios]
    • getbyuf.html [Busca todos os municípios de uma determianda UF]
    • getbycodigo.html [Busca o município dado seu Código]
    • post.html [Cria um Município]
    • put.html [Altera um Município]
    • delete.html [Deleta um Município]

Eu optei por criar tudo na mão e depois abrir pelo Visual Studio como um Web Site, mas sinta-se livre para executar localmente ou publicar no IIS para os testes. Se você navegar no site vai ver que não temos ainda nenhuma interação com nosso serviço. 

No próximo post vamos implementar nossa solução com as chamadas AJAX utilizando JSONP e CORS. Também vamos realizar algumas configurações em nosso serviço para tornar possível o consumo para os diversos clientes.

 

Até mais e bom estudo a todos!

Me Azul

Twitter: @vitormeriat

vitormeriat@gmail.com

vitor.pereira@studentpartner.com


Author's profile picture

Vitor is a computer scientist who is passionate about creating software that will positively change the world we live in.

MVP Azure - Cloud Architect - Data science enthusiast


5 minutes to read