ASP.NET Web API - Como funciona o Content Negotiation

Services

CNNos posts anteriores (ASP.NET Web API – Criando e consumindo dados [Parte 1], [Parte 2] e ASP.NET Web API – Base Architecture), falamos sobre os componentes e recursos disponíveis no WebAPI. Dentre eles o Content Negotiation (Negociação de Conteúdo), que é o mecanismo do WebAPI que permite ao servidor web devolver o mesmo conteúdo, utilizando a mesma URL mas em formatos diferentes.  Neste post, vamos realizar alguns exemplos e focar em entender como funciona este, que é um dos recursos mais interessantes e importantes do ASP.NET Web API.

Realmente tenho notado a importância do Content Negotiation. Não só por ter tido …

Os exemplos deste post podem ser baixados no link ao final do artigo.

 

O que é o Content Negotiation e qual seu papel no WebAPI

Estamos falando de uma especificação HTTP que foi definida na RFC 2616.Este documento define que o Content Negotiation é o processo de selecionar a melhor representação de conteúdo para uma determinada resposta quando houver múltiplas representações disponíveis. Neste caso, qualquer resposta que contém em seu corpo uma entidade pode ser objeto de negociação incluindo respostas de erro.

Já no WebAPI o Content Negotiation é o algoritmo utilizado para determinar com base na requisição do cliente, qual o media type formatter deve ser utilizado na resposta. Quando falamos em .NET, ele realmente decide como enviar o objeto CLR para o cliente através do protocolo HTTP.

Um passo fundamental para entender o Content Negotiation é saber sobre os seus dois pilares:

    • Media type – Definido pela W3C como campos do cabeçalho a fim de fornecer tipos de dados e tipos de negociação;
    • Media type formatter – É a classe responsável por ler e escrever um objeto CLR do ou para o corpo da solicitação o requisição. Dependendo do sentido do fluxo HTTP.

Existem dois resultados possíveis para a negociação de conteúdo: O cliente e o servidor podem ou não concordar com o formato. Caso haja discordância quanto ao formato, cabe ao cliente realizar a ação, como por exemplo, registrar o erro.

Outro ponto importante a se considerar são os cabeçalhos envolvidos no processo. Para trabalhar com Content Negotiation no WebAPI vamos precisar constantemente destes dois cabeçalhos:

    • Accept
    • Content-Type

 

Iniciando no Content Negotiation

Se você estiver implementando negociação de conteúdo na mão, a maneira mais simples será capturar os parâmetros HTTP GET e mudar os filtros de entrada e saída para o formato escolhido, como no exemplo abaixo onde o conteúdo é entre em XML e JSON.

Untitled

Além desta implementação é possível criar um interprete de acordo com a extensão do recurso. O recurso é o mesmo que o visto anteriormente mas requer lógica do lado do servidor. O lado bom é que esta abordagem nos permite definir diferentes controladores que serão chamados de acordo com a extensão do recurso.

Se você leu os posts anteriores já deve estar notando o papel do WebAPI dentro desta necessidade.

 

Content Negotiation no Web API

Agora vamos partir para um pouco de código. Para entender melhor sobre o Content Negotiation. Vamos utilizar a aplicação que construímos no ASP.NET Web API – Criando e consumindo dados [Parte 1] e que pode ser baixado CLICANDO AQUI! 

Agora que você já tem a aplicação rodando, vamos repassar algumas informações: Neste exemplo estamos utilizando um Entity Data Model apontando para o banco de dados Northwind. Nosso exemplo foi construído baseado na tabela Customer. Também fiz algumas alterações no layout mas o código completo está publicado no final do post.

Agora, vamos para Views, Home e Index.cshtml. Neste arquivo vamos inserir o seguinte código na tag header vamos adicionar a chamada para o Jquery e o código abaixo que chama o cliente WebAPI.

Untitled

O código acima utiliza a função $.ajax() do JQuery para realizar a chamada ao cliente WebAPI. Notem que temos um objeto client que armazena todas as configurações necessárias para chamar nossa WebAPI. Neste primeiro exemplo vamos trabalhar com os valores padrão, sendo assim não é necessário definir os cabeçalhos Accept e Content-Type.

Na função lerResultadoJSON(), passamos o resultado da solicitação quando a mesma ocorrer com sucesso. O resultado será renderizado em uma tabela dentro de uma div container que você pode criar dentro da div body do nosso exemplo.

Como já dito anteriormente, o formato padrão com o qual o WebAPI trabalha é o JSON, e nossa função trata o retorno como sendo uma matriz JSON, percorrendo cada elemento e montando a tabela com os resultados pesquisados.

A função exibirError() é responsável por “exibir” o erro e seu código caso ocorra qualquer falha durante a chamada do serviço.

Rode a aplicação e o resultado será como se segue:

json

Por motivos de espaço não estou exibindo todos os resultados ok?

Vamos olhar para nossa requisição e resposta:

headersjson

Repare que nosso cabeçalho Accept não contem valor. Já na resposta o valor de retorno é o padrão JSON, como podemos ver na aba Preview.

previewjson

Agora vamos brincar com o Content Negotiation. Em nosso código JQuery, altere o código exatamente como o descrito abaixo:

9898

Neste trecho de código apenas inseri a seguinte linha: client.headers = { "accept": "application/xml;charset=utf-8" }; e alterei criei uma chamada para uma função lerResultadoXML().

Com apenas este cabeçalho, estamos dizendo para o WebAPI para enviar os dados em formato XML. Note que agora vamos precisar criar uma função específica para exibir os dados em XML. Insira o código abaixo para a função lerResultadoXML(), que vai tratar o XML de resposta exibindo os dados corretamente.

lerxml

Para este exemplo, alterei as colunas a fim de exibir valores diferentes para facilitar na visualização do recurso que acabamos de alterar. O resultado será o seguinte:

xml

Se olharmos para nossa requisição e reposta veremos que nosso cabeçalho Accept solicita que a resposta seja em XML. Nosso Content-Type está marcado como JSON por padrão, mesmo não informando este valor no objeto client. Já na resposta nosso Content-Type está setado com o formato XML.

headersxml

previewxml

Se apenas utilizando o cabeçalho Accept conseguimos o resultado esperado, qual a necessidade do cabeçalho Content-Type?

Este cabeçalho é utilizado para quando o formato solicitado para a resposta no cabeçalho Accept não pode ser entregue pelo servidor. Vamos a um exemplo prático.

Altere o código JQuery para:

6666666

Note que no objeto client inserimos a propriedade contentType definido o formato como JSON. Já em headers alteramos nosso cabeçalho inserindo um valor inválido xml123. Ao executar nossa aplicação não vamos ver nenhum Customer exibido na tela, mas ao analisar o nossa requisição vamos ver que houve uma resposta 200 – OK.

headerscontent

Note em Request Headers que o nosso pedido foi realizado apontando para o formato inválido xml123, porém na resposta o formato utilizado foi o JSON. Para verificar a veracidade desta informação, basta trocar a chamada de sucesso para client.success = lerResultadoJSON; e os resultados serão apresentados na tela corretamente.

 

Como Assim?

Para que os exemplos que postei aqui possam ocorrer com sucesso, foram executados os seguintes passos:

  1. Mapeamento do tipo de mídia – Mapeia o tipo de mídia a ser utilizada na requisição;
  2. Aceitação dos cabeçalhos emitidos pelo cliente – Verifica os cabeçalhos da solicitação para que o pedido seja validado;
  3. Inspeção do tipo de conteúdo solicitado – Inspeciona o tipo de conteúdo solicitado já que o mesmo pode um tipo de conteúdo específico. Neste ponto cabe ao MediaTypeMappings a verificação do cabeçalho Accept;
  4. Verificar se o formatador pode serializar o tipo de conteúdo para a resposta – O Content Negotiation varre sua coleção de formatadores até encontrar um que possa tratar o conteúdo da resposta adequadamente.

 

O código fonte pode ser baixado CLICANDO AQUI!

Conclusão

Com isso concluímos aqui nossa visão sobre o Content Negotiation no ASP.NET Web API. No próximo post vou mostrar como consumir o Web API realizando um CRUD apenas com HTML e JQuery.

 

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


8 minutes to read