Utilizando o tipo HttpResponseMessage em serviços Web API
Embora conte com o padrão XML como uma de suas opções nativas para a serialização de dados, o ASP.NET Web API não suporta o uso deste formato em Actions cujo retorno seja um tipo anônimo ou dinâmico. A tentativa de realizar uma operação deste gênero resultará em erro (algo que não aconteceria ao se empregar JSON), limitando a princípio a utilização de XML apenas a referências criadas a partir de classes concretas.
Informações sobre tal problema podem ser encontradas no seguinte artigo:
Por mais que a situação levantada represente uma restrição, existe ainda assim uma alternativa: a utilização de instâncias do tipo HttpResponseMessage (namespace System.Net.Http) como retorno de Actions em serviços Web API.
Para demonstrar a classe HttpResponseMessage em ação será usada uma aplicação Web API descrita em:
OBSERVAÇÃO: o exemplo aqui apresentado foi criado a partir do Visual Studio Community 2015 Update 2, utilizando para tanto o .NET Framework 4.6.1.
Como primeiro ajuste será desativado o uso do formato JSON (Listagem 1). Ajustar para isto método Register do tipo WebApiConfig, de forma a remover da propriedade Formatters do objeto config a estrutura responsável pela serialização JSON:
[code language=”csharp” highlight=”11,12"]
using System.Web.Http;
namespace TesteHttpResponseMessage
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
…
config.Formatters.Remove(
config.Formatters.JsonFormatter);
}
}
}
[/code]
Listagem 1: Classe WebApiConfig
O tipo SimulacaoCotacao será utilizado para a geração de valores “fake” representando cotações de moedas estrangeiras como o dólar norte-americano (USD), o euro (EUR) e a libra esterlina (LIB), com isto acontecendo através do método ObterValorCotacao. Um objeto dinâmico corresponderá ao retorno de ObterValorCotacao, conforme consta na Listagem 2:
[code language=”csharp”]
using System;
using System.Linq;
using System.Dynamic;
namespace TesteHttpResponseMessage
{
public static class SimulacaoCotacao
{
private static readonly string[] MOEDAS_DISPONIVEIS =
{ “USD”, “EUR”, “LIB” };
public static bool MoedaValida(string siglaMoeda)
{
return MOEDAS_DISPONIVEIS.Contains(siglaMoeda);
}
private static double CalcularValorCotacao(
double valorBase,
int menorValorDecimal,
int maiorValorDecimal)
{
Random r = new Random();
return valorBase +
(((double)r.Next(menorValorDecimal,
maiorValorDecimal)) / 10000);
}
public static dynamic ObterValorCotacao(
string siglaMoeda)
{
DateTime dataAtual = DateTime.Now;
dynamic cotacao = new ExpandoObject();
cotacao.SiglaMoeda = siglaMoeda;
cotacao.Data = dataAtual.ToString(“dd/MM/yyyy”);
cotacao.Horario = dataAtual.ToString(“HH:mm”);
if (siglaMoeda == “USD”)
{
cotacao.NomeMoeda = “Dólar norte-americano”;
cotacao.ValorComercial = CalcularValorCotacao(3, 5000, 6000);
cotacao.ValorTurismo = CalcularValorCotacao(3, 6000, 7000);
}
if (siglaMoeda == “EUR”)
{
cotacao.NomeMoeda = “Euro”;
cotacao.Valor = CalcularValorCotacao(3, 9000, 9999);
}
if (siglaMoeda == “LIB”)
{
cotacao.NomeMoeda = “Libra esterlina”;
cotacao.Valor = CalcularValorCotacao(5, 0, 1000);
}
return cotacao;
}
}
}
[/code]
Listagem 2: Classe SimulacaoCotacao
Na Listagem 3 está a definição do tipo CotacaoController:
- Este Controller foi marcado com o atributo RouteAttribute (namespace System.Web.Http), sendo que o valor informado como parâmetro a este elemento indica a rota utilizada para consulta às cotações de moedas estrangeiras;
- A Action Get recebe como parâmetro a sigla da moeda a ser pesquisada. A cotação esperada é obtida por meio de uma chamada ao método ObterValorCotacao do tipo SimulacaoCotacao; este objeto é então convertido primeiro para o formato JSON e, depois, para o equivalente em XML via classe JsonConvert (namespace Newtonsoft.Json);
- Por fim, uma instância da classe HttpResponseMessage é criada. A propriedade Content deste objeto foi preenchida com uma referência do tipo StringContent (namespace System.Net.Http), com esta última recebendo como parâmetros a string XML a ser devolvida pela Action, o padrão de caracteres da resposta (UTF-8) e o tipo deste retorno (identificado pelo valor “application/xml”).
[code language=”csharp” highlight=”23–27"]
using System.Text;
using System.Net.Http;
using System.Web.Http;
using System.Xml.Linq;
using Newtonsoft.Json;
namespace TesteHttpResponseMessage.Controllers
{
public class CotacaoController : ApiController
{
[Route(“api/cotacao/{siglaMoeda}”)]
public HttpResponseMessage Get(string siglaMoeda)
{
siglaMoeda = siglaMoeda.ToUpper();
dynamic cotacao =
SimulacaoCotacao.ObterValorCotacao(siglaMoeda);
string valorJSON =
JsonConvert.SerializeObject(cotacao);
XDocument xml =
JsonConvert.DeserializeXNode(valorJSON, “Cotacao”);
return new HttpResponseMessage
{
Content = new StringContent(
xml.ToString(), Encoding.UTF8, “application/xml”)
};
}
}
}
[/code]
Listagem 3: Classe CotacaoController
OBSERVAÇÃO: a classe JsonConvert integra o package Newtonsoft.Json, o qual foi adicionado automaticamente durante a criação de um projeto baseado na tecnologia Web API.
Na Imagem 1 estão os resultados (em XML) de consultas às diferentes moedas previstas para o serviço de cotações:
Imagem 1. Exemplos de consultas às cotações
E concluo assim este post, no qual procurei demonstrar a utilização em aplicações Web API de retornos variáveis em XML. Informações adicionais podem ser encontradas na seção de Referências.
Referências
ASP.NET Web API
http://www.asp.net/web-api
HttpResponseMessage Class
https://msdn.microsoft.com/en-us/library/system.net.http.httpresponsemessage%28v=vs.118%29.aspx