André Alves de Lima

Talking about Software Development and more…

Como retornar XML em Controllers do ASP.NET Web API?

Meses atrás, quando eu estava escrevendo o meu artigo sobre live tiles para a revista .NET Magazine, topei com um problema muito chato. O mecanismo de atualização automática de live tiles do Windows Phone e Windows 8.1 requer que um XML seja hospedado em alguma URL. Esse XML contém todas as informações da nova tile que deve ser utilizada no aplicativo. Porém, para que tudo isso funcione corretamente, o XML deve seguir um padrão muito específico, e o serviço deve retornar justamente esse formato. E aí surgiu a dúvida: uma vez que você já tenha o conteúdo do XML em uma variável, como retornar XML “pronto” em Controllers do ASP.NET Web API?

Trabalhando com objetos serializáveis

Antes de começar, não sei se você sabe, mas, quando você retorna um objeto serializável pelo ASP.NET Web API, ele suporta nativamente os formatos JSON e XML. O tipo a ser retornado depende do que está definido no header do request. Por exemplo, o Internet Explorer “pede“, por padrão, um retorno em JSON. Já o Google Chrome, “pede” um retorno em XML.

Para exemplificar esse efeito, vamos criar um projeto do tipo “ASP.NET Web Application” selecionando o template “Web API“:

Dentro desse projeto, vamos criar uma nova classe extremamente simples, chamada “Pessoa“, com as propriedades “Nome” e “Sobrenome“. Crie essa classe dentro da pasta “Models” do projeto:

    public class Pessoa
    {
        public string Nome { get; set; }
        public string Sobrenome { get; set; }
    }

Feito isso, vamos criar um novo Controller que retornará uma instância de “Pessoa” no método GET. Para fazer isso, escolha a opção “Add Controller” dentro da pasta “Controllers“, escolha o tipo “Web API 2 Controller with read/write actions” e dê o nome de “PessoaController“:

Dentro desse novo Controller, apague todos os métodos criados, com exceção do “Get“, onde retornaremos uma instância simples da classe “Pessoa” que criamos anteriormente:

    public class PessoaController : ApiController
    {
        public Models.Pessoa Get()
        {
            return new Models.Pessoa { Nome = "André", Sobrenome = "Lima" };
        }
    }

Execute o projeto e acesse o endereço do Controller que, por padrão, seguirá este formato:

http://localhost:{PORTA}/api/pessoa

Se você acessar o endereço do Controller pelo Internet Explorer, veja que ele retornará um JSON:

Já se você acessar o mesmo endereço pelo Chrome, ele retornará um XML:

Você pode também utilizar o Fiddler para testar os dois tipos de retorno, como eu mostrei no meu artigo da semana passada.

Retornando XML a partir de uma string?

Até agora, tudo claro, não é mesmo? Se você estiver retornando um objeto serializável pela Web API, o retorno será em JSON ou XML, dependendo do que estiver especificado no header do request. Mas, e se você não estiver trabalhando com um objeto serializável? E se você já tiver uma string com o XML a ser retornado? O que acontece nesse caso? Vamos conferir.

Crie um novo Controller utilizando o nome “ExemploXMLController“. Para retornar um XML de uma string, a primeira ideia que veio na minha cabeça foi: vou retornar a string e acho que o Web API vai entender que estou retornando um XML e tudo vai funcionar perfeitamente. Ou seja, tentei retornar o XML dessa maneira:

    public class ExemploXMLController : ApiController
    {
        public string Get()
        {
            string xml =
                "<tagExterna>" +
                    "<tagInterna elemento=\"56\"/>" +
                "</tagExterna>";

            return xml;
        }
    }

Porém, ao acessar o endereço desse novo Controller, o comportamento ainda será o mesmo que observamos anteriormente com objetos serializáveis (afinal de contas, uma string é um objeto serializável). Ou seja, no Internet Explorer, o resultado foi um JSON com uma string dentro. No Chrome, o resultado foi um XML com uma string dentro!

Obviamente, esse não é o resultado que estávamos querendo. Depois de pesquisar um pouco, acabei encontrando uma ideia em uma discussão que eu achei no StackOverflow. A solução é, ao invés de retornarmos uma string, temos que retornar uma HttpResponseMessage. Com ela, temos total controle do formato que será retornado, veja só:

    public class ExemploXMLController : ApiController
    {
        public HttpResponseMessage Get()
        {
            string xml =
                "<tagExterna>" +
                    "<tagInterna elemento=\"56\"/>" +
                "</tagExterna>";

            return new HttpResponseMessage()
            {
                Content = new StringContent(
                    xml,
                    System.Text.Encoding.UTF8,
                    "text/xml"
                )
            };
        }
    }

E com isso, ao acessarmos o endereço do Controller tanto no Internet Explorer quanto no Chrome, o resultado será o XML que estávamos esperando:

Concluindo

Retornar XML em Controllers do ASP.NET Web API é muito simples caso você esteja utilizando objetos serializáveis. Nesse caso, o retorno será JSON ou XML dependendo do que estiver definido no header do request. Porém, se você já tiver uma string com o XML pronto (e não estiver retornando um objeto serializável), você precisa retornar uma HttpResponseMessage customizada onde você definirá o tipo de retorno como “text/xml“. E foi justamente isso que você aprendeu no artigo de hoje. Espero que seja útil caso você passe por essa situação no futuro.

Antes de me despedir, convido você a inscrever-se na minha newsletter. Ao fazer isso, você receberá um e-mail toda semana sobre o artigo publicado, ficará sabendo em primeira mão sobre o artigo da próxima semana e receberá também dicas “bônus” que eu só compartilho por e-mail. Além disso, você já deve ter percebido que eu recebo muitas sugestões de temas e eu costumo dar prioridade às sugestões vindas de inscritos da minha newsletter. Inscreva-se aqui ou utilizando o formulário logo abaixo.

Até a próxima!

André Lima

Newsletter do André Lima

* indicates required



Powered by MailChimp

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *