Sie sind auf Seite 1von 63

27/06/2016

Minhacoleo

Minha coleo

Este documento fornecido "no estado em que se encontra". As informaes e ideias expressas neste documento, inclusive referncias a URLs e a outros sites da Internet,
podem ser alteradas sem aviso prvio. Este documento no lhe concede nenhum direito legal sobre nenhuma propriedade intelectual ou sobre produtos ou nomes de
produtos da Microsoft. Voc pode copiar e usar este documento para suas finalidades internas e de referncia. Voc pode modificar este documento para suas finalidades
internas e de referncia. 2016 Microsoft. Todos os direitos reservados. Termos de uso https://msdn.microsoft.com/cc300389.aspx | Marcas comerciais
http://www.microsoft.com/library/toolbar/3.0/trademarks/enus.mspx

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

1/63

27/06/2016

Minhacoleo

Table Of Contents
Captulo 1
Web Criando e Consumindo Web API Parte 1
Web Criando e Consumindo Web API Parte 2
Web Criando e Consumindo Web API Parte 3
Web Criando e Consumindo Web API Parte 4
Web Criando e Consumindo Web API Parte 5
ASP.NET Web API HTTP, REST e o ASP.NET
ASP.NET Web API Estrutura da API
ASP.NET Web API Roteamento
ASP.NET Web API Hosting
ASP.NET Web API Consumo
ASP.NET Web API Formatadores
ASP.NET Web API Segurana
ASP.NET Web API Testes e Tracing
ASP.NET Web API Estensibilidade e Arquitetura

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

2/63

27/06/2016

Minhacoleo

Captulo 1
Web Criando e Consumindo Web API Parte 1
Mauricio Junior

Setembro 2013
Ol pessoal, este artigo eu vou falar e mostrar como criar um Web API e a parte 2 eu vou focar em consumir atravs do C# esse Web API. Se voc ainda no sabe o
que Web API, leia alguns artigos anteriores publicados no site www.ecode10.com e www.mauriciojunior.org. O Web API veio para entrar no lugar do Web Service
que mais pesado, pesado para consumir ou trafegar na rede de Internet.

Links para analisar:


http://ecode10.com/artigo/1612/CursogratisdeAplicativoHTML5usandoASP.NETWebAPIejQuery
http://ecode10.com/artigo/1707/TecnologiaWebApi

Requisito:
Ferramenta: Visual Studio 2012
Linguagem: C#.NET
Tecnologia: Web API, MVC e ASP.NET.
Banco de dados: SQL Server 2008
Conexo com banco de dados: Entity Framework
Nesta parte 1, eu vou montar as classes de banco de dados usando Entity Framework criado pela Microsoft com o objetivo de conectar ao banco SQL Server 2008. O
primeiro passo para criar um Web API comea na criao do projeto. Agora voc no cria mais um Web Project, voc cria um Projeto do tipo Web API.
Primeiro voc escolhe a linguagem do lado esquero, depois o tipo do projeto que Web e depois o ASP.NET MVC 4 Web Application. Coloque um nome e confirme o
endereo onde ser gravado. Figura 1.

Figura 1 Criando o projeto


Confirmado o nome e o endereo, clique no boto OK, outra tela aparece para voc escolher o template do projeto. Nela voc escolhe a opo Web API. Veja a figura
2.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

3/63

27/06/2016

Minhacoleo

Figura 2 Escolhendo o template do projeto


Clique no boto OK e todo o projeto criado. At agora s temos o template funcionando, nada de conexo nem classes criadas ainda. necessrio criar classe para
conexo com o banco e classes para gerar as tabelas do banco de dados.
Antes de qualquer alterao no template criado, vamos passar para o arquivo de configurao e alterar a string de conexo com o banco de dados. O template vem
com uma string default, como o nosso caso criar um projeto Web API onde o banco de dados j est pronto, vamos mudar essa string de conexo. Listagem 1.
Listagem 1 String de conexo
C#
<!<addname="DefaultConnection"connectionString="DataSource=(LocalDb)\v11.0;InitialCatalog=aspnetMVCTeste
20130401162929;IntegratedSecurity=SSPI;AttachDBFilename=|DataDirectory|\aspnetMVCTeste20130401162929.mdf"
providerName="System.Data.SqlClient"/>>
<addname="MeuContext"connectionString="DataSource=Servidor;InitialCatalog=dbWebApi;UserId=usuario;Password=senha;"
providerName="System.Data.SqlClient"/>
Note que na listagem 1, a string que veio no template foi comentada e uma outra foi criada com o nome de MeuContext. Precisamos agora criar uma classe
chamada MeuContext dentro da pasta Model do projeto. Para criar uma classe dentro da pasta, clique com o boto direito em cima da pasta e siga os passos da
Figura 3.

Figura 3 Criando classe dentro da pasta.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

4/63

27/06/2016

Minhacoleo

Essa classe precisa extender de DbContext, indicando o nome de MeuContext.cs. O banco de dados chama dbWebAPI informado na conexo e no arquivo de
configurao. Figura 4.

Figura 4 Criando a classe MeuContext.


A classe precisa ser alterada em alguns aspectos, para isso temos a listagem 2.
Listagem 2 Classe MeuContext.
C#
usingSystem.Data.Entity;
namespaceMVCTeste.Models
{
publicclassMeuContext:DbContext
{
publicMeuContext():base("name=MeuContext")
{
}
}
}
Note que a listagem 2 possui a base de extenso no construtor da classe basename=MeuContext indicando o nome colocado no arquivo de configurao. Pronto,
agora temos a classe de conexo com o banco de dados usando o Entity Framework e o banco de dados SQL Server 2008. Lembrese que o banco j est pronto com
suas respectivas tabelas.
A primeira tabela que vou abordar a de usurios. O banco de dados tem uma tabela chamada Usuarios, precisamos criar uma classe chamada Usuario e depois
vamos indicar na classe de conexto. Utilize os passos da figura 3 para gerar uma classe chamada Usuario.cs dentro da pasta Model. O banco de dados possui apenas
dois campos, um do tipo Int e outro String.
Tabela: Usuarios
Campos: Id, Nome.
J que temos dois campos dentro da tabela de usurio, vamos criar uma classe de usurio com duas propriedades iguais aos valores das tabelas. Uma dessas
propriedades ser chave da tabela, crie a classe dentro da pasta Model. Listagem 3.
Listagem 3 Classe de usurio
C#
usingSystem;
usingSystem.Collections.Generic;
usingSystem.ComponentModel.DataAnnotations;
usingSystem.Linq;
usingSystem.Web;
namespaceMVCTeste.Models
{
publicclassUsuario
{
[Key]

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

5/63

27/06/2016

Minhacoleo
publicInt32Id{get;set;}
publicStringNome{get;set;}
}
}

Pronto, o nosso trabalho est quase pronto. Compile todo o projeto e veja se tem algum erro, no deixe erro no projeto para pode gerar a controller. Depois disso,
vamos adicionar um controle de usurio, responsvel por inserir, alterar, excluir e pesquisar no banco de dados SQL Server. Em vez de criarmos um controle MVC,
vamos criar um controle do tipo Web API pedindo para criar todos os mtodos.
Clique com o boto direito em cima da pasta Controller, escolha a opo Add e depois Controller. Uma tela aparece para que seja digitado e escolhidas algumas
opes. Figura 5.

Figura 5 Criando controle de usurio


Digite o nome UsuarioControler no campo controller name, escolha o template API controller with read/write actions, usando Entity Framework, escolha na opo
Model class a classe Usuario e no campo Data context class a opo Usuario.
Depois de clicar no boto OK, toda estrutura criada de forma automtica pela ferramenta Visual Studio 2012. Todos os mtodos foram criados na classe
UsuarioController.cs, veja na listagem 5.
Listagem 5 Controller de usurio criada.
C#
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Data;
usingSystem.Data.Entity;
usingSystem.Data.Entity.Infrastructure;
usingSystem.Linq;
usingSystem.Net;
usingSystem.Net.Http;
usingSystem.Web;
usingSystem.Web.Http;
usingMVCTeste.Models;
namespaceMVCTeste.Controllers
{
publicclassUsuarioController:ApiController
{
privateMeuContextdb=newMeuContext();
//GETapi/Usuario
publicIEnumerable<Usuario>GetUsuarios()
{
returndb.Usuarios.AsEnumerable();
}
//GETapi/Usuario/5
publicUsuarioGetUsuario(intid)
{
Usuariousuario=db.Usuarios.Find(id);
if(usuario==null)
{
thrownewHttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
returnusuario;
}
//PUTapi/Usuario/5
publicHttpResponseMessagePutUsuario(intid,Usuariousuario)
{
if(!ModelState.IsValid)

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

6/63

27/06/2016

Minhacoleo
{
returnRequest.CreateErrorResponse(HttpStatusCode.BadRequest,ModelState);
}
if(id!=usuario.Id)
{
returnRequest.CreateResponse(HttpStatusCode.BadRequest);
}
db.Entry(usuario).State=EntityState.Modified;
try
{
db.SaveChanges();
}
catch(DbUpdateConcurrencyExceptionex)
{
returnRequest.CreateErrorResponse(HttpStatusCode.NotFound,ex);
}
returnRequest.CreateResponse(HttpStatusCode.OK);
}
//POSTapi/Usuario
publicHttpResponseMessagePostUsuario(Usuariousuario)
{
try
{
if(ModelState.IsValid)
{
db.Usuarios.Add(usuario);
db.SaveChanges();
HttpResponseMessageresponse=Request.CreateResponse(HttpStatusCode.Created,usuario);
response.Headers.Location=newUri(Url.Link("DefaultApi",new{id=usuario.Id}));
returnresponse;
}
else
{
returnRequest.CreateErrorResponse(HttpStatusCode.BadRequest,ModelState);
}
}
catch(Exceptionex)
{
throwex;
}
}
//DELETEapi/Usuario/5
publicHttpResponseMessageDeleteUsuario(intid)
{
Usuariousuario=db.Usuarios.Find(id);
if(usuario==null)
{
returnRequest.CreateResponse(HttpStatusCode.NotFound);
}
db.Usuarios.Remove(usuario);
try
{
db.SaveChanges();
}
catch(DbUpdateConcurrencyExceptionex)
{
returnRequest.CreateErrorResponse(HttpStatusCode.NotFound,ex);
}
returnRequest.CreateResponse(HttpStatusCode.OK,usuario);
}
protectedoverridevoidDispose(booldisposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}

O resultado final lindo, como diz alguns amigos. Compile e clique F5 para rodar a aplicao. Acrescente no endereo da URL o /api/usuario e automaticamente
aparece o XML pronto no browser. No caso de abrir pelo browser, o dado retornado vem em XML, se for usado outro cliente, pode ser usado o Json. A figura 6
mostra os dados buscados diretamente do banco de dados.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

7/63

27/06/2016

Minhacoleo

Figura 6 Resultado buscado do banco de dados.


Bom, eu vou parar por aqui. Primeiro para no ficar to grande e segundo para no ficar cansativo. Espero que o seu projeto tenha dado certo como o meu e que no
final os valores do banco de dados apaream na tela.
Esse padro Web API to legal por utilizar Json que pode ser consumido por qualquer aplicativo, incluindo o servio mvel como no smartphone, tv digital ou tablet.
Os dados so importantes e so buscados de um mesmo local atravs do Web API com Json.

| Home | Artigos Tcnicos | Comunidade

2016 Microsoft

Criando e Consumindo Web API Parte 2


Mauricio Junior

Setembro 2013
Ol pessoal, hoje eu vou falar de Web API parte 2 da forma bem simples e fcil. No artigo anterior criamos a parte do banco de dados e exportamos os dados em
forma de XML ou Json. Agora vamos consumir esse Web API usando a linguagem C# .NET.
Antes de comear a falar da parte 2, peo para que leia a parte 1 localizada no endereo abaixo. Essa parte 2 exatamente continuao da parte 1 e sem ela voc no
vai entender o que falarei aqui.
Artigo anterior: http://msdn.microsoft.com/ptbr/library/dn450975.aspx

Utilizado neste artigo:


Ferramenta Visual Studio 2012
Linguagem de programao C#
Tecnologia utilizada, WebForm, Web API, Rest e Json.
Nessa parte 2 vou mostrar como pegar os dados do Web API de forma correta preencher um GridView ou DataList dinamicamente, ou seja, vamos usar o mtodo GET.
Outros artigos eu mostro como fazer PUT, DELETE e POST dos dados.
Voc pode consumir o mtodo GET usando o mesmo projeto, mas o ideal criar um novo projeto do tipo WebForm para consumir o Rest. Como falei anteriormente
na parte 1, o Web API veio para substituir o Web Service que se tornou lento mediante a nova tecnologia.

Primeiro passo
Criar um novo projeto do tipo WebForm, o mais comum entre os desenvolvedores de software, usando a linguagem C# ou VB. Dentro da pgina default.aspx e na
parte de HTML, coloquei o objeto GridView. Esse objeto traz apenas o nome do usurio vindo do Rest consumido.
Listagem 1 Lista de usurio
C#

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

8/63

27/06/2016

Minhacoleo
<asp:GridViewID="GridView1"runat="server"AutoGenerateColumns="false">
<Columns>
<asp:BoundFieldDataField="Id"HeaderText="Id"/>
<asp:BoundFieldDataField="Nome"HeaderText="Nome"/>
</Columns>
</asp:GridView>

Agora temos que preencher esse GridView com os dados vindo do Rest criado no artigo parte 1.

Segundo passo
O segundo passo feito dentro da linguagem C#, neste caso o default.aspx.cs. Primeiro declarei duas variveis. Uma do System.Uri e outra do System.Net.Http.
Listagem 2 Declarao de varivel
C#
HttpClientclient;
UriusuarioUri;
Agora no construtor do mtodo necessrio indicar o endereo do site e o tipo de retorno, que no nosso caso o Json.
Listagem 3 Construtor
C#
public_default()
{
if(client==null)
{
client=newHttpClient();
client.BaseAddress=newUri("http://localhost:1020");
client.DefaultRequestHeaders.Accept.Add(new
System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
}
}
Note que na listagem 3, o tipo do cabealho do Rest o application/json baseado no HttpClient.
No Page_Load da classe default.cs eu chamei outro mtodo chamado getAll. Listagem 4. O mtodo getAll busca atravs do Web API o link e os dados para preencher
o GridView.
Listagem 4 Page_Load
C#
protectedvoidPage_Load(objectsender,EventArgse)
{
if(!Page.IsPostBack)
{
getAll();
}
}
Passando para o mtodo getAll, a chamada da url se torna simples e os dados retornados so pegos atravs de um Enumerable. Listagem 5.
Listagem 5 Chamando o rest e preenchendo o grid
C#
privatevoidgetAll()
{
//chamandoaapipelaurl
System.Net.Http.HttpResponseMessageresponse=client.GetAsync("api/usuario").Result;
//seretornarcomsucessobuscaosdados
if(response.IsSuccessStatusCode)
{
//pegandoocabealho
usuarioUri=response.Headers.Location;
//PegandoosdadosdoRestearmazenandonavarivelusurios
varusuarios=response.Content.ReadAsAsync<IEnumerable<Usuario>>().Result;
//preenchendoalistacomosdadosretornadosdavarivel
GridView1.DataSource=usuarios;
GridView1.DataBind();
}
//Sedererronachamada,mostraostatusdocdigodeerro.
else
Response.Write(response.StatusCode.ToString()+""+response.ReasonPhrase);
}
Em cada linha da listagem 5 existe uma explicao simplificada do que feito. O resultado final dessa chamada o grid preenchido rapidamente. Imagem 1.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

9/63

27/06/2016

Minhacoleo

Imagem 1 Grid preenchido pelo Rest


Espero que tenha gostado e em breve pblico mais um artigo falando e mostrando como excluir, incluir e pesquisar algum dado usando o Rest e Web API da
Microsoft. Qualquer dvida, pode entrar em contato pelo site www.mauriciojunior.org.

| Home | Artigos Tcnicos | Comunidade

2016 Microsoft

Criando e Consumindo Web API Parte 3


Mauricio Junior

Setembro 2013
Ol Leitora, hoje eu vou dar continuidade srie de artigo falando sobre a tecnologia Web API. Lembro a voc da necessidade de leitura dos outros artigos
anteriores citados abaixo, para um melhor entendimento e aprendizagem. Vou continuar com o mesmo seguimento, explicando e mostrando o cdigo fonte
desenvolvido.
Parte 1 http://msdn.microsoft.com/ptbr/library/dn450975.aspx
Parte 2 http://msdn.microsoft.com/ptbr/library/dn450977.aspx
Segue as ferramentas utilizadas:
Visual Studio 2012
Linguagem C#
Tecnologia: MVC e Web API
Neste artigo eu vou abordar a parte de delete de dados usando Web API. Na parte 2 do artigo eu mostrei como pegar os dados com o GET e preencher um GridView,
dessa vez eu vou pegar os dados do GridView e vou apaglos usando o DELETE do Web API criado na parte 1. No muito difcil ou trabalhoso, s vamos ter que
criar dois mtodos, um para o GridView e outro para fazer o delete depois do clique do usurio.
O primeiro mtodo que pega os dados do Grid para apagar necessrio fazer um ajuste junto ao GridView, dentro da parte em HTML. O GridView deve disponibilizar
alm das informaes, dois links especficos para excluir e atualizar, veja na figura 1.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

10/63

27/06/2016

Minhacoleo

Figura 1. GridView com lista e links


Puxar os dados e colocar os links fcil de fazer. O cdigo da listagem 1 mostra tudo na parte HTML do Visual Studio. Lembro que esses passos so bsicos de acordo
com a nossa proposta de artigos falando sobre Web API. Segue o cdigo para o GridView, listagem 1.
Listagem 1 Cdigo do GridView
C#
<asp:GridViewID="GridView1"runat="server"AutoGenerateColumns="false"
DataKeyNames="Id"OnRowCommand="GridView1_RowCommand">
<Columns>
<asp:BoundFieldDataField="Id"HeaderText="Id"/>
<asp:BoundFieldDataField="Nome"HeaderText="Nome"/>
<asp:ButtonFieldButtonType="Link"CommandName="Excluir"Text="Excluir"HeaderText="Excluir"/>
<asp:ButtonFieldButtonType="Link"CommandName="Atualizar"Text="Atualizar"HeaderText="Atualizar"/>
</Columns>
</asp:GridView>
A listagem 1 mostra o GridView chamado de GridView1, com as colunas BoundField e ButtonField para excluir e atualizar. Note tambm a existncia do
DataKeyNames, um atributo essencial para pegar a chave do banco de dados. Dentro desse atributo existe o valor Id que o mesmo nome do campo na tabela do
banco de dados criada na parte 1 da srie de artigos. Acrescentando estas colunas e o DataKeyName, preciso te mostrar como gerar o atributo RowCommand
responsvel por pegar os valores da linha selecionada com o clique do mouse.
No posso deixar de falar sobre o CommandName, essa propriedade define qual o nome vai verificar dentro da linguagem C#. Qualquer nome pode ser colocado,
lembrese de no usar palavras com acento ou caracter especial. Nesse caso, coloquei o nome Excluir em um CommandName e no outro Atualizar.
O primeiro passo acessar dentro da ferramenta na parte de Design, depois basta selecionar o GridView e clicar duas vezes no evento do objeto. A figura 2 mostra a
parte de Design dentro da ferramenta.

Figura 2 Parte de Design dentro da ferramenta


Ao selecionar o GridView, clique na aba de Properties e depois em Events. Veja a figura 3 mostrando o passo a passo.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

11/63

27/06/2016

Minhacoleo

Figura 3 Acessando propriedade do objeto


Note que na figura 3, o boto que parece um raio, chamase Events. Selecionando essa opo, a ao RowCommand est pronta para ser acionada. Para gerar um
mtodo especfico de RowCommand clicando duas vezes em cima do campo a frente do comando. Automaticamente a ferramenta gera para voc um mtodo na
linguagem C#.
A listagem 2 mostra o mtodo criado aps o duplo clique.
Listagem 2 Criando mtodo RowCommand
C#
protectedvoidGridView1_RowCommand(objectsender,GridViewCommandEventArgse)
{

}
Note na listagem 2 que o nome do mtodo composto do nome do objeto mais o nome do comando RowCommand. Dentro do mtodo necessrio verificar qual o
nome do comando para excluir ou atualizar de acordo com a seleo do usurio. O que precisamos pegar neste caso a chave coloca no DataKeyName. Para isso, vou
acrescentar alguns cdigos dentro do mtodo, e pegando o valor passadao para outro mtodo que vou criar posteriormente afim de apagar o dado no banco de
dados pelo Web API.
A listagem 3 mostra como ficou o mtodo para excluir o valor.
Listagem 3 Mtodo RowCommand, pegando a chave
C#
protectedvoidGridView1_RowCommand(objectsender,GridViewCommandEventArgse)
{
if(e.CommandName=="Excluir")
{
int_index=int.Parse((String)e.CommandArgument);
string_chave=GridView1.DataKeys[_index]["Id"].ToString();
}
}
Note que na listagem 3 a primeira verificao foi a igualdade do ComandName. Se o CommandName for igual a Excluir ento ele entra na prxima linha para executar
os dados. O prximo passo pegar o index da linha selecionada com o clique do mouse. Esse valor foi armazenado na varivel index do tipo Int. A segunda linha
responsvel por pegar a chave daquele registro, por isso passo o index e o nome do campo no banco de dados. GridView1.DataKeys[_index][Id].ToString.
O valor armazenado na varivel do tipo String chamada chave. Essa chave precisa ser passada para outro mtodo e esse mtodo precisa chamar o Web API de
DELETE passando parmetros. O mtodo que vou criar chama deleteint Id e espera como parmetro o tipo Int.
Antes de criar o mtodo, lembrese que o client deve ser definido no construtor da classe. A listagem 4 mostra essa informao necessria.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

12/63

27/06/2016

Minhacoleo

Listagem 4 Mtodo construtor da classe


C#
publicpartialclassWebForm1:System.Web.UI.Page
{
HttpClientclient;
UriusuariosUri;
publicWebForm1()
{
if(client==null)
{
client=newHttpClient();
client.BaseAddress=newUri(endereco_do_site);
client.DefaultRequestHeaders.Accept.Add(new
System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
}
}
...
}
A listagem 4 j foi explicada no artigo parte 2 publicado anteriormente.
Passando para a criao do mtodo delete, basta escrever algumas linhas especficas para executar o delete via Web API. A criao do mtodo mostrado na listagem
5.
Listagem 5 Criando o mtodo delete.
C#
privatevoiddelete(intId)
{
System.Net.Http.HttpResponseMessageresponse=client.GetAsync("api/usuario/"+Id).Result;
response=client.DeleteAsync("api/usuario/"+Id).Result;
if(response.IsSuccessStatusCode)
usuariosUri=response.Headers.Location;
else
Response.Write(response.StatusCode.ToString()+""+response.ReasonPhrase.ToString());
//chamaromtodoquepegatodososdadosnovamente,mostradonaparte2.
}
A listagem 5 mostra o mtodo privado e no retorna valor algum, s espera que seja passado um valor do tipo Int informado anteriormente. A primeira linha o
response que passa o endereo do Web API com o valor passado. Depois disso, necessrio chamar o mtodo DeleteAsync passando os parmetros e se for
executado com sucesso, o dado apagado. Por isso que na prxima linha verificado o status do cdigo executado, se no for executado corretamente, o cdigo
passa para o else que mostra o erro ao usurio pelo StatusCode. No final de tudo, necessrio chamar outro mtodo que pega todos os valores automaticamente
consultando o Web API.
Com o mtodo delete pronto, basta chamar indicar o nome passando parmetro dentro do RowCommand. Ai ficou simples para fazer. A listagem 6 mostra essa
chamada dentro do mtodo.
Listagem 6 Chamando o mtodo delete
C#
protectedvoidGridView1_RowCommand(objectsender,GridViewCommandEventArgse)
{
if(e.CommandName=="Excluir")
{
int_index=int.Parse((String)e.CommandArgument);
string_chave=GridView1.DataKeys[_index]["Id"].ToString();
delete(int.Parse(_chave));
}
}
A listagem 6 mostra na ltima linha que o mtodo delete chamado passando como parmetro a chave convertida para o tipo Int. Para mostrar todo esse caminho
percorrido, vou debugar via passo a passo e vai entender todo o mtodo.
Ao clicar F5 na ferramenta e marcar a linha desejada posso acompanhar passo a passo e os valores das variveis naquele momento. A figura 4 mostra a lista toda de
dados no meu banco de dados.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

13/63

27/06/2016

Minhacoleo

Figura 4 Mostrando todos os dados do banco de dados


Marquei a primeira linha do RowCommand e selecionei a primeira linha do meu grid. Note que o valor da primeira coluna 133. Esse o valor que precisa ser pego
dentro do mtodo. A figura 5 mostra que o mtodo parou esperando ser debugado.

Figura 5 Debugando o mtodo RowCommand.


A figura 6 mostra que o valor da chave pego foi o 133, o mesmo selecionado pelo clique do usurio.

Figura 6 Mostrando o valor seleiconado


Note que na figura 6, o debug est parado no comando delete. Para entrar dentro do mtodo delete, basta clicar F11; se for F10 ele no entra no mtodo mas executa
o que tem dentro dele. Resolvi entrar dentro do mtodo clicando F11. A figura 7 mostra o mtodo delete.

Figura 7 Debugando o mtodo delete para apagar o dado.


A figura 8 mostra que o valor foi apagado com sucesso.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

14/63

27/06/2016

Minhacoleo

Figura 8 Dado apagado com sucesso.


Depois de deletar o dado, eu pego novamente todos os dados e mostro na tela pelo GridView. A figura 9 mostra que o dado 133 no existe mais no banco de dados
buscado pelo Web API.

Figura 9 Mostrando o dado apagado.


Todos os passos acontecem de forma rpida e simples usando Web API, o trmite feito rapidamente e pode ser chamado por qualquer aplicativo incluindo aplicativo
mvel.
Bom, espero que tenha gostado e fico por aqui mais uma vez. Qualquer dvida, pode entrar em contato pelo site www.mauriciojunior.org. Fique atendo, em breve
pblico mais um artigo.

| Home | Artigos Tcnicos | Comunidade

2016 Microsoft

Criando e Consumindo Web API Parte 4


Mauricio Junior

Setembro 2013
Ol leitora, dando continuidade a srie de artigos sobre criar e consumir Web API, hoje eu vou falar e mostrar como fazer o PUT ou seja, como fazer update no
banco de dados usando Web API e o mtodo PUT criado em artigos anteriores. A criao do Web API est descrito todo na primeira parte.
No deixe de ler as partes anteriores, segue o link abaixo:
http://msdn.microsoft.com/ptbr/library/hh972587.aspx
Lembro que todos os artigos foram descritos baseados no passo a passo, ou seja, buscando descrever de forma simples e prtica para um melhor aprendizado. Toda
essa tecnologia da Microsoft est disponvel com a nova plataforma MVC 4.0 e a ferramenta Visual Studio 2012. A ferramenta pode ser baixada gratuitamente no site
da Microsoft. O Web API pode ser usado em qualquer dispositivo mvel ou web site, isso tudo foi descrito nas partes anteriores.
Lembro tambm que essa tecnologia conhecida tambm como REST usada desde do ano 2000 pelo eBay, depois o Amazon comeou a usar e veio se popularizar no
ano 2010 quando outros servios comearam a usar e disponibilizar pela Internet. Veja o que usei para desenvolver esse artigo:
Visual Studio 2012
MVC 4.0
Template Web API
Projeto do tipo Web/Mobile
No artigo anterior, parte 3, mostrei o objeto GridView com os links chamados Excluir e Atualizar. O excluir foi feito e agora vamos fazer o Atualizar, isto ,
continuo com o mesmo projeto e o mesmo GridView. Por isso peo a todos que leia desde o primeiro artigo at o ltimo.
Antes de mostrar o cdigo, vou informar a ideia principal para que entenda melhor cada passo. Como o objeto GridView preenchido, o clique no link chamado

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

15/63

27/06/2016

Minhacoleo

atualizar feito dentro do mtodo RowCommand. Os valores da linha selecionada so pegos e so enviados para os campos da pgina.
Com os campos preenchidos, o Id chave principal da minha tabela est escondido e o usurio no consegue alterar. O objeto usado para esconder o Id foi o Hidden.
Como o usurio pode atualizar o nome da pessoa, esse campo armazenado em um objeto TextBox. Existe um boto que chama a atualizao dos dados, isto , no
clique do boto, os valores so passados para o mtodo que por si s usa o Web Api. Espero que tenham entendido o funcionamento desse exemplo 4.
Para atualizar os dados no banco de dados atravs do Web API, o comando necessrio para executar este feito o PutAsJsonAsync, passando a URL e os dados de
atualizao. A figura 1 mostra os dados retornados.

Figura 1 Dados retornados


Existe um campo que o usurio pode ver, que o objeto TextBox, o outro o usurio no pode. Na parte HTML do cdigo ASPX existem os dois campos. Listagem 1.
Listagem 1 Mostrando os objetos da tela
C#
<asp:HiddenFieldID="hdId"runat="server"/>
<asp:TextBoxID="txtNome"runat="server"></asp:TextBox>
<asp:ButtonID="cmdAtualizar"runat="server"Text="Atualizar"OnClick="cmdAtualizar_Click"/>
O nome do Hidden hdId, o nome do TextBox txtNome e o boto que vai atualizar os dados o cmdAtualizar. O primeiro passo programar o click do link
Atualizar dentro do GridView. A listagem 2 mostra como pegar os dados do GridView e jogar nos campos.
Listagem 2 Mostrando como pegar os dados depois de clicar no link atualizar
C#
protectedvoidGridView1_RowCommand(objectsender,GridViewCommandEventArgse)
{
if(e.CommandName=="Atualizar")
{
int_index=int.Parse((String)e.CommandArgument);
string_chave=GridView1.DataKeys[_index]["Id"].ToString();
string_nome=Server.HtmlDecode(GridView1.Rows[_index].Cells[1].Text);
hdId.Value=_chave;
txtNome.Text=_nome;
txtNome.Focus();
}
}
A primeira linha do cdigo verifica se o comando igual ao link do GridView. Se o comando for Atualizar, ento o index pego com o ComandArgument. A chave
do GridView pego atravs do DataKeys e a linha pega com o mtodo Rows do prprio GridView passando a varivel index. Lembrese que necessrio passar o
nmero da clula comeando do zero e assim por diante.
Com as variveis e dados, basta atribuir os valores para os objetos da tela. Por isso que existe o hdId.Value= _chave e o txtNome.Text = _nome.
Para jogar os dados do grid na tela, no precisa buscar no banco de dados novamente, nem mesmo resubimeter os dados na pgina. Esses comandos feitos so
mostrados como resultado da figura 2.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

16/63

27/06/2016

Minhacoleo

Figura 2 Jogando os dados para o campo TextBox.


At o momento, fizemos apenas o envio dos dados para os campos. Um escondido e outro que pode ser alterado. A parte onde aparece o nome Mauricio 22, o
usurio pode alterar e depois basta clicar no boto Atualizar.
A listagem 3 mostra o clique do boto Atualizar chamando outro mtodo responsvel pela comunicao Web API e passando parmetros.
Listagem 3 Clique do boto atualizar.
C#
protectedvoidcmdAtualizar_Click(objectsender,EventArgse)
{
update(int.Parse(hdId.Value),txtNome.Text);
}
O primeiro passo foi criar uma classe chamada User com duas propriedades.Veja na listagem 4.
Listagem 4 Nova classe com propriedades
C#
classUser
{
[Key]
publicInt32Id{get;set;}

publicStringNome{get;set;}
}
Note que a classe possui os mesmos valores existentes no grid. Essa classe eu criei para passar ao Web Api a informao.
Passando para o mtodo update, a primeira percepo que ele recebe dois parmetros. Depois, os parmetros so atribudos na classe User. Veja a listagem 5
mostrando todo o mtodo.
Listagem 5 Mtodo update Web API.
C#
privatevoidupdate(int_Id,String_nome)
{
varusuarios=newUser(){Id=_Id,Nome=_nome};
System.Net.Http.HttpResponseMessageresponse=client.GetAsync("api/usuario").Result;
response=client.PutAsJsonAsync("api/usuario/"+_Id,usuarios).Result;
if(response.IsSuccessStatusCode)
usuariosUri=response.Headers.Location;
else
Response.Write(response.StatusCode.ToString()+""+response.ReasonPhrase.ToString());
getAll();
}
A primeira linha pega os dados enviados e atribui a classe criada chamada User. Listagem 6.
Listagem 6 Pegando os dados e atribuindo na classe User
C#
varusuarios=newUser(){Id=_Id,Nome=_nome};
Depois de atribuir os parmetros, usei o HttpResponseMessage enviando a URL do Web API. A mesma varivel response chama o client.PutAsJsonAsync passando
parmetro: URL barra o Id vrgula a varivel de usurios atribuda anteriormente. Se o resultado for de sucesso, ento o dado foi atualizado com sucesso, caso
contrrio impresso na tela o status do erro. Vamos ver se vai funcionar, veja a figura 3.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

17/63

27/06/2016

Minhacoleo

Figura 3 Alterando dados


Note que o dado Mauricio 22 foi alterado para Mauricio Junior sem qualquer problema. O GridView mostra que o Id 208 foi atualizado sem qualquer problema.
Bom, vou ficar por aqui e qualquer dvida pode entrar em contato pelo site www.mauriciojunior.org. Lembro que, para ler este artigo necessrio ler todos os outros
desde a criao do Web API at a utilizao da tecnologia. Espero que tenha gostado e at o prximo artigo.

| Home | Artigos Tcnicos | Comunidade

2016 Microsoft

Criando e Consumindo Web API Parte 5


Mauricio Junior

Setembro 2013
Ol pessoal, hoje eu gostaria de falar e mostrar como customizar as pesquisas no Web API, ou seja, saindo um pouco da rotina j criada pela ferramenta Visual Studio
da Microsoft, vamos criar outros mtodos dentro do Web API para pesquisas. importante entender que alm do trivial que so os mtodos PUT, DELETE e GET, existe
a possibilidade de criarmos outros usando outros nomes na assinatura do mtodo.
Utilizei:
Ferramenta: Visual Studio
Linguagem C#
Tecnologia Web API / REST
Busca no banco de dados: Linq
Esse mtodo que vou criar fica disponvel para ser chamado por outras aplicaes sem qualquer problema. Pode ser chamado at pela prpria aplicao que est
usando a tecnologia. A assinatura do mtodo faz com que a busca de um modo geral passe parmetros como ? interrogao e & comercial.
Lembrese de ler todos os artigos anteriores que falei sobre Web API, cada passo importante at chegar aqui. Segue os links abaixo dos artigos anteriores:
http://msdn.microsoft.com/ptbr/library/hh972587.aspx
Criei dentro da classe controller para determinado contexto um mtodo que soma valores. O mtodo recebe dois parmetros do tipo Int e retorna um do tipo
Int32. Esse mtodo no um padro do Web API, pra isso coloquei o nome de GetUsuariosByIdade. Veja a listagem 1.
Listagem 1. Criando mtodo que soma valores
C#
publicInt32GetUsuariosByIdade(intidade,intsoma)
{
returnidade+soma;
}
Como esse mtodo est no contexto de usurio, para acesslo basta digitar o endereo api/usuario/?idade=10&soma=10. Note que no coloco o nome do mtodo,
passo apenas os parmetros com os nomes iguais. Em resumo, assim que funciona quando criamos algum mtodo que no padro.
Outro exemplo a busca pelo nome da pessoa. Por padro, a busca de forma geral sem a passagem de parmetros, por exemplo: GetUsuarios. Caso queira pegar
um usurio pelo nome passando o parmetro, necessrio gerar outro mtodo. A listagem 2 mostra como buscar os usurios pelo nome usando Linq.
Listagem 2. Buscando os usurios pelo nome.
C#
publicIEnumerable<Usuario>GetUsuarioByName(stringname)
{
varusuario=db.Usuarios.Where(x=>x.Nome.Contains(name)).AsEnumerable();

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

18/63

27/06/2016

Minhacoleo
if(usuario==null)
thrownewHttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
returnusuario;
}

Note que na listagem 2, o nome do mtodo GetUsuarioByName recebe um parmetro do tipo string chamado name. Na primeira linha do mtodo eu busco a
tabela de usurios where o campo Nome contm o valor da varivel name. Isso significa que, se a varivel name tiver o valor de Mau e retornar todos os
nomes que comeam ou terminam com esse valor, depois os dados sero armazenados na varivel usuario que verificada logo em seguida. Se o valor for igual a
null, faz com que um erro retorne. No final do mtodo o comando return usuario retorna os dados do tipo IEnumerable <Usuario>.
Para acessar esse mtodo via browser ou no momento de consumir usando qualquer linguagem de programao, necessrio chamar o seguinte endereo:
api/usuario/?name=valor. Seguindo o nosso exemplo citado acima, seria: api/usuario/?name=Mau.
Uma dica importante no colocar os parmetros com o mesmo nome, assim voc pode criar vrios mtodos sem qualquer problema de conflito. Isso porque os
mtodos so identificados pelos parmetros passados.
Veja o resultado da pesquisa na imagem 1.

Imagem 1 Pesquisando nomes


A pesquisa realizada quando o usurio digita o valor no campo e clica no boto pesquisar. A listagem 3 mostra o que foi feito no boto pesquisar para consumir o
mtodo usando parmetros.
Listagem 3. Consumindo os dados por parmetro.
C#
protectedvoidcmdPesquisar_Click(objectsender,EventArgse)
{
System.Net.Http.HttpResponseMessageresponse=client.GetAsync("api/usuario/?name="+txtNome.Text).Result;
if(response.IsSuccessStatusCode)
{
usuariosUri=response.Headers.Location;
varusuarios=response.Content.ReadAsAsync<IEnumerable<User>>().Result;
GridView1.DataSource=usuarios;
GridView1.DataBind();
}
else
Response.Write(response.StatusCode.ToString()+""+response.ReasonPhrase);
}
Espero que tenham entendido como usar e como chamar, qualquer dvida pode entrar em contato pelo site www.mauriciojunior.org. Em breve publico mais um artigo
e uma srie de vdeos mostrando na prtica. Abrao a todos.

| Home | Artigos Tcnicos | Comunidade

2016 Microsoft

ASP.NET Web API HTTP, REST e o ASP.NET


Israel Aece
Julho 2013
Para basear todas as funcionalidades expostas pela tecnologia, precisamos ter um conhecimento bsico em relao ao que motivou tudo isso, contando um pouco da
histria e evoluo, passando pela estrutura do protocolo HTTP e a relao que tudo isso tem com o ASP.NET.
Os sistemas que so construdos atualmente produzem toneladas e toneladas de informaes, que so armazenadas em uma base de dados, para mais tarde, estas
mesmas informaes sero consumidas por estas e outras aplicaes.
No existe muitos problemas enquanto h apenas uma nica aplicao consumidora destas informaes, afinal ela pode consumir diretamente a base de dados para
ler e gravar as informaes desejadas. Se estamos dentro de um ambiente controlado, como por exemplo, aplicaes construdas dentro de uma mesma empresa,

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

19/63

27/06/2016

Minhacoleo

podemos utilizar a prpria base de dados para integrar as mesmas.


Enquanto estamos consumindo informaes locais, estamos diretamente conectados a nossa infraestrutura, sem qualquer impeclio mais crtico para acessar e
consumir as informaes. O dinamismo do mercado faz com que hoje as empresas operem em tempo real, onde as informaes que precisam ser consumidas ou
disponibilizadas esto alm do ambiente interno, ou seja, a necessidade de uma integrao real com parceiros de negcios, rgos governamentais, etc.
Utilizar a base de dados como meio de integrao no mais uma opo. Estamos agora lidando com empresas que esto fora da nossa rede, com aplicaes
construdas com tecnologias diferentes daquelas que adotamos internamente, padres diferentes, etc.
Tudo isso motivou algumas grandes empresas de tecnologia do mundo a trabalharem na construo de forma de integrao, criando um padro predefinido para
troca de informaes entre tais empresas. Em pouco tempo surgiu o conceito de Web Services, onde a ideia permitir com que sistemas se conectem a fim de trocar
informaes entre eles, sem a necessidade da interveno humana.
Para dar suporte a tudo isso, o XML foi utilizado como forma de expressar essa comunicao entre as partes. O XML uma linguagem de marcao, e que apesar de
ser texto puro, fornece uma gama de outros recursos agregados que o torna bastante poderoso, como por exemplo, a possibilidade de estensvel, separar definio de
contedo, opes para validao de estrutura, simplicidade na leitura inclusive por humanos.
Como a internet estava cada vez mais difundida, utilizla como forma de integrao foi uma das principais opes, pois tratavamse de tecnologias de padro aberto,
como o caso do HTTP e HTML. O HTTP d vida aos Web Services, pois ele que o torna acessvel, para que as aplicaes interessadas possam acesslos e trocar as
informaes. Alm disso, o fato de se apoiar em tecnologias de padro aberto, torna o consumo muito mais simplificado pelas mais diversas linguagens e tecnologias,
desde uma aplicao de linha de comando, passando por um navegador e at mesmo um dispositivo mvel.
Sendo o HTTP o responsvel pela infraestrutura de comunicao e o XML a linguagem que descrever a comunicao, ainda era necessrio um formato para
formalizar a interao entre as partes produtora e consumidora. Eis que surge o SOAP Simple Object Access Protocol. A finalidade do SOAP foi padronizar o
contedo que trafega entre as partes sob o protoloco HTTP. O SOAP baseado em XML e, consequentemente, estensvel, e em pouco tempo ele ficou popular e foi
utilizado em larga escala. Cada empresa utilizou as especificaes criadas e regidas por rgos independentes, criando um ferramental para que seja possvel a criao
e consumo destes tipos de servios. A Microsoft fez a sua parte criando os ASP.NET Web Services ASMX, que seguia as especificaes do W3C para a criao e
consumo de servios dentro da plataforma .NET, e isso contribuiu ainda mais para a popularizao destes tipos de servios.
O grande uso destes tipos de servios motivou a criao de algumas outras tecnologias para incrementar os Web Services, incluindo algumas caractersticas referentes
a segurana, entrega de mensagens, transaes, etc., e ento uma srie de especificaes WS* foram criadas graas a estensibilidade que o SOAP possibilita, a fim
de padronizar cada um destes novos recursos. A Microsoft correu para adequar os ASP.NET Web Services para suportar estas novas funcionalidades, e a surgiu o WSE
Web Services Enhancements.
Dentro do universo Microsoft h vrias opes para comunicao distruda, onde cada uma tinha um objetivo diferente, uma implementao nica e uma API nada
comum. Com o intuito de facilitar a comunicao distribuda dentro da plataforma .NET ela construiu o WCF Windows Communication Foundation. Ele um dos
pilares do .NET Framework, sendo o framework de comunicao para toda a plafaforma. O WCF unifica todas as tecnologias de comunicao distribudas que a
Microsoft tinha at ento. A proposta com ele tornar a construo e consumo de servios algo simples, onde o foco est apenas nas regras de negcios, e detalhes
com a infraestrutura, comunicao, protocolo, etc., seriam poucas configuraes a serem realizadas.
O WCF foi construdo com o protocolo HTTP, TCP, MQ sendo apenas uma forma de comunicao, onde o SOAP o padro que define todo o trfego das
mensagens, independentemente do protocolo que seja utilizado para a comunicao.
Como vimos at ento, o SOAP se apresenta como a soluo ideal para a integrao entre os mais variados sistemas, de qualquer tecnologia, justamente por trabalhar
com padres abertos e gerenciados por rgos independentes. S que o SOAP foi ganhando uma dimenso em funcionalidades, e grande parte das plataformas e
linguagens no conseguiram acompanhar a sua evoluo, tornando cada vez mais complicado a sua adoo, pois a cada nova funcionalidade adicionada, uma srie de
novos recursos precisam serm, tambm, adicionados nas plataformas/linguagens para suportar isso.
Motivada pela complexidade que o SOAP ganhou ao longo do tempo, e tambm pela dificuldade na evoluo por parte dos produtos e consumidores destes tipos de
servios, uma nova alternativa foi ganhando cada vez mais espao: o REST Representational State Transfer. O estilo REST vai contra tudo o que prega o SOAP, ou seja,
enquanto o SOAP entende que o HTTP uma forma de trfego da informao, o REST abraa o HTTP, utilizando integralmente todos os seus recursos.
Orientado recursos, o estilo REST define o acesso elementos como se eles fossem um conjunto predefinido de informaes quais queremos interagir acessvel
atravs de sua URI, extraindo e/ou criando estes recursos, diferindo do estilo baseado em RPC Remote Procedure Call que usvamos at ento, que define que o
acesso alguma funcionalidade.
Novamente, correndo atrs do que o mercado estava utilizando como principal meio de comunicao e integrao, a Microsoft comeou a trabalhar em uma nova
verso do WCF, j que era o pilar de comunicao da plataforma, para agregar a possibilidade de construir servios baseados em REST. Passamos ento a ter a
possibilidade de criar este tipo de servio no WCF, mas como o mesmo foi construdo abstraindo a figura do protocolo HTTP e outros, ficou complexo demais criar
servios REST sobre ele, j que era necessrio entender toda a infraestrutura do WCF para criar um servio deste tipo, pois para interagir com os elementos do HTTP,
tnhamos que lidar com objetos do framework que passava a expor o acesso aos recursos do HTTP URIs, headers, requisio, resposta, etc..
Como a criao de servios REST no WCF acabou ficando mais complexo do que deveria, a Microsoft comeou a investir na criao de uma nova forma de construir e
consumir servios REST na plataforma .NET. Inicialmente ele seria uma espcie de agregado ao WCF, mas pela complexidade de manter o modelo de classes que j
existia, a Microsoft decidiu criar a vincular isso ao ASP.NET, tornandoo uma plataforma completa para a criao de qualquer funcionalidade para ser exposta via Web,
e assim surgiu o ASP.NET Web API. Como toda e qualquer tecnologia, o ASP.NET Web API abstrai vrios elementos que so necessrios para o funcionamento destes
tipos de servios. Mas isso no motivo para no entender quais so e para o que eles servem.
Web API nada mais que uma interface que um sistema expe atravs do HTTP para ser acessado pelos mais variados clientes, utilizando as caractersticas do prprio
protocolo para interagir com o mesmo. E como estamos agora fundamentados no HTTP, necessrio conhecermos alguns elementos que passam a ser essencias para
a construo destes servios. Sendo assim, quando estamos lidando com a Web, toda e qualquer requisio e resposta possuem algumas caractersticas especficas
que envolvem todo o processo, a saber:
Recursos: recursos podem ser qualquer coisa que esteja disponvel e desejamos acessar. Podemos entender o recurso como uma pgina HTML, produtos de
uma loja, um video, uma imagem e tambm uma funcionalidade que pode ser acessvel atravs de outras aplicaes.
URIs: Todo e qualquer recurso para ser acessvel, precisa ter uma URI que determina o endereo onde ele est localizado. A URI segue a seguinte estrutura:
http://Servidor/MusicStore/Artistas?max+pezzali.
Representao: Basicamete uma fotografia de um recurso em um determinado momento.
Media Type: O recurso retornado ao cliente uma fotografia em um determinado momento, seguindo um determinado formato. O Media Type responsvel
por determinado o formato em que a requisio enviado e como a resposta devolvida. Alguns media types: image/png, text/plain, etc.
Se depurarmos uma requisio para qualquer tipo de API via HTTP, podemos enxegar cada um dos elementos elencados acima. Novamente, apesar de no ser
necessrio entender os bastidores da comunicao, o entendimento bsico nos dar conhecimento para depurar e encontrar mais facilmente eventuais
problemas, entendimento para tirar proveito de alguns recursos que o prprio HTTP nos fornece.
O HTTP baseado no envio e recebimento de mensagens. Tanto a requisio quanto a resposta HTTP possui a mesma estrutura. Temos o cabealho da
mensagem, uma linha em branco, e o corpo da mensagem. O cabealho composto por informaes inerentes ao endereo do servio e um conjunto de
headers, que nada mais que um dicionrio contendo uma srie de informaes contextuais requisio/resposta, que guiar o servio ou o cliente a como
tratar a mensagem.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

20/63

27/06/2016

Minhacoleo
HTML
POSThttp://localhost:1062/api/clientesHTTP/1.1
UserAgent:Fiddler
ContentType:application/json
Host:localhost:1062
ContentLength:48
{"Nome":"Israel","Email":"ia@israelaece.com"}

Na primeira linha vemos a forma verbo e para onde URI a requisio est sendo encaminhada. Vale lembrar que o verbo tem um significado importante no HTTP,
pois ele determina o formato da mensagem e como ela ser processada. Vemos tambm o ContentType, que determina o formato do contedo da mensagem, e que
neste caso, est serializado em JSON. Depois da linha em branco temos o contedo da mensagem. Se olharmos o todo, vemos que o cliente est interessado em
postar adicionar um novo cliente chamado Israel na coleo de clientes.
Depois de processado pelo cliente, e partindo do princpio que tudo deu certo, uma mensagem de resposta ser retornada, e l teremos informaes referente ao
processamento da requisio referente ao sucesso ou a falha:
HTML
HTTP/1.1201Created
ContentType:application/json;charset=utf8
Location:http://localhost:1062/api/clientes/12
ContentLength:58
{"Id":12,"Nome":"Israel","Email":"ia@israelaece.com"}
Estruturalmente a mensagem de resposta igual a da requisio, com cabealho, linha em branco e o corpo. A resposta contm tambm a coleo de headers,
incluindo o ContentType do corpo, pois a entidade postada est sendo retornada ao cliente informando, atravs do cdigo de status 201 Created, que o cliente foi
criado com sucesso e o Id que foi gerado e atribudo ele.
Claro que o HTTP fornece muito mais do que isso que vimos nestes exemplos de requisio e resposta. No decorrer dos prximos captulos iremos abordarmos com
mais detalhes cada um desses elementos e diversos outros recursos que sob demanda iremos explorando e, consequentemente, agregando e exibindo novas
funcionalidades que o HTTP fornece.

Veja tambm:
ASP.NET Web API HTTP, REST e o ASP.NET: Para basear todas as funcionalidades expostas pela tecnologia, precisamos ter um conhecimento bsico em relao ao
que motivou tudo isso, contando um pouco da histria e evoluo, passando pela estrutura do protocolo HTTP e a relao que tudo isso tem com o ASP.NET.
ASP.NET Web API Estrutura da API: Entenderemos aqui a template de projeto que o Visual Studio fornece para a construo das APIs, bem como sua estrutura e
como ela se relaciona ao protocolo.
ASP.NET Web API Roteamento: Como o prprio nome diz, o captulo ir abordar a configurao necessria para que a requisio seja direcionada corretamente para
o destino solicitado, preenchendo e validando os parmetros que so por ele solicitado.
ASP.NET Web API Hosting: Um captulo de extrema relevncia para a API. o hosting que d vida API, disponibilizando para o consumo por parte dos clientes, e a
sua escolha interfere diretamente em escalabilidade, distribuio e gerenciamento. Existem diversas formas de se expor as APIs, e aqui vamos abordar as principais
delas.
ASP.NET Web API Consumo: Como a proposta ter uma API sendo consumido por qualquer cliente, podem haver os mais diversos meios bibliotecas de consumir
estas APIs. Este captulo tem a finalidade de exibir algumas opes que temos para este consumo, incluindo as opes que a Microsoft criou para que seja possvel
efetuar o consumo por aplicaes .NET.
ASP.NET Web API Formatadores: Os formatadores desempenham um papel importante na API. So eles os responsveis por avaliar a requisio, extrair o seu
contedo, e quando a resposta devolvida ao cliente, ele entra em ao novamente para formatar o contedo no formato em que o cliente possa entender. Aqui
vamos explorar os formatadores padres que j esto embuitdos, bem como a criao de um novo.
ASP.NET Web API Segurana: Como a grande maioria das aplicaes, temos tambm que nos preocupar com a segurana das APIs. E quando falamos de aplicaes
distribudas, alm da autenticao e autorizao, necessrio nos preocuparmos com a segurana das mensagens que so trocadas entre o cliente e o servio. Este
captulo ir abordar algumas opes que temos disponveis para tornar as APIs mais seguras.
ASP.NET Web API Testes e Tracing: Para toda e qualquer aplicao, temos a necessidade de escrever testes para garantir que a mesma se comporte conforme o
esperado. Isso no diferentes com APIs Web. Aqui iremos abordar os recursos, incluindo a prpria IDE, para a escrita, gerenciamento e execuo dos testes.
ASP.NET Web API Estensibilidade e Arquitetura: Mesmo que j tenhamos tudo o que precisamos para criar e consumir uma API no ASP.NET Web API, a customizao
de algum ponto sempre acaba sendo necessria, pois podemos criar mecanismos reutilizveis, externalizandoos do processo de negcio em si. O ASP.NET Web API
foi concebido com a estensibilidade em mente, e justamente por isso que existe um captulo exclusivo para abordar esse assunto.

| Home | Artigos Tcnicos | Comunidade

2016 Microsoft

ASP.NET Web API Estrutura da API


Israel Aece
Julho 2013
Apesar de servios REST utilizar completamente o HTTP, importante que tenhamos suporte para a construo e consumo destes tipos de servios. Precisamos
entender como estruturar, configurar e distribuir estes tipos de servios.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

21/63

27/06/2016

Minhacoleo

Para facilitar tudo isso, a Microsoft preparou o ASP.NET para suportar o desenvolvimento de servios REST. A finalidade deste captulo introduzir a template de
projeto que temos, a API, a configurao mnima para a construo e exposio do mesmo.

A Template de Projeto
A construo de Web API est debaixo de um projeto ASP.NET MVC 4, e logo na sequncia da escolha deste projeto, voc deve escolher qual a template de projeto.
Neste caso, temos que recorrer a opo chamada Web API, conforme vemos nas imagens abaixo. O projeto j est prconfigurado com o que precisamos para criar
um servio REST e expor para que seja consumido, sem a necessidade de realizar muitas configuraes.

Figura 1 Escolha da Template do Projeto


O projeto j est configurado com as referncias DLLs necessrias que contm os tipos e membros que utilizaremos na construo das Web APIs, sendo a principal
delas o assembly System.Web.Http.dll. Dentro deste assembly temos vrios namespaces com todos os elementos necessrios que iremos utilizar para a construo de
Web APIs. Alm disso, j temos algumas configuraes definidas para que seja possvel criar e executar uma API criada, sem a necessidade de conhecer detalhes mais
profundos em um primeiro momento.
Analisando os itens do Solution Explorer, vemos que alm dos arquivos tradicionais de um projeto ASP.NET como o Global.asax e o Web.config, vemos ali um arquivo
chamado WebApiConfig.cs, que uma classe que contm a configurao padro do roteamento que ser abordado mais adiante para o funcionamento dos servios
REST. Alm disso, temos um servio j criado como exemplo, que est contido na classe/arquivo ValuesController.cs.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

22/63

27/06/2016

Minhacoleo

Figura 2 Elementos Padro de um Projeto Web API

A classe ApiController
A construo de Web APIs utilizando o ASP.NET segue uma certa simetria em relao a construo de um site baseado no padro MVC. Para a construo de views o
MVC exige que se tenha um controlador controller para receber, processar e retornar as requisies que so realizadas para o site.
De forma parecida trabalha a Web API. Todas as Web APIs construdas no ASP.NET devem herdar de uma classe abstrata chamada ApiController. Esta classe fornece
toda a infraestrutura necessria para o desenvolvimento destes tipos de servios, e entre as suas tarefas, temos: fazer a escolha do mtodo a ser executado, converso
das mensagens em parmetros, aplicao de eventuais filtros de vrios nveis, etc. Cada requisio, por padro, ter como alvo um mtodo dentro desta classe, que
ser responsvel por processar a mesma e retornar o resultado.
A criao de uma Web API pode ser realizada de forma manual herdando da classe ApiController, ou se preferir, pode ser utilizado o assistente que o prprio Visual
Studio disponibiliza, onde j existe algumas opes predefinidas para que a classe j seja criada com a estrutura bsica para alguns cenrios.

Figura 3 Opes para a criao do Controller


Independentemente da forma que voc utilize para a criao do controlador, sempre teremos uma classe que servir como a base para a API, e o cdigo abaixo ilustra
a herana da classe ApiController:
Classe ApiController
usingSystem.Web.Http;
namespaceMusicStore.Controllers
{
publicclassArtistasController:ApiController
{
}
}
Uma considerao importante com relao ao sufixo Controller que o nome da classe que representar a API dever ter. Apesar dele ser transparente para o cliente,
isso utilizado pelo ASP.NET para encontrar o controller durante a requisio. Podemos notar tambm que a classe no possui nenhum mtodo. Para que ela comece
a ter sentido, precisamos criar os mtodos que atendero as requisies que sero feitas para este servio. Da mesma forma que fazemos no MVC, aqui criaremos as
aes que retornaro dados aos clientes, formatados em algum padro e, opcionalmente, os clientes podero parametrizar a requisio, caso o servio permita isso.
A classe pode ter quantos mtodos forem necessrios, apenas temos que ter um pouco do bom senso aqui para no darmos mais funcionalidade do que deveria para
a mesma, considerando a granularidade. A criao dos mtodos possuem algumas convenes que se seguidas corretamente, no haver maiores configuraes a
serem realizadas para que ele j esteja acessvel ao rodar o servio.
Mas como que o ASP.NET escolhe qual dos mtodos acessar? O HTTP possui o que chamamos de verbos algumas vezes chamados de mtodos, e os mais comuns
so: GET, POST, PUT e DELETE, e cada um deles indica uma determinada ao a ser executada em um recurso especfico.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

23/63

27/06/2016

Minhacoleo
GET: Est requisitando ao servio um determinado recurso, apenas isso. Este verbo deve apenas extrair a informao, no alterandoa.
POST: Indica ao servio que a ele deve acatar o recurso que est sendo postado para o mesmo, e que muito vezes, o adicionamos em algum repositrio.
PUT: Indica que ao servio que o recurso que est sendo colocado deve ser alterado se ele j existir, ou ainda, pode ser adicionado caso ele ainda no exista.
DELETE: Indica que o servio deve excluir o recurso.

Mas o que isso tem a ver com o Web API? O ASP.NET j mapeia todos estes conhecidos verbos do HTTP para mtodos que estejam criados o interior do controller.
Para que isso acontea, precisamos definir os mtodos com o nome de cada verbo acima descrito, e com isso, automaticamente, quando o ASP.NET recepcionar a
requisio, esse ser o primeiro critrio de busca aos mtodos.
C#
publicclassArtistasController:ApiController
{
publicArtistaGet(intid)
{
}
publicvoidPost(ArtistanovoArtista)
{
}
}
claro que no estamos condicionados a trabalhar desta forma. Se voc quer criar uma API em portugus, talvez utilizar a configurao padro no seja a melhor
opo pela coerncia. Podemos nomear os mtodos da forma que desejarmos, mas isso nos obrigar a realizar algumas configuraes extras, para direcionar o
ASP.NET a como encontrar o mtodo dentro da classe, pois agora, difere daquilo que foi previamente configurado.
Para realizar essa configurao, vamos recorrer alguns atributos que j existem dentro do ASP.NET e que foram construdos para cada um dos verbos do HTTP:
HttpGetAttribute, HttpPutAttribute, HttpPostAttribute, HttpDeleteAttribute, etc. Quando um destes atributos colocado em um mtodo, ele permitir que ele seja
acessvel atravs daquele verbo. Utilizando o mesmo exemplo anterior, se alterarmos o nome dos mtodos apenas, eles deixaro de estar acessveis aos clientes.
C#
publicclassArtistasController:ApiController
{
[HttpGet]
publicArtistaRecuperar(intid)
{
}
[HttpPost]
publicvoidAdicionar(ArtistanovoArtista)
{
}
}
E ainda, como alternativa, podemos recorrer ao atributo ActionNameAttribute para alterar o nome que ser publicado em relao aquele que definido no mtodo,
dando a chance de utilizar uma conveno de nomenclatura para escrita e outra para publicao.
C#
publicclassArtistasController:ApiController
{
[ActionName(Recuperar)]
publicArtistaGet(intid)
{
}
}
Como comentado acima, existe um atributo para cada verbo. Para uma maior flexibilidade, temos tambm o atributo AcceptVerbsAttribute, que nos permite informar
em seu construtor quais os verbos que podem chegar at o mtodo em questo.
C#
publicclassArtistasController:ApiController
{
[AcceptVerbs("POST","PUT")]
publicvoidAdicionar(ArtistanovoArtista)
{
}
}
E se houver um mtodo pblico que se encaixe com as regras dos verbos que foram comentadas acima e no queremos que ele esteja disponvel publicamente,
podemos proibir o acesso decorando o mtodo com o atributo NonActionAttribute.

Parametrizao dos Mtodos


Todos os mtodos podem receber informaes como parmetros, e como sada, podemos retornar alguma informao que caracteriza o sucesso ou a falha referente
a execuo do mesmo. Quando falamos de mtodos que so disponibilizados para acesso remoto, isso no diferente.
Os mtodos podem necessitar alguns parmetros para executar a tarefa que est sendo solicitada. Os parmetros podem ter tipos mais simples como inteiro, string,
etc. at objetos mais complexos Usuario, Pedido, Produto, etc.. A utilizao de objetos complexo nos permite descrever o nosso negcio, tornandoo bem mais
intuitivo que criar um mtodo contendo uma infinidade de parmetros.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

24/63

27/06/2016

Minhacoleo

Figura 4 Postando um recurso de um objeto complexo.


Apesar de estarmos habituados a declarar o mtodo, seus parmetros e resultado da forma tradicional quando estamos construindo uma Web API, eles so trafegados
entre o cliente e o servio utilizando o modelo do HTTP, ou seja, eles podero ser carregados atravs de querystrings, headers ou do corpo das mensagens.
De forma semelhante ao que ocorre no ASP.NET MVC, o ASP.NET Web API capaz de mapear as querystrings que so tipos simples textos, nmeros, etc. para os
parmetros dos mtodos do controller de forma automtica. J os objetos complexos viajam entre o cliente e o servio e viceversa no corpo da mensagem. Toda a
mgica da transformao da mensagem em um objeto customizado realizada pelos formatadores de contedo, qual ter um captulo especfico para abordar este
assunto.
Quando estamos acessando os mtodos atravs do verbo GET, as querystrings so mapeadas para os parmetros destes mtodos; j quando realizamos o POST, o
corpo da mensagem transformado no objeto complexo, conforme vimos na imagem acima. Existe algumas opes mais rebuscadas se quisermos customizar como
estes parmetros so lidos das mensagens, e para isso, podemos recurrer aos atributos FromBodyAttribute ou ao FromUriAttribute. Estes atributos nos permite
direcionar o ASP.NET a buscar os valores para abastecer os parmetros em locais diferentes dos padres.
Podemos abastecer os parmetros baseados nas querystrings ou no corpo da mensagem. O corpo da mensagem pode estar em diversos formatos abordaremos com
mais detalhes adiante, e um deles a postagem sendo realizada atravs de um formulrio HTML.
HTML
<formaction="http://localhost:43139/api/Artistas/Adicionar"method="post">
<inputtype="text="id="Id"name="Id"/>
<inputtype="text="id="Nome"name="Nome"/>
<inputtype="text="id="Email"name="Email"/>
<inputtype="submit"name="Enviar"value="Enviar"/>
</form>
Ao preencher os campos e postar o formulrio, podemos capturar a requisio e analisar o que est sendo enviado ao servio mencionado. O que chama ateno na
requisio abaixo o header ContentType definido como application/xwwwformurlencoded, que corresponde ao valor padro para formulrios HTML. No corpo
da mensagem temos os campos do formulrio separados pelo caracter &. J os espaos so substitudos pelo caracter +. E, para finalizar, o nome do controle
definido como chave, enquanto o contedo do controle definido como valor no dicionrio.
Script
POSThttp://localhost:43139/api/artistas/adicionarHTTP/1.1
UserAgent:Fiddler
Host:localhost:43139
ContentType:application/xwwwformurlencoded
ContentLength:41
Id=12&Nome=Israel&Email=ia@israelaece.com

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

25/63

27/06/2016

Minhacoleo

Ao postar um formulrio para um mtodo que possui um objeto, o ASP.NET Web API j capaz de extrair as informaes do corpo da mensagem a partir do
dicionrio de valores e abastecer cada propriedade deste objeto. Se desejar, podemos ler individualmente as informaes que esto sendo encaminhadas, no
acionando o formatador de contedo, utilizando um outro tipo de codificao quando estamos postando o formulrio.
No exemplo acima, o formulrio foi postado utilizando o formato application/xwwwformurlencoded, que mais ou menos os valores do formulrio codificados
como se fossem itens de uma querystring. Existe um outro formato que o multipart/formdata, que possui uma codificao mais sofisticada. Em geral, ele utilizado
em conjunto com o elemento do tipo file, que quando queremos fazer upload de arquivos para o servidor.
Quando postamos um arquivo, automaticamente o tipo definido como sendo multipart/formdata e na sequencia, vemos o arquivo anexado.
Script
POSThttp://localhost:43139/api/artistas/AlterarFotoHTTP/1.1
ContentType:multipart/formdata;boundary=acebdf13572468
UserAgent:Fiddler
Host:localhost:43139
ContentLength:1168
acebdf13572468
ContentDisposition:formdata;name="fieldNameHere";filename="MaxPezzali.png"
ContentType:image/png
REMOVIDOPORQUESTESDEESPAO
Mas para recepcionar este tipo de requisio temos que preparar o servio. Note que ele no recebe nenhum parmetro; ele extrado do corpo da mensagem ao
executar o mtodo ReadAsMultipartAsync, que assincronamente l e materializa os arquivos, salvando automaticamente no caminho informado no provider. Se
desejar, podemos iterar atravs da propriedade Contents, acessando individualmente cada um dos arquivos que foram postados.
C#
[HttpPost]
publicasyncTask<HttpResponseMessage>AlterarFoto()
{
varprovider=
newMultipartFormDataStreamProvider(
HttpContext.Current.Server.MapPath("~/Uploads"));
returnawaitRequest
.Content
.ReadAsMultipartAsync(provider)
.ContinueWith<HttpResponseMessage>(t=>
{
if(t.IsFaulted||t.IsCanceled)
returnRequest.CreateErrorResponse(
HttpStatusCode.InternalServerError,t.Exception);
returnRequest.CreateResponse(HttpStatusCode.OK);
});
}
Apesar das tcnicas acima serem interessantes, utilizar uma delas pode ser um problema ao trabalhar com servios REST, devido ao fato de que em algumas situaes
haver a necessidade de ter o controle total das mensagens HTTP.
Com o intuito de facilitar e dar mais controle para ao desenvolvedor, a Microsoft inclui nesta API classes que representam a mensagem de requisio
HttpRequestMessage e de resposta HttpResponseMessage. Cada uma dessas classes trazem vrias propriedades, onde cada uma delas expe caractersticas do
protocolo HTTP, tais como: Content, Headers, Method, Uri, StatusCode, etc.
O servio passar a utilizar essas classes em seus mtodos, ou seja, receber um parmetro do tipo HttpRequestMessage, que possui todas as informaes necessrias
solicitadas pelo cliente, enquanto o retorno ser do tipo HttpResponseMessage, que ser onde colocaremos todas as informaes de resposta para o mesmo cliente,
sendo essas informaes o resultado em si, o cdigo de status do HTTP, eventuais headers, etc.
C#
publicclassArtistasController:ApiController
{
[HttpGet]
publicHttpResponseMessagePing(HttpRequestMessageinfo)
{
returnnewHttpResponseMessage(HttpStatusCode.OK)
{
Content=newStringContent("ping...")
};
}
}
O corpo da mensagem de retorno tambm pode ser customizado, onde podemos retornar uma simples string ou at mesmo um objeto complexo. Isso tudo ser
abordado com maiores detalhes nos captulos seguintes.

Mtodos Assncronos
A Microsoft incorporou diretamente no C# e no VB.NET o suporte para programao assncrona. A ideia facilitar a programao assncrona, que no era nada trivial
at o momento, tornando a escrita de um cdigo assncrono muito prximo a escrita de um cdigo sncrono, e nos bastidores, o compilador faz grande parte do
trabalho. Grande parte das funcionalidades do .NET Framework que j possuem suporte nativo ao consumo em formato assncrono, foram readaptados para que
assim, os desenvolvedores possam fazer uso dos novos recursos oferecidos pela linguagem para consumilos.
Com o ASP.NET Web API tambm podemos fazer com que os mtodos expostos pela API sejam processados assincronamente, usufruindo de todos os benefcios de
um mtodo ser executado de forma assncrona.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

26/63

27/06/2016

Minhacoleo

Vamos supor que o nosso servio de Artistas deve recorrer um segundo servio para extrair as notcias referentes um determinado artista. No interior do mtodo
que retorna o artista, faremos a chamada para o servio de Notcias e esperamos pelo resultado, que ao voltar, efetuamos o parser e, finalmente, convertemos para o
formato esperado e retornamos ao cliente.
Ao executar este tipo de servio, a requisio ser bloqueada pelo runtime at que o resultado seja devolvido para o servio. Isso prejudica, e muito, a escalabilidade
do servio. O fato da thread ficar bloqueada enquanto espera pelas notcias, ela poderia estar atendendo outras requisies, que talvez no exijam recursos de
terceiros I/O bound. O fato de disponibilizar a thread para que ela possa atender outras requisies, faro com que elas no esperem por um tempo
indeterminado, pois como dependemos do resultado de um terceiro, poderamos arranjar muito trabalho para esta thread, at que ela precise retomar o trabalho da
requisio anterior.
Para implementar o controller da API de forma assncrona, exigir algumas mudanas, mas nada que faa com que seja necessrio escrever e/ou gerenciar uma poro
de cdigo para garantir o assincronismo IAsyncResult por exemplo. Com isso, o primeiro detalhe a notar na escrita da ao assncrona, a exigncia da keyword
async, que faz do C#.
C#
publicclassArtistasController:ApiController
{
[HttpGet]
publicasyncTask<Artista>Recuperar(intid)
{
varartista=this.repositorio.Buscar(id);
using(varclient=newHttpClient())
artista.Noticias=
await
(awaitclient.GetAsync(ServicoDeNoticias))
.Content
.ReadAsAsync<IEnumerable<Noticia>>();
returnartista;
}
}

Tratamento de Erros
Durante a execuo, uma poro de excees podem acontecer, sejam elas referentes infraestrutura ou at mesmo alguma regra de negcio, e o no tratamento
correto delas, far com as mesmas no sejam propagadas corretamente ao cliente que consome a API. A maior preocupao aqui mapear o problema ocorrido para
algum cdigo HTTP correspondente.
Isso se faz necessrio porque excees so caractersticas de plataforma, e precisamos de alguma forma expressar isso atravs de algum elemento do HTTP, para que
cada um dos mais variados clientes possam interpretar de uma forma especfica. Por padro, todos os erros que ocorrem no servio e no tratados, retornando ao
cliente o cdigo de status 500, que indica um erro interno do servio Internal Server Error.
O ASP.NET Web API possui uma exceo chamada HttpResponseException, que quando instanciada definimos em seu construtor o cdigo de status do HTTP
indicando o erro que ocorreu. Para exemplificar o uso deste tipo, podemos disparar o erro 404 Not Found se o cliente est solicitando um artista que no existe.
C#
publicclassArtistasController:ApiController
{
[HttpGet]
publicArtistaRecuperar(intid)
{
varartista=this.repositorio.Buscar(id);
if(artista==null)
thrownewHttpResponseException(
newHttpResponseMessage(HttpStatusCode.NotFound)
{
Content=newStringContent("Artistanoencontrado"),
ReasonPhrase="IdInvlido"
});
returnartista;
}
}
Ainda como opo temos a classe HttpError para expressar o problema que ocorreu dentro do mtodo. A principal vantagem de utilizar esta classe em relao aquele
que vimos acima, que o contedo que identifica o erro serializado no corpo da mensagem, seguindo as regras de negociao de contedo.
C#
publicclassArtistasController:ApiController
{
[HttpGet]
publicHttpResponseMessageRecuperar(intid)
{
varartista=this.repositorio.Buscar(id);
if(artista==null)
returnRequest.CreateErrorResponse(
HttpStatusCode.NotFound,
newHttpError("Artistanoencontrado"));
else
returnRequest.CreateResponse(HttpStatusCode.OK,artista);
}

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

27/63

27/06/2016

Minhacoleo
}

Tratar as excees inplace como acima pode no ser uma sada elegante, devido a redundncia de cdigo. Para facilitar, podemos centralizar o tratamento em nvel
de aplicao, o que permitir com que qualquer exceo no tratada no interior da ao, ser capturada por este tratador, que por sua vez analisar o erro ocorrido,
podendo efetuar algum tipo de logging e, finalmente, encaminhar o problema ao cliente. neste momento que podemos efetuar alguma espcie de traduo, para
tornar a resposta coerente ao que determina os cdigos do HTTP, como por exemplo: se algum erro relacionado autorizao, devemos definir como resposta 403
Forbidden; j se algum informao est faltante assim como vimos no exemplo acima, devemos retornar o status 400 Bad Request; j se o registro procurado no
foi encontrado, ele dever receber o cdigo 404 Not Found, e assim por diante.
Para isso vamos recorrer a criao de um filtro customizado para centralizar a traduo de algum problema que acontecer. S que neste caso, temos uma classe
abstrata chamada de ExceptionFilterAttribute, que j fornece parte da infraestrutura necessria para o tratamento de erros que ocorrem, e equivalente ao atributo
HandleErrorAttribute que temos no ASP.NET MVC. Tudo o que precisamos fazer aqui sobrescrever o mtodo OnException e definir toda a regra de traduo
necessria. Abaixo um exemplo simples de como proceder para realizar esta customizao:
C#
publicclassExceptionTranslatorAttribute:ExceptionFilterAttribute
{
publicoverridevoidOnException(HttpActionExecutedContextctx)
{
varerrorDetails=newErrorDetails();
varstatusCode=HttpStatusCode.InternalServerError;
if(ctx.ExceptionisHttpException)
{
varhttpEx=(HttpException)ctx.Exception;
errorDetails.Message=httpEx.Message;
statusCode=(HttpStatusCode)httpEx.GetHttpCode();
}
else
{
errorDetails.Message="**InternalServerError**";
}
ctx.Result=
newHttpResponseMessage<ErrorDetails>(errorDetails,statusCode);
}
}
No vamos se aprofundar muito aqui, mas a criao de filtros um ponto de estensibilidade, e que teremos um captulo especfico para abordar este assunto. O que
precisamos nos atentar aqui existem vrios escopos para registros um filtro deste tipo, podendo ele ser aplicado em nvel de ao, de controller ou globalmente.
O cdigo abaixo registra o tradutor de excees em nvel global, recorrendo ao arquivo Global.asax para isso, que ser utilizado por todo e qualquer API que estiver
abaixo deste projeto. Maiores detalhes sobre a configurao de servio, sero abordados em breve, ainda neste captulo.
Global.asax
GlobalConfiguration
.Configuration
.Filters
.Add(newExceptionTranslatorAttribute());

Validaes
Como vimos anteriormente, o ASP.NET Web API capaz de construir um objeto complexo baseado no corpo da requisio. Mas como acontece em qualquer
aplicao, pode ser que o objeto esteja com um valores invlidos, o que impedir do mesmo ser processado corretamente.
Mesma se tratando de servios onde o foco a integrao entre aplicaes, necessrio que se faa a validao, para garantir que a requisio tenha as informaes
corretas para ser processada.
Uma das opes que temos para isso, fazer como j realizamos no ASP.NET MVC: recorrer aos Data Annotations do .NET Framework para validar se o objeto
encontrase em um estado vlido. Para isso, basta decorarmos as propriedades com os mais variados atributos que existem debaixo do namespace e assembly
System.ComponentModel.DataAnnotations.
Para iniciar devemos referenciar em nosso projeto o assembly que contm os tipos para a validao: System.ComponentModel.DataAnnotations.dll. A partir do
momento em que referenciamos este assembly na aplicao, podemos aplicar em nossos objetos os atributos que determinam as regras que cada propriedade dever
respeitar. No exemplo abaixo ilustra estamos informando ao ASP.NET que a propriedade Nome deve ser preenchida e a propriedade email deve representar um
endereo de email em formato vlido.
C#
publicclassArtista
{
publicintId{get;set;}
[Required]
publicstringNome{get;set;}
[EmailAddress]
publicstringEmail{get;set;}
}
S que os atributos no funcionam por si s. O ASP.NET Web API j est preparado para realizar a validao do objeto que est sendo postado, avaliando se cada
propriedade do mesmo est seguindo os atributos aplicados ela.
Como o ASP.NET j realiza toda a validao, o que nos resta no interior do mtodo verificar se o objeto est vlido. A classe ApiController fornece uma propriedade

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

28/63

27/06/2016

Minhacoleo

chamada ModelState. Essa propriedade d ao controller a possibilidade de verificar se o modelo que est sendo postado est ou no valido atravs da propriedade
boleana IsValid, e alm disso, nos permite acessar as propriedades problemticas, ou melhor, aquelas que no passaram na validao, que est baseada nos atributos
que foram aplicados.
Abaixo estamos avaliando essa propriedade, e se houver alguma informao errada, retornamos ao cliente o cdigo 400 Bad Request, indicando que h problemas
na requisio que foi encaminhada para o servio. O que importante notar que o mtodo que recebe e trata a requisio no possui regras de validao para o
objeto. Isso acabou sendo terceirizado para os Data Annotations do .NET, que acabam realizando toda a validao em estgios anteriores ao processamento da
requisio, e com isso o mtodo fica apenas com a responsabilidade de processar se a requisio foi encaminhada da forma correta.
C#
publicclassArtistasController:ApiController
{
[HttpPost]
publicHttpResponseMessageAdicionar(Artistaartista)
{
if(ModelState.IsValid)
{
//...
returnnewHttpResponseMessage(HttpStatusCode.Created);
}
returnnewHttpResponseMessage(HttpStatusCode.BadRequest);
}
}

Configurao
Ao trabalhar com algum tipo de projeto .NET, estamos acostumados a lidar com a configurao e estensibilidade do mesmo utilizando os arquivos de configurao
App.config ou Web.config. O ASP.NET Web API trouxe toda a configurao para ser realizada atravs do modelo imperativo via cdigo ao invs do modelo
declarativo via Xml.
Para centralizar toda a configurao das APIs, temos a disposio um objeto global que possui uma variedade de mtodos para registrarmos todos os elementos que
podemos customizar. Toda essa configurao realizada a partir do mtodo Application_Start do arquivo Global.asax. Como a template do projeto segue a mesma
linha do ASP.NET MVC, a configurao das APIs so realizadas em uma classe esttica chamada WebApiConfig, que recebe como parmetro um objeto do tipo
HttpConfiguration, acessvel atravs da propriedade esttica Configuration da classe GlobalConfiguration.
C#
publicclassWebApiApplication:System.Web.HttpApplication
{
protectedvoidApplication_Start()
{
WebApiConfig.Register(GlobalConfiguration.Configuration);
}
}
publicstaticclassWebApiConfig
{
publicstaticvoidRegister(HttpConfigurationconfig)
{
config.Routes.MapHttpRoute(
name:"DefaultApi",
routeTemplate:"api/{controller}/{id}",
defaults:new{id=RouteParameter.Optional}
);
}
}
Inicialmente o configurador das APIs possui apenas um cdigo que registra a rota padro para que as requisies sejam encaminhadas corretamente para os mtodos.
No vamos nos estender aqui, pois h um captulo dedicado a este assunto. A classe HttpConfiguration possui uma srie de propriedades que sero exploradas ao
longo dos prximos captulos.

Elementos do HTTP
Alm das informaes que so enviadas e recebidas atravs do corpo da mensagem, podemos recorrer alguns elementos inerentes ao HTTP, para incluir informaes
que fazem parte da requisio, como por exemplo, ID para controle da segurana, tags para caching, etc.
Para essas informaes, podemos recorrer aos famosos elementos do HTTP que so a coleo de headers, de querystrings e cookies. Como falamos anteriormente, se
quisermos ter o controle da mensagem, o mtodo/ao deve lidar diretamente com as classes HttpRequestMessage e HttpResponseMessage. Esses objetos expem
propriedades para acesso estes recursos, e mtodos de estenso facilitam o acesso a estas informaes.
O cookie nada mais que um header dentro da requisio, que quando o servio adiciona um cookie, chega uma instruo header ao cliente chamado SetCookie,
que faz com que o mesmo seja salvo e adicionado nas futuras requisies. No ASP.NET Web API temos uma classe chamada CookieHeaderValue, que representa um
cookie, que depois de criado, podemos adicionar na coleo de cookies da resposta e entregar ao cliente.
C#
[HttpGet]
publicHttpResponseMessagePing(HttpRequestMessagerequest)
{
varresponse=newHttpResponseMessage(HttpStatusCode.OK);
varid=request.Headers.GetCookies("Id").FirstOrDefault();
if(id==null)
{
response.Headers.AddCookies(newCookieHeaderValue[]
{

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

29/63

27/06/2016

Minhacoleo
newCookieHeaderValue("Id",Guid.NewGuid().ToString())
{
Expires=DateTimeOffset.Now.AddDays(10)
}
});
}
returnresponse;
}

Ao realizar a requisio, temos o header SetCookie sendo devolvido, que competir ao cliente que est acessando, salvlo para enviar em futuras requisies. Se
fizermos isso com o Fiddler, podemos perceber que quando a ao executada, o header Cookie interpretado e entregue ao ASP.NET Web API como uma instncia
da casse CookieHeaderValue.

Figura 6 Cookie sendo retornado para o servio.


No exemplo acima apenas estamos lidando com um nico valor, mas nada impede de termos uma informao mais estruturada dentro do cookie, ou seja, podemos
armazenar diversos dados. A classe CookieHeaderValue possui um construtor que permite informar uma coleo do tipo NameValueCollection, que define uma lista
de valores nomeados, onde podemos adicionar todos elementos que queremos que sejam levado ao cliente, e que sero separados pelo caracter &.
C#
[HttpGet]
publicHttpResponseMessagePing(HttpRequestMessagerequest)
{
varresponse=newHttpResponseMessage(HttpStatusCode.OK);
varinfo=request.Headers.GetCookies("Info").FirstOrDefault();
if(info==null)
{
vardata=newNameValueCollection();
data["Id"]=Guid.NewGuid().ToString();
data["Type"]="Simplex";
data["Server"]="SRV01";
response.Headers.AddCookies(newCookieHeaderValue[]
{
newCookieHeaderValue("Info",data)
});
}
returnresponse;
}

Figura 7 Cookie com mltiplos valores.

Documentao
http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

30/63

27/06/2016

Minhacoleo

Quando estamos falando de servios baseados em SOAP, temos um documento comando de WSDL Web Service Description Language baseado em XML, que
descreve todas as caractersticas definies de um determinado servio. justamente esse documento que utilizado por ferramentas como o svcutil.exe e a opo
"Add Service Reference" do Visual Studio, para gerar uma classe que representar o proxy, que por sua vez, ser utilizado pelos clientes para consumir o servio como
se fosse uma classe local, mas durante a execuo, a mensagem ser enviada ao ponto remoto.
Mas importante dizer que mesmo servios baseados em REST, tambm precisam, de alguma forma, expor alguma espcie de documentao, para descrever as aes
que as APIs esto disponibilizando aos consumidores, apontando o caminho URI at aquele ponto, mtodo/verbo HTTP, informaes que precisam ser passadas,
formatos suportados, etc.
A ideia apenas ser apenas informativo, ou seja, isso no ser utilizado pelo cliente para a criao automtica de um proxy. Pensando nisso, a Microsoft incluiu no
ASP.NET Web API a opo para gerar e customizar as documentaes de uma API.
Mas a documentao sempre exibida, na maioria das vezes, de forma amigvel ao consumidor, para que ele possa entender cada uma das aes, suas exigncias,
para que ele possa construir as requisies da forma correta. Sendo assim, podemos na prpria aplicao onde ns temos as APIs, criar um controller que retorna uma
view HTML, contendo a descrio das APIs que esto sendo hospedadas naquela mesma aplicao.
C#
publicclassDeveloperController:Controller
{
publicActionResultApis()
{
varexplorer=GlobalConfiguration.Configuration.Services.GetApiExplorer();
returnView(explorer.ApiDescriptions);
}
}
Note que estamos recorrendo ao mtodo GetApiExplorer, disponibilizado atravs da configurao global das APIs. Este mtodo retorna um objeto que implementa a
interface IApiExplorer, que como o prprio nome sugere, define a estrutura que permite obter a descrio das APIs. Nativamente j temos uma implementao
chamada ApiExplorer, que materializa todoas as APIs em instncias da classe ApiDescription, e uma coleo deste objeto retornada atravs da propriedade
ApiDescriptions, e que repassamos para que a view possa renderizar isso.
Na view, tudo o que precisamos fazer iterar pelo modelo, e cada elemento dentro deste lao representa uma ao especfica que est dentro da API. A classe que
representa a ao, possui vrias propriedades, fornecendo tudo o que necessrio para que os clientes possam consumir qualquer ums destas aes. Abaixo temos o
cdigo que percorre e exibe cada uma delas:
C#
@modelIEnumerable<System.Web.Http.Description.ApiDescription>
<body>
@foreach(vardescriptorinthis.Model)
{
<ul>
<li><b>@descriptor.HttpMethod@descriptor.RelativePath</b></li>
<li>Documentation:@descriptor.Documentation</li>
@if(descriptor.SupportedResponseFormatters.Count>0)
{
<li>MediaTypes
<ul>
@foreach(varmediaTypeindescriptor.SupportedResponseFormatters.Select(
mt=>mt.SupportedMediaTypes.First().MediaType))
{
<li>@mediaType</li>
}
</ul>
</li>
}
@if(descriptor.ParameterDescriptions.Count>0)
{
<li>Parameters
<ul>
@foreach(varparameterindescriptor.ParameterDescriptions)
{
<li>Name:@parameter.Name</li>
<li>Type:@parameter.ParameterDescriptor.ParameterType</li>
<li>Source:@parameter.Source</li>
}
</ul>
</li>
}
</ul>
}
</body>
Ao acessar essa view no navegador, temos a relao de todas as aes que esto expostas pelas APIs. A visibilidade das aes controlada a partir do atributo
ApiExplorerSettingsAttribute, que possui uma propriedade boleana chamada IgnoreApi, que quando definida como True, omite a extrao e, consequentemente, a sua
visualizao.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

31/63

27/06/2016

Minhacoleo

Figura 8 Documentao sendo exibida no browser.


importante notar que na imagem acima, estamos apresentando a propriedade Documentation. A mensagem que aparece ali uma customizao que podemos
fazer para prover essa informao, extraindoa de algum lugar. Para definir a descrio da ao, vamos criar um atributo customizado para que quando decorado no
mtodo, ele ser extrado por parte da infraestrutura do ASP.NET, alimentando a propriedade Documentation. O primeiro passo, consiste na criao de um atributo
para definir a mensagem:
C#
[AttributeUsage(AttributeTargets.Method,AllowMultiple=false)]
publicclassApiDocumentationAttribute:Attribute
{
publicApiDocumentationAttribute(stringmessage)
{
this.Message=message;
}
publicstringMessage{get;privateset;}
}
O prximo passo decorlo em cada uma das aes que quisermos apresentar uma informao/descrio. A classe abaixo representa a nossa API, e o atributo
recentemente criado foi decorado em todas as aes, descrevendo suas respectivas funcionalidades:
C#
publicclassClientesController:ApiController
{
[ApiDocumentation("Retornatodososclientes.")]
publicIEnumerable<Cliente>Get()
{
//...
}
[ApiDocumentation("RetornaumclientepeloseuId.")]
publicClienteGet(intid)
{
//...
}
[ApiDocumentation("Incluiumnovocliente.")]
publicvoidPost(Clientecliente)
{
//...
}
[ApiDocumentation("Excluiumclienteexistente.")]
publicvoidDelete(intid)
{
//...
}
}
S que o atributo por si s no funciona. Precisamos de algum elemento para extrair essa customizao que fizemos, e para isso, a temos uma segunda interface,
chamada IDocumentationProvider, que fornece dois mtodos com o mesmo nome: GetDocumentation. A diferena entre eles o parmetro que cada um deles
recebe. O primeiro recebe um parmetro do tipo HttpParameterDescriptor, o que permitir descrever, tambm, cada um dos parmetros de uma determinada ao. J
o segundo mtodo, recebe um parmetro do tipo HttpActionDescriptor, qual utilizaremos para extrair as informaes pertinentes uma ao especfica.
C#
publicclassApiDocumentationAttributeProvider:IdocumentationProvider
{
publicstringGetDocumentation(HttpParameterDescriptorparameterDescriptor)
{
returnnull;
}
publicstringGetDocumentation(HttpActionDescriptoractionDescriptor)
{
varattributes=
actionDescriptor.GetCustomAttributes<ApiDocumentationAttribute>();
if(attributes.Count>0)
returnattributes.First().Message;

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

32/63

27/06/2016

Minhacoleo
returnnull;
}
}

Aqui extramos o atributo que criamos, e se ele for encontrado, retornamos o valor definido na propriedade Message. A ausncia deste atributo, faz com que um valor
nulo seja retornado, fazendo com que nenhuma informao extra seja includa para a ao.
E, finalmente, para incluir o provedor de documentao ao runtime do ASP.NET Web API, recorremos configurao das APIs, substituindo qualquer implementao
existente para este servio, para o nosso provedor que extra a documentao do atributo customizado.
API atributo
GlobalConfiguration.Configuration.Services.Replace(
typeof(IDocumentationProvider),
newApiDocumentationAttributeProvider());
Veja tambm:
ASP.NET Web API HTTP, REST e o ASP.NET: Para basear todas as funcionalidades expostas pela tecnologia, precisamos ter um conhecimento bsico em relao ao
que motivou tudo isso, contando um pouco da histria e evoluo, passando pela estrutura do protocolo HTTP e a relao que tudo isso tem com o ASP.NET.
ASP.NET Web API Estrutura da API: Entenderemos aqui a template de projeto que o Visual Studio fornece para a construo das APIs, bem como sua estrutura e
como ela se relaciona ao protocolo.
ASP.NET Web API Roteamento: Como o prprio nome diz, o captulo ir abordar a configurao necessria para que a requisio seja direcionada corretamente para
o destino solicitado, preenchendo e validando os parmetros que so por ele solicitado.
ASP.NET Web API Hosting: Um captulo de extrema relevncia para a API. o hosting que d vida API, disponibilizando para o consumo por parte dos clientes, e a
sua escolha interfere diretamente em escalabilidade, distribuio e gerenciamento. Existem diversas formas de se expor as APIs, e aqui vamos abordar as principais
delas.
ASP.NET Web API Consumo: Como a proposta ter uma API sendo consumido por qualquer cliente, podem haver os mais diversos meios bibliotecas de consumir
estas APIs. Este captulo tem a finalidade de exibir algumas opes que temos para este consumo, incluindo as opes que a Microsoft criou para que seja possvel
efetuar o consumo por aplicaes .NET.
ASP.NET Web API Formatadores: Os formatadores desempenham um papel importante na API. So eles os responsveis por avaliar a requisio, extrair o seu
contedo, e quando a resposta devolvida ao cliente, ele entra em ao novamente para formatar o contedo no formato em que o cliente possa entender. Aqui
vamos explorar os formatadores padres que j esto embuitdos, bem como a criao de um novo.
ASP.NET Web API Segurana: Como a grande maioria das aplicaes, temos tambm que nos preocupar com a segurana das APIs. E quando falamos de aplicaes
distribudas, alm da autenticao e autorizao, necessrio nos preocuparmos com a segurana das mensagens que so trocadas entre o cliente e o servio. Este
captulo ir abordar algumas opes que temos disponveis para tornar as APIs mais seguras.
ASP.NET Web API Testes e Tracing: Para toda e qualquer aplicao, temos a necessidade de escrever testes para garantir que a mesma se comporte conforme o
esperado. Isso no diferentes com APIs Web. Aqui iremos abordar os recursos, incluindo a prpria IDE, para a escrita, gerenciamento e execuo dos testes.
ASP.NET Web API Estensibilidade e Arquitetura: Mesmo que j tenhamos tudo o que precisamos para criar e consumir uma API no ASP.NET Web API, a customizao
de algum ponto sempre acaba sendo necessria, pois podemos criar mecanismos reutilizveis, externalizandoos do processo de negcio em si. O ASP.NET Web API
foi concebido com a estensibilidade em mente, e justamente por isso que existe um captulo exclusivo para abordar esse assunto.

| Home | Artigos Tcnicos | Comunidade

2016 Microsoft

ASP.NET Web API Roteamento


Israel Aece
Julho 2013
No nicio foi comentado que uma das caracterstica dos servios REST, que todo recurso enderevel atravs de uma URI Universal Resource Identifier. atravs
da URI que sabemos onde ele est localizado e, consequentemente, conseguiremos chegar at ele recurso e executar uma determinada ao.
Cada URI identifica um recurso especfico, e ela tem uma sintaxe que bastante comum para os desenvolvedores: [scheme]:[port]://[host]/[path][?query]. Cada pedao
dela tem uma representao e funcionalidade, que esto detalhes na listagem abaixo:
Scheme: Identifica o protocolo que ser utilizado para realizar a requisio algum recurso, podendo ser: HTTP, HTTPS, FTP, etc.
Port: Opo para definir o nmero da porta no destino que ser utilizada para receber a requisio. Se omitido, utilizar a porta padro do protocolo, onde no
HTTP a porte 80, no HTTPS a porta 443, etc.
Host: O Host define o nome fornecido pelo DNS ou o endereo IP do servidor.
Path: Esta parte da URI qual identifica o recurso em si. atravs dele que apontamos qual dos recursos que desejamos acesso dentro daquele servidor.
Query: Tratase de uma informao opcional que pode ser encaminhada para o servio, fornecendo informaes adicionais para o processamento da
requisio. Um exemplo disso incluir o identificador do recurso que est sendo solicitado.
At pouco tempo atrs as URI eram algo indecifrvel para o usurio final, sendo apenas um endereo para algum recurso seja ele qual for em um ponto da rede. Aos
poucos as URIs foram ficando cada vez mais legvel, ou seja, tendo a mesma funcionalidade mas sendo mais amigvel, o que facilita o retorno do usurio, ou ainda, a
prpria URI refletir o que ela representa. H tambm benefcios relacionados ao SEO Search Engine Optimization, onde os buscadores consideram as palavras
encontradas na URI durante a pesquisa.
Durante o desenvolvimento do ASP.NET MVC, a Microsoft criou dentro dele um mecanismo de roteamento, que baseado em uma tabela de regras, ele capaz de
interpretar a requisio URI que est chegando para o mesmo e identificar o local, o servio, a classe e o mtodo a ser executado. Antes mesmo do lanamento
oficial do ASP.NET MVC, a Microsoft fez com que este recurso de roteamento fosse desacoplado e levado para o core do ASP.NET, e com isso, pode ser utilizado pelo
ASP.NET MVC, Web Forms e tambm pelo ASP.NET Web API, que o nosso foco aqui.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

33/63

27/06/2016

Minhacoleo

Tudo comea pela configurao dessa tabela de regras que est localizada no arquivo Global.asax. Como sabemos, ao rodar a aplicao pela primeira vez, o evento
Application_Start disparado, e justamente dentro dele onde o cdigo que faz toda a configurao das rotas colocada.
O objeto de configurao fornece uma coleo de rotas, e que na template de projeto que estamos utilizando, a rota padro colocada no arquivo WebApiConfig.
Notamos que a rota padro possui o nome de DefaultApi, e existe um segmento na seo Path da URI chamado de api. Ele utilizado para diferenciar e no causar
conflito com outras eventuais rotas que j existam naquela aplicao, como por exemplo, aquelas que so criadas pelo projeto ASP.NET MVC. Essa necessidade se
deve pelo fato de que podemos hospedar debaixo de um mesmo projeto, controllers que renderizam views HTML bem como controllers que retornam dados Web
API.
C#
publicstaticclassWebApiConfig
{
publicstaticvoidRegister(HttpConfigurationconfig)
{
config.Routes.MapHttpRoute(
name:"DefaultApi",
routeTemplate:"api/{controller}/{id}",
defaults:new{id=RouteParameter.Optional}
);
}
}
Toda rota pode ser composta de literais e de placeholders, que so substitudos durante a execuo. No exemplo acima, api tratase de um literal, enquanto o
{controller} e {id} so os placeholders. Quando a requisio realizada, o ASP.NET tenta mapear os valores extrados da URL e preencher os placeholders colocados na
rota. Caso nenhuma rota se enquadre com a requisio que est solicitada, o erro 404 Not Found retornado ao cliente.
importante mencionar que os placeholders podem ter valor padro definido. isso que define o ltimo parmetro do mtodo MapHttpRoute, chamado defaults.
Podemos determinar se ele opcional, e definir um valor padro se ele for omitido durante a requisio atravs de um dicionrio, onde cada item corresponde ao
nome do placeholder e seu respectivo valor. Abaixo temos algumas URLs indicando se ela est ou no enquadrada na rota padro:

URL

Mtodo

api/Artistas/MaxPezzali

ArtistasController.GetMaxPezzali

api/Artistas/34

ArtistasController.Get34

Artistas/Eros

Como no h o sufixo api/, ele no se enquadrar na rota padro, rejeitandoa.

api/Artistas

ArtistasController.Get e o parmetro id ser nulo.

Para o exemplo acima, estamos utilizando o seguinte mtodo:


C#
publicArtistaGet(stringid=""){}
Por conveno, se o mtodo for nomeado com o verbo do HTTP, automaticamente o ASP.NET Web API entrega a requisio naquela verbo paa ele, sem qualquer
trabalho adicional para que isso ocorra.
Durante a execuo o processo de roteamento possui alguns estgios de processamento que so executados at que a ao seja de fato executada. O primeiro passo
consiste ao enquadramento da URI uma rota configurada na tabela de roteamento. Se encontrada, as informaes colocadas na URI so extradas e adicionadas no
dicionrio de rotas, que podero ser utilizadas por toda a requisio, sendo pelo ASP.NET Web API runtime ou pelo cdigo customizado.
Depois de alguma rota encontrada, comea o processo para identificar qual a ao, ou melhor, o mtodo que o cliente est solicitando. S que antes de disso,
necessrio identificar a classe controller onde ele est. Como a rota padro j vem configurada no projeto, os dois placeholders determinam indiretamente a classe
controller e o mtodo ao, competindo ao ASP.NET realizar o parser dos fragmentos da URI, encontrar a classe e o mtodo, e depois disso, abastecer os
parmetros caso eles existam e, finalmente, invocar o mtodo, retornando o resultado sucesso ou falha ao cliente solicitante.
Apesar do compilador no indicar, toda a classe que ser considerada uma API, necessrio que ela no seja abstrata e tenha o seu modificador de acesso definido
como pblico, caso contrrio, o ASP.NET Web API no ser capaz de instancila. E, finalmente, apesar de termos a necessidade do sufixo Controller nas classes, essa
palavra no est presente na URI. Isso apenas uma exigncia do ASP.NET Web API, para identificar quais classes dentro do projeto correspondem uma API.
Depois de encontrada a classe, o momento de escolher o mtodo a ser executado. Da mesma forma que a classe, o mtodo a ser executado tambm escolhido
baseado na URI da requisio. Pela afinidade ao HTTP, a busca do mtodo dentro da classe considera os verbos do HTTP GET, POST, PUT, DELETE, etc. durante a
busca. O algoritmo de pesquisa do mtodo dentro do controller segue os passos descritos abaixo:
1. Seleciona todos os mtodos do controller que se enquadram com o verbo do HTTP da requisio. O mtodo pode ser nomeado ou prefixado apenas com o
nome do verbo.
2. Remove aquelas aes com o nome diferente do valor que est no atributo action do dicionrio de rotas.
3. Tentar realizar o mapeamento dos parmetros, onde os tipos simples so extrados da URI, enquanto tipos complexos so extrados do corpo da mensagem.
a. Para cada ao, extrai uma lista de parmetros de tipos simples, e exceto os parmetros opcionais, tenta encontrar o valor de cada um deles da URI.
b. Dessa lista tenta encontrar o respectivo valor no dicionrio de rotas ou na querystring da URI, independente de case ou de ordem dos parmetros.
c. Seleciona aquela ao onde cada um dos parmetros encontrado na URI.
4. Ignora as aes que esto decoradas com o atributo NonActionAttribute.
Como notamos no algoritmo acima, ele no considera a busca de aes quando h tipos complexos. A ideia tentar encontrar uma ao atravs da descrio esttica
da mensagem, ou seja, sem a necessidade de recorrer a qualquer mecanismo extra. Caso isso no seja suficiente, o ASP.NET Web API recorrer um binder ou um
formatador, baseado na descrio do parmetro e que na maioria das vezes, oriundo a partir do corpo da mensagem.
E o mtodo MapHttpRoute ainda fornece um outro parmetro que nos permite especificar constraints. Atravs delas podemos determinar um validador para um
parmetro especfico, ou seja, se conseguimos antecipar qual o formato que a informao deve ser colocada, isso evitar que ela seja rejeitada logo nos primeiros
estgios do processamento, retornando o erro 404 Not Found.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

34/63

27/06/2016

Minhacoleo
C#
publicstaticclassWebApiConfig
{
publicstaticvoidRegister(HttpConfigurationconfig)
{
config.Routes.MapHttpRoute(
name:"DefaultApi",
routeTemplate:"api/{controller}/{periodo}",
defaults:new{periodo=DateTime.Now.ToString("yyyyMM")},
constraints:new{periodo=@"[09]{4}\[09]{2}"}
);
}
}

Da mesma forma que fazemos com os valores padro para cada placeholder, criamos um novo dicionrio onde a chave o nome do parmetro, e o valor uma
expresso regular que determina o formato em que o parmetro deve ter. O fato de adicionar isso, o prprio ASP.NET Web API se encarrega de avaliar se o valor dos
parmetros se enquadram com a regra determinada na expresso regular. Isso nos d a chance de separar as validaes do mtodo que executa a ao, ficando
responsvel apenas por lidar com a regra de negcio.

Depurando Rotas
Acima vimos como podemos configurar as rotas no projeto, mas no estamos limitados a incluir apenas uma opo de roteamento. Na medida em que as APIs vo
sendo construdas, voc est livre para criar rotas especficas para recepcionar as requisies.
A medida em que as rotas vo sendo adicionadas, podemos enfrentar alguma dificuldade no desenvolvimento, onde a requisio no chega ao destino esperado, no
encontrando o controller ou a ao, ou at mesmo, em casos mais extremos, se enquadrando em uma rota diferente daquela que estvamos imaginando.
Para facilitar a depurao disso, existe uma ferramenta chamada ASP.NET Web API Route Debugger, que pode ser adicionado aplicao atravs do Nuget. Para
adicionla ao projeto, basta executar o comando abaixo na Package Manager Console, conforme mostrado abaixo:
Route Debugger
PM>InstallPackageWebApiRouteDebugger
Ao rodar este comando, alguns elementos so includos no projeto. Basicamente tratase de uma nova rea, que possui a interface grfica para exibir o resultado da
requisio com os parmetros e resultados da interceptao que foi realizada pelo debugger.
Depois de instalar este depurador, basta rodarmos a aplicao e quando chegarmos no navegador, basta acrescentarmos na URL o sufixo /rd. Isso far com que uma
tela seja exibida para que voc digite o endereo completo para a API que deseja invocar.

Figura 9 Route Debbuger.


A partir desta tela podemos ir testando as URIs que temos para validar se alguma rota dentro deste projeto consegue ser encontrada e, consequentemente,
direcionada para o mtodo que tratar a requisio. Quando pressionamos o boto Send, um resumo como o resultado da avaliao exibido, e nele voc conseguir
analisar de forma simples as informaes que foram extradas e facilmente identificar onde est o problema.
Entre as informaes, ele exibe o dicionrio de dados que foi extrado da URI. Ele elenca as informao chave e valor, quais voc poder avaliar se o valor informado
na URI est, corretamente, abastacendo o parmetro desejado.
A prxima tabela aponta as rotas que esto configuradas no projeto, incluindo as informaes extras, tais como: valores padro, constraints, etc. Com as informaes
que compem a configurao da rota sendo colocada aqui, fica fcil determinar o porque os parmetros entraram ou no, porque eles os parmetros assumiram o
valor padro ao invs de receber aquele que est na URI, e assim por diante.
Entre as duas ltimas tabelas temos a primeira que lista todos os controllers que esto adicionados ao projeto, bem como o seu tipo, namespace e assembly. J a
segunda, e no menos importante, exibe todas as aes que foram localizadas, descrevendoas complementos, incluindo o verbo HTTP que ela atende, o seu nome e
os parmetros. Logo na sequncia, ele nos aponta se ao mtodo foi encontrado pelo nome By Action Name ou pelo verbo By HTTP Verb. A imagem abaixo
ilustra essa tela com todos os detalhes descritos aqui.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

35/63

27/06/2016

Minhacoleo

Figura 10 Route Debugger exibindo as informaes.


Para a grande maioria das tarefas discutidas neste captulo, existem objetos responsveis por executar cada uma delas, e que podemos customizar cada um deles para
que seja possvel mudarmos algumas regras ou interceptarmos os estgios do processamento e incluir um cdigo para efetuar logs, mensurar performance, etc. A
estensibilidade abordada em detalhes em um captulo mais adiante.

Rotas Declarativas
O modelo de roteamento que vimos at aqui baseado em uma conveno que definida atravs de templates e esto centralizadas arquivo Global.asax. Como
falamos acima, durante a execuo os placeholders so substitudos pelos parmetros que so extrados, na maioria das vezes, da URI e, consequentemente,
encaminhada para a ao dentro do controller. Por ser uma coleo, podemos predefinir vrias rotas para atender todas as URIs que so criadas para as APIs que
rodam dentro daquela aplicao.
Apesar da centralizao ser um ponto positivo, comea a ficar complicado quando o nmero de rotas criadas comea a crescer. Haver um trabalho em olhar para
essa tabela e analisar qual das rotas a ao se enquadra. Nem sempre haver uma rota genrica para atender todas as requisies, j que para expressar melhor a
estrutura e hirarquia dos recursos, teremos que definir a rota para cada ao contida no controller.
para este fim que a Microsoft incluiu no ASP.NET Web API uma funcionalidade chamada de attribute routing, ou roteamento declativo. A ideia aqui configurar o
roteamento para uma ao em um local mais prximo dela, para alm de permitir a configurao especfica, facilitar a manuteno.
A implementao bastante simples mas muito poderosa. Aqueles atributos que vimos acima que determinam atravs de que verbo do HTTP a ao estar acessvel
HttpGetAttribute, HttpPutAttribute, HttpPostAttribute, HttpDeleteAttribute, etc., passam a ter um overload no construtor que aceita uma string com a template da
rota que ser atendida por aquela ao mtodo.
C#
publicclassArtistasController:ApiController
{
[HttpGet("artistas/{nomeDoArtista}/albuns")]
publicIEnumerable<Album>RecuperarAlbuns(stringnomeDoArtista)
{
returnnew[]
{
newAlbum(){Titulo="Max20"},
newAlbum(){Titulo="Terraferma"}
};
}
}
No exemplo acima vemos que a rota foi configurada inplace, ou seja, no prprio local onde a ao foi criada. Da mesma forma que fazemos na definio da rota no
arquivo Global.asax, aqui tambm podemos utilizar placeholders, para que eles sejam substitudos pelos parmetros da prpria ao que, novamente, so extrados da
requisio.
Mas aplicar os atributos com as rotas no suficiente. H a necessidade de instruir o ASP.NET a coletar as informaes sobre o roteamento diretamente nas aes.
Para isso h um mtodo de estenso que aplicado classe HttpConfiguration chamado MapHttpAttributeRoutes no arquivo Global.asax:

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

36/63

27/06/2016

Minhacoleo
Global.asax
config.MapHttpAttributeRoutes();

O resultado final para a chamada desta ao fica:


localhost
http://localhost:49170/artistas/MaxPezzali/albuns
claro que o controller pode conter diversas outras aes, onde cada uma delas retorna outras informaes, neste caso, de um determinado artista. Suponhamos que
tambm teremos uma ao que retorne as notcias do artista. Bastaria adicionar o mtodo classe, configurar o roteamento apenas alterando a ltima parte ,
trocando albuns por noticias.
H tambm uma opo para elevar o prefixo das rotas para o nvel da classe controller. Para isso, utilizaremos um atributo chamado RoutePrefixAttribute que nos
permite definir um valor que ser combinado com as rotas configuradas ao por ao para compor a rota final de acesso para cada uma delas.
C#
[RoutePrefix("artistas")]
publicclassArtistasController:ApiController
{
[HttpGet("{nomeDoArtista}/albuns")]
publicIEnumerable<Album>RecuperarAlbuns(stringnomeDoArtista)
{
returnnew[]
{
newAlbum(){Titulo="Max20"},
newAlbum(){Titulo="Terraferma"}
};
}
[HttpGet("{nomeDoArtista}/noticias")]
publicIEnumerable<Noticia>RecuperarNoticias(stringnomeDoArtista)
{
returnnew[]
{
newNoticia(){Titulo="NovoAlbumem2013"}
};
}
}
O fato de configurarmos as rotas nas aes, no quer dizer que perderemos certas funcionalidades. Mesmo utilizando esta tcnica, teremos a possibilidade de
configurar valores padro para os parmetros, bem como constraints para garantir que o cliente informe os dados seguindo uma regra j estabelecida.
Para ambos os casos, teremos uma sintaxe ligeiramente diferente comparada ao modelo tradicional centralizado, de forma imperativa. O prprio placeholder ir
contemplar os valores padro e as constraints. Para casos onde teremos um parmetro opcional e desejarmos definir um valor padro, teremos das formas para
representar, onde a primeira delas basta utilizar o recurso do prprio C# para isso, e no placeholder sufixar o parmetro com o caracter ?.
C#
[HttpGet("artistas/noticias/{cultura?}")]
publicIEnumerable<Noticia>RecuperarNoticias(stringcultura="ptBR"){}
[HttpGet("artistas/noticias/{cultura=ptBR}")]
publicIEnumerable<Noticia>RecuperarNoticias(stringcultura){}
J a segunda forma, definimos o valor padro do parmetro no prprio placeholder, que ponto de vista daquele que est acessando a cultura de dentro da ao, no
muda em nada. A diferena que no segundo caso, o valor ser encaminhado para o model binder, onde voc poder fazer algo diferente se assim desejar.
No caso das constraints temos um conjunto de opes e funes que garantem que os parmetros informados pelo cliente se enquadrem com a exigncia da API. A
ideia definir na configurao da rota a constraint usando a seguinte sintaxe: {parametro:contraint}. Na primeira parte definiremos o nome do parmetro que est
declarado na assinatura do mtodo ao, e na opo constraint iremos escolher uma das vrias opes predefinidas que temos a nossa disposio:

Constraint

Descrio

Exemplo

alpha, datetime, bool,


guid

Garante com que o parmetro seja alfanumrico az, AZ. H tambm opes para tipos
de dados especiais.

{cultura:alpha}

int, decimal, double,


float, long

Opes para nmeros de diferentes tipos.

{pagina:int}

length, maxlength,
minlength

Garante que uma determinada string tenha um tamanho especfico.

{razaoSocial:maxlength100}

max, min, range

Opes para determinar intervalos.

{idade:range18, 65}

regex

Assegura que o parmetro se encaixe em uma expresso regular.

{email: \b[AZ09._%]+@[AZ09.]+\.[A
Z]{2,4}\b}

Nada impede definirmos mais que uma constraint para um mesmo parmetro. Para isso basta utilizarmos uma vrgula para separar as constraints que desejamos

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

37/63

27/06/2016

Minhacoleo

aplicar a este parmetro.


C#
[HttpGet("artistas/detalhes/{artistaId:int}")]
publicArtistaRecuperarDetalhes(intartistaId){}

Nomenclatura das Rotas


Tanto para as rotas que definimos em nvel centralizado quanto estar em nvel de mtodo ao, podemos opcionalmente definir um nome que a identifique. A
finalidade deste nome facilitar a gerao dos links para recursos especficos que j existem ou que so criados sob demanda, evitando assim a definio em hard
code de links, o que dificulta a manuteno futura.
Como facilitador para a gerao destes links, temos uma classe chamada UrlHelper, que utiliza a tabela de roteamento para compor as URLs necessrias para a API. A
classe ApiController possui uma propriedade chamada Url, que retorna a instncia da classe UrlHelper j configurada para a utilizao.
C#
[RoutePrefix("artistas")]
publicclassArtistasController:ApiController
{
privatestaticIList<Artista>artistas=newList<Artista>();
privatestaticintIds=0;
[HttpPost("adicionar")]
publicHttpResponseMessageAdicionarArtista(HttpRequestMessagerequest)
{
varnovoArtista=request.Content.ReadAsAsync<Artista>().Result;
novoArtista.Id=++Ids;
artistas.Add(novoArtista);
varresposta=newHttpResponseMessage(HttpStatusCode.Created);
resposta.Headers.Location=
newUri(Url.Link("Detalhamento",new{artistaId=novoArtista.Id}));
returnresposta;
}
[HttpGet("detalhes/{artistaId:int}",RouteName="Detalhamento")]
publicArtistaBuscarDetalhes(intartistaId)
{
returnartistas.SingleOrDefault(a=>a.Id==artistaId);
}
}
Ao incluir o novo artista na coleo, o mtodo cria e retorna um objeto do tipo HttpResponseMessage, definindo o header Location com o endereo para detalhar a
entidade que foi recentemente criada. O mtodo Link da classe UrlHelper j combina o endereo geral host da API com o path at a ao que especificada,
retornando assim o endereo absoluto para um determinado local. O resultado da resposta mostrado abaixo:
host mtodo
HTTP/1.1201Created
Location:http://localhost:49170/artistas/detalhes/1
Date:Mon,01Jul201323:32:58GMT
ContentLength:0

Veja tambm:
ASP.NET Web API HTTP, REST e o ASP.NET: Para basear todas as funcionalidades expostas pela tecnologia, precisamos ter um conhecimento bsico em relao ao
que motivou tudo isso, contando um pouco da histria e evoluo, passando pela estrutura do protocolo HTTP e a relao que tudo isso tem com o ASP.NET.
ASP.NET Web API Estrutura da API: Entenderemos aqui a template de projeto que o Visual Studio fornece para a construo das APIs, bem como sua estrutura e
como ela se relaciona ao protocolo.
ASP.NET Web API Roteamento: Como o prprio nome diz, o captulo ir abordar a configurao necessria para que a requisio seja direcionada corretamente para
o destino solicitado, preenchendo e validando os parmetros que so por ele solicitado.
ASP.NET Web API Hosting: Um captulo de extrema relevncia para a API. o hosting que d vida API, disponibilizando para o consumo por parte dos clientes, e a
sua escolha interfere diretamente em escalabilidade, distribuio e gerenciamento. Existem diversas formas de se expor as APIs, e aqui vamos abordar as principais
delas.
ASP.NET Web API Consumo: Como a proposta ter uma API sendo consumido por qualquer cliente, podem haver os mais diversos meios bibliotecas de consumir
estas APIs. Este captulo tem a finalidade de exibir algumas opes que temos para este consumo, incluindo as opes que a Microsoft criou para que seja possvel
efetuar o consumo por aplicaes .NET.
ASP.NET Web API Formatadores: Os formatadores desempenham um papel importante na API. So eles os responsveis por avaliar a requisio, extrair o seu
contedo, e quando a resposta devolvida ao cliente, ele entra em ao novamente para formatar o contedo no formato em que o cliente possa entender. Aqui
vamos explorar os formatadores padres que j esto embuitdos, bem como a criao de um novo.
ASP.NET Web API Segurana: Como a grande maioria das aplicaes, temos tambm que nos preocupar com a segurana das APIs. E quando falamos de aplicaes
distribudas, alm da autenticao e autorizao, necessrio nos preocuparmos com a segurana das mensagens que so trocadas entre o cliente e o servio. Este
captulo ir abordar algumas opes que temos disponveis para tornar as APIs mais seguras.
ASP.NET Web API Testes e Tracing: Para toda e qualquer aplicao, temos a necessidade de escrever testes para garantir que a mesma se comporte conforme o
esperado. Isso no diferentes com APIs Web. Aqui iremos abordar os recursos, incluindo a prpria IDE, para a escrita, gerenciamento e execuo dos testes.
ASP.NET Web API Estensibilidade e Arquitetura: Mesmo que j tenhamos tudo o que precisamos para criar e consumir uma API no ASP.NET Web API, a customizao

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

38/63

27/06/2016

Minhacoleo

de algum ponto sempre acaba sendo necessria, pois podemos criar mecanismos reutilizveis, externalizandoos do processo de negcio em si. O ASP.NET Web API
foi concebido com a estensibilidade em mente, e justamente por isso que existe um captulo exclusivo para abordar esse assunto.

| Home | Artigos Tcnicos | Comunidade

2016 Microsoft

ASP.NET Web API Hosting


Israel Aece
Julho 2013
At o momento vimos algumas caractersticas do HTTP, a estrutura que uma API deve ter quando utilizamos o ASP.NET Web API, a configurao para rotear as
requisies para um tratador mtodo, etc. Mas para dar vida a tudo isso, precisamos de algum elemento que faa com que toda essa estrutura seja ativada e,
consequentemente, passe a tratar as requisies.
O responsvel por isso o hosting. Dado todas as configuraes necessrias a ele, ele ser responsvel por construtir toda a infraestrutura para receber, manipular,
processar e devolver a resposta ao cliente.
Ns temos algumas opes para realizar a hospedagem de APIs dentro do .NET, uma cada uma delas possuem suas vantagens e desvantagens. As opes so: self
hosting, webhosting e cloudhosting.
A primeira opo, selfhosting, consiste em hospedar as APIs em um processo que no seja o IIS como habitualmente . Isso permitir utilizar algum outro processo
do Windows, como por exemplo, uma aplicao Console, um Windows Service, ou at mesmo um projeto de testes, que poderemos utilizar para a facilitar a criao de
testes unitrios.
O primeiro passo para ter acesso a todos os recursos para hospedar APIs escritar em ASP.NET Web API em um processo prprio, instalar o pacote disponvel via
Nuget chamado Microsoft ASP.NET Web API Self Host.

Figura 11 Pacote para selfhosting.


Quando estamos falando em selfhosting, somos obrigados a criar toda a estrutura necessria para hospedar a API, e alm disso, precisamos gerenciar a vida destes
objetos, pois eles no so ativados sob demanda, obrigando eles estarem disponveis no momento em que a requisio chegar, caso contrrio, ela ser rejeitada.
Ao referenciar o pacote que vimos acima, o principal assembly que temos o System.Web.Http.SelfHost .dll. A principal classe a ser utilizada a HttpSelfHostServer,
que em seu construtor recebe a instncia da classe HttpSelfHostConfiguration, que tem a funo de receber todas as configuraes necessrias, para que em tempo
de execuo, fornea todos os recursos necessrios para a API ser executada.
Antes de qualquer coisa, precisamos criar a classe que representar a API, e isso no muda em nada, independente de como hospedamos a API. Sendo assim, temos
que criar uma classe, sufixada com a palavra Controller e herdar da classe abstrata ApiController, e a implementao dos mtodos nada muda em relao ao que j
conhecemos nos captulos anteriores.
A partir das APIs criadas, o momento de fazermos as configuraes e, consequentemente, ceder essas informaes para que a infraestrutura consiga fazer o papel
dela. Como sabemos, as rotas tem um papel extremamente importante para busca pela API, pelo mtodo e mapeamento dos respectivos parmetros. Todas as
configuraes, incluindo a tabela de roteamento, est acessvel a partida classe HttpSelfHostConfiguration.
Depois das configuraes realizadas, passamos a instncia desta classe para o construtor da classe HttpSelfHostServer. Internamente esta classe utiliza alguns recursos
do framework do WCF para extrair as mensagens do HTTP, materializando em classes para que o ASP.NET Web API possa comear a manipular.
C#
staticvoidMain(string[]args)
{
varconfig=newHttpSelfHostConfiguration("http://localhost:9393");
config.Routes.MapHttpRoute("Default","api/{controller}");
using(varserver=newHttpSelfHostServer(config))

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

39/63

27/06/2016

Minhacoleo
{
server.OpenAsync().Wait();
Console.ReadLine();
}
}

O mtodo OpenAsync, como j suspeitase, ele tem o sufixo Async por se tratar de um mtodo que executado de forma assncrona, retornando um objeto do tipo
Task, que representa a inicializao e abertura do servio, que quando concluda, passar a receber as requisies. O mtodo Wait, exposto atravs da classe Task,
bloqueia a execuo at que o host seja aberto.
Um dos overloads do construtor da classe HttpSelfHostServer recebe como parmetro uma instncia da classe HttpMessageHandler, qual podemos utilizar para
interceptar a requisio e a resposta, injetando algum cdigo customizado, como por exemplo, efetuar o log das mensagens, inspecionar os headers, etc. No captulo
sobre estensibilidade ser abordado as opes disponveis que temos para isso.
Como vimos, a opo do selfhosting d a chance de hospedar a API em um projeto que no seja ASP.NET e, consequentemente, no temos a necessidade termos
obrigatoriamente o IIS Internet Information Services, tendo um controle mais refinido sobre a criao e gerenciamento dos componentes da aplicao.
A outra opo que temos para hospedar APIs Web justamente utilizar o IIS webhosting, que por sua vez, nos d uma infinidade de recursos para gerenciamento
das APIs, reciclagem de processo, controle de acesso, ativao, segurana, etc. Esse modelo reutiliza a infraestrutura criada para o ASP.NET e tambm para o ASP.NET
MVC para executar os servios que sero hospedados ali.
Ao contrrio do que vimos na outra opo de hospedagem, quando optamos pelo ASP.NET, que j temos uma template de projeto disponvel chamada Web API
mais detalhes acima, que j traz algumas coisas j prconfiguradas, e os objetos que utilizamos para realizar as configuraes e customizaes, j esto mais
acessveis. Caso voc j esteja utilizando outra template de projeto, podemos recorrer um outro pacote via Nuget chamado Microsoft ASPNET Web API Web Host.

Figura 12 Pacote para webhosting.


A configurao j est acessvel atravs do arquivo Global.asax, que nos permite interceptar alguns eventos em nvel de aplicao, e um deles o Application_Start,
onde podemos realizar todas as configuraes referente ao roteamento para assim possibilitar os clientes chegarem at eles.
Essa configurao inicial j foi abordada nos captulos anteriores, mas claro que o objeto de configurao tanto no selfhosting quanto no webhosting so
utilizados apenas para armazenar a tabela de roteamento. Ele vai muito alm disso, e vamos explorar mais algumas funcionalidades que ele expe nos prximos
captulos.
A terceira e ltima opo abordada aqui cloudhosting, onde estaremos utilizando o Windows Azure para publicar e rodar as nossas APIs. Hospedar o servio na
nuvem pode facilitar o escalonamento do mesmo sem que haja a necessidade realizar mudanas na infraestrutura, afinal, o prprio mecanismo de gerenciamento e
execuo possui algoritmos que detectam o alto volume de acesso e, consequemente, sugerem e/ou ativam novas instncias mquinas virtuais para conseguir
atender toda a demanda.
importante dizer que o hosting nada tem a ver com o meio em que a API ou qualquer tipo de aplicao distribuda deployment. A distribuio determina como
ela empacotada, disponibilizada e instalada no computador onde ela ser executada. Para cada tipo de hosting que vimos at aqui, h um mecanismo de
distribuio diferente, combinando o Visual Studio para a criao do pacote e tecnologias que existem nos computadores e servidores para a instao do mesmo.

Veja tambm:
ASP.NET Web API HTTP, REST e o ASP.NET: Para basear todas as funcionalidades expostas pela tecnologia, precisamos ter um conhecimento bsico em relao ao
que motivou tudo isso, contando um pouco da histria e evoluo, passando pela estrutura do protocolo HTTP e a relao que tudo isso tem com o ASP.NET.
ASP.NET Web API Estrutura da API: Entenderemos aqui a template de projeto que o Visual Studio fornece para a construo das APIs, bem como sua estrutura e
como ela se relaciona ao protocolo.
ASP.NET Web API Roteamento: Como o prprio nome diz, o captulo ir abordar a configurao necessria para que a requisio seja direcionada corretamente para
o destino solicitado, preenchendo e validando os parmetros que so por ele solicitado.
ASP.NET Web API Hosting: Um captulo de extrema relevncia para a API. o hosting que d vida API, disponibilizando para o consumo por parte dos clientes, e a
sua escolha interfere diretamente em escalabilidade, distribuio e gerenciamento. Existem diversas formas de se expor as APIs, e aqui vamos abordar as principais
delas.
ASP.NET Web API Consumo: Como a proposta ter uma API sendo consumido por qualquer cliente, podem haver os mais diversos meios bibliotecas de consumir
estas APIs. Este captulo tem a finalidade de exibir algumas opes que temos para este consumo, incluindo as opes que a Microsoft criou para que seja possvel
efetuar o consumo por aplicaes .NET.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

40/63

27/06/2016

Minhacoleo

ASP.NET Web API Formatadores: Os formatadores desempenham um papel importante na API. So eles os responsveis por avaliar a requisio, extrair o seu
contedo, e quando a resposta devolvida ao cliente, ele entra em ao novamente para formatar o contedo no formato em que o cliente possa entender. Aqui
vamos explorar os formatadores padres que j esto embuitdos, bem como a criao de um novo.
ASP.NET Web API Segurana: Como a grande maioria das aplicaes, temos tambm que nos preocupar com a segurana das APIs. E quando falamos de aplicaes
distribudas, alm da autenticao e autorizao, necessrio nos preocuparmos com a segurana das mensagens que so trocadas entre o cliente e o servio. Este
captulo ir abordar algumas opes que temos disponveis para tornar as APIs mais seguras.
ASP.NET Web API Testes e Tracing: Para toda e qualquer aplicao, temos a necessidade de escrever testes para garantir que a mesma se comporte conforme o
esperado. Isso no diferentes com APIs Web. Aqui iremos abordar os recursos, incluindo a prpria IDE, para a escrita, gerenciamento e execuo dos testes.
ASP.NET Web API Estensibilidade e Arquitetura: Mesmo que j tenhamos tudo o que precisamos para criar e consumir uma API no ASP.NET Web API, a customizao
de algum ponto sempre acaba sendo necessria, pois podemos criar mecanismos reutilizveis, externalizandoos do processo de negcio em si. O ASP.NET Web API
foi concebido com a estensibilidade em mente, e justamente por isso que existe um captulo exclusivo para abordar esse assunto.

| Home | Artigos Tcnicos | Comunidade

2016 Microsoft

ASP.NET Web API Consumo


Israel Aece
Julho 2013
Depois da API construda, hospedada e rodando no servidor, chega o momento de consumirmos isso do lado do cliente. Como o foco o HTTP, que bastante
popular, a grande maioria das tecnologias cliente do suporte ao consumo deste tipo de servios. aqui que servios REST diferem bastante do SOAP. O SOAP define
uma estrutura para comunicao, que sem um ferramental que ajude, o consumo se torna bastante complexo, uma vez que temos que manualmente formatar as
mensagens de envio e interpretar as mensagens de retorno.
Mesmo com poucos facilitadores para consumir servios por parte de uma tecnologia, o trabalho com servios HTTP no muito complexo. Com um objeto que
gerencie a conexo, a configurao da requisio e leitura da resposta acabo sendo uma tarefa bem mais simples do que quando comparado ao SOAP.
Podemos ter os mais variados tipos de clientes, podendo ser aplicaes desktops, de linha de comando, aplicaes para internet, dispositivos mveis ou at mesmo
outros servios. Quando o consumo realizado por aplicaes Web, muito comum utilizarmos cdigo script para isso, onde recorremos Javascript para solicitar o
envio, recuperar a resposta e apresentar o resultado na tela. Neste ambiente temos uma biblioteca chamada jQuery, que fornece uma infinidade de facilitadores para o
consumo de servios REST.
Alm disso, podemos consumir servios REST em aplicaes que no so Web. Da mesma forma que a Microsoft criou tudo o que vimos at o momento para a
construo de servios, ela tambm se preocupou em criar recursos para tornar o consumo de servios REST em aplicaes .NET muito simples.
Para consumirmos servios REST em aplicaes .NET, o primeiro passo referenciar o assembly System.Net.Http.dll. Dentro deste assembly temos o namespace
System.Net.Http, que possui tipos para consumir servios baseados exclusivamente no protocolo HTTP. Os componentes que veremos aqui podem tambm ser
utilizados pelo lado do servio como o caso das classes HttpRequestMessage e HttpResponseMessage, fornecendo uma certo simetria entre o cdigo do lado do
cliente e do lado do servio, obviamente quando ambos forem .NET.
S que este assembly apenas no o suficiente. Ao invs de descobrirmos quais os assemblies e recursos que precisamos, podemos recorrer ao Nuget para que ele
registre tudo o que precisamos nas aplicaes cliente para consumir servios HTTP utilizando o ASP.NET Web API. Para isso podemos digitar a chave
Microsoft.AspNet.WebApi.Client, e j teremos a Microsoft ASP.NET Web API Client Libraries listada nos resultados, e clicando no boto Install, elas so configuradas
no projeto em questo.
importante dizer que tambm temos a verso portvel destas bibliotecas. Com isso, poderemos reutilizar o consumo de APIs REST HTTP atravs de diferentes
plataformas, sem a necessidade de reconstruir a cada novo projeto uma ponte de comunicao com estes tipos de servios, e ainda, sem a necessidade de recorrer de
classes de mais baixo nvel para atingir o mesmo objetivo.

Figura 13 Pacote com recursos para consumo de APIs.


Do lado do cliente a principal classe a HttpClient. Ela responsvel por gerenciar toda a comunicao com um determinado servio. Ela atua como sendo uma

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

41/63

27/06/2016

Minhacoleo

espcie de sesso, onde voc pode realizar diversas configuraes e que sero aplicadas para todas as requisies que partirem da instncia desta classe.
Essa a principal classe que utilizada quando estamos falando de um cliente .NET, fornecendo mtodos nomeados com os principais verbos do HTTP, e que
trabalham com as classes HttpRequestMessage e HttpResponseMessage, o que dar ao cliente o controle total da mensagem que enviada e da resposta que
retornada. Internamente a classe HttpClient trabalha com classes que so velhas conhecidas de quem j trabalha com .NET: HttpWebRequest e HttpWebResponse,
mas como todo e qualquer facilitador, a classe HttpClient encapsula toda a complexidade destas classes, expondo mtodos mais simples para consumo dos servios.
Apesar da classe HttpClient ser comparada com um proxy de um servio WCF, voc no est obrigado a somente invocar APIs que esto debaixo de um mesmo
servidor, pois isso deve ser definido o endereo URL onde est localizado o servio. Caso quisermos criar um cliente especfico para um determinado servio,
podemos herdar da classe HttpClient, e fornecer mtodos especficos para acessar os recursos que so manipulados pela API. Um exemplo disso seria ter uma classe
chamada FacebookClient, que internamente recorrer aos mtodos da classe HttpClient encapsulando ainda mais a pouca complexidade que temos, tornando o
consumo um pouco amigvel.
Antes de analisarmos algum cdigo, importante dizer que a classe HttpClient expe os mtodos para consumo dos servios de forma assncrona. Como o consumo
depende de recursos de I/O, os mtodos foram desenhados para que ao consumir qualquer recurso remoto, essa tarefa seja executada por uma outra thread. E, como
ele j faz uso do novo mecanismo de programao assncrona do .NET Tasks, ficar bastante simples gerenciar e coordenar requisies que so realizadas.
C#
classProgram
{
privateconststringEndereco="http://localhost:43139/api/artistas/MaxPezzali";
staticvoidMain(string[]args)
{
Executar();
Console.ReadLine();
}
privateasyncstaticvoidExecutar()
{
using(varclient=newHttpClient())
{
using(varrequest=awaitclient.GetAsync(Endereco))
{
request.EnsureSuccessStatusCode();
awaitrequest.Content.ReadAsAsync<JObject>().ContinueWith(t=>
{
Console.WriteLine(t.Result["Nome"]);
});
}
}
}
}
Dentro do mtodo Executar criamos a instncia da classe HttpClient, que atravs do mtodo GetAsync, realiza uma requisio atravs do verbo GET para o servio de
artistas, que estamos utilizando para os exemplos. Temos que fazer uso das palavras async e await para que o C# possa criar o mecanismo necessrio para que o
servio seja invocada de forma assncrona.
O mtodo EnsureSuccessStatusCode assegura que o servio foi invocado com sucesso, disparando uma exceo se o cdigo do status de retorno caracterizar uma
falha. Finalmente chamando o mtodo, tambm de forma assncrona, ReadAsAsync<T>. Este mtodo realiza a leitura do corpo da mensagem de retorno, tentando
converter a mesma no tipo genrico T. No exemplo acima estamos utilizando a classe JObject, que fornecida pelo framework Json.NET, que o mais popular meio
para manipular a serializao de objetos em Json dentro do .NET. Para instalarmos, basta recorrer ao comando abaixo no Nuget:
mtodo
PM>InstallPackageNewtonsoft.Json
Finalmente, quando finalizamos a leitura do corpo da mensagem, entregamos o objeto JObject ao ContinueWith para que ele exiba na tela. O objeto JObject
implementa a interface IDictionary, que dado uma string com o nome da propriedade, ele retorna o seu valor.
O problema da tcnica acima que ela baseada em strings e objects, sem qualquer tipificao, o que pode gerar erros, e que na maioria das vezes, acontecem
somente durante a execuo. Para facilitar isso, o Visual Studio .NET 2012, fornece dois recursos chamados Paste JSON as Classes e Paste XML as Classes, que dado
um contedo Json ou Xml que est na rea de transferncia, ele consegue construir as classes no projeto, configurando suas propriedades e seus respectivos tipos.

Figura 14 Opes do Visual Studio.


C#

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

42/63

27/06/2016

Minhacoleo
publicclassRootobject
{
publicintId{get;set;}
publicstringNome{get;set;}
publicintAnoDeNascimento{get;set;}
publicintQuantidadeDeAlbuns{get;set;}
}

Desta forma, podemos passar a utilizar as classes especficas ao invs de ficar lidando com ndices e nome das propriedades, que acaba sendo sujeito a erros. O cdigo
abaixo exibe um trecho do consumo do servio recorrendo a classe que acabamos de construir:
C#
awaitrequest.Content.ReadAsAsync<Artista>().ContinueWith(t=>
{
Console.WriteLine(t.Result.Nome);
});
Como pudemos perceber, o mtodo GetAsync recebe apenas o endereo para onde a requisio deve ser realizada. Mas e se quisermos customizar a requisio? Por
exemplo, incluir headers especficos para caching e segurana, especificar o formato de resultado que desejamos, etc. Devido a essas necessidades que devemos
recorrer a construo e configurao da classe HttpRequestMessage. atravs dela que toda a configurao realizada antes da mesma partir para o servio, e depois
que ela estiver devidamente configurada, recorremos ao mtodo SendAsync, que como parmetro recebe a classe HttpRequestMessage e retorna a classe
HttpResponseMessage. Apesar de Send no refletir um verbo do HTTP, dentro da mensagem que vamos especificar qual verbo ser utilizado para realizar a
requisio.
Utilizando o mesmo exemplo acima, vamos customizar a requisio para que ela retorne o artista em formato Xml:
XML
using(varclient=newHttpClient())
{
using(varrequest=newHttpRequestMessage(HttpMethod.Get,Endereco))
{
request.Headers.Add("Accept","application/xml");
using(varresponse=awaitclient.SendAsync(request))
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
}
A classe HttpMethod traz algumas propriedades estticas com os principais verbos criados, prontos para serem utilizados. Logo na sequncia estamos adicionando um
novo header chamado Accept, que determina o formato que queremos que o retorno seja devolvido. Da mesma forma que podemos utilizar a classe
HttpRequestMessage para customizar a requisio, podemos inspecionar a classe HttpResponseMessage para explorarmos tudo aquilo que o servio nos devolveu e,
consequentemente, tomar decises, realizar logs, novas requisies, etc.
Tanto a classe HttpRequestMessage quanto a HttpResponseMessage implementam a interface IDisposable, e por isso, podem ser envolvidas em blocos using. Ambas
as classes fornecem uma propriedade chamada Content, onde temos o corpo das mensagens, e como ele pode ser um stream, a implementao dessa interface auxilia
no descarte imediato quando elas no esto mais sendo utilizadas.
Quando vamos utilizar um verbo diferente do GET, como o caso do POST, ento precisamos definir o corpo da mensagem de envio, onde temos vrias opes para
os mais diversos contedos que enviamos para o servidor. O diagrama abaixo d uma dimenso disso.

Figura 15 Hierarquia das classes que representam o contedo das mensagens.


Cada uma dessa classes lidam exclusivamente com um tipo de contedo. Temos como customizar o envio determinando que o corpo deve ser uma espcie de
formulrio, string, stream e objetos.
Independente se estamos falando de requisio ou resposta, a classe ObjectContent<T> tem a funo de materializar objetos, baseandose no formato que ele foi
serializado. Existem classes que representam esses formatos, quais falaremos delas mais adiante, mas quando estamos consumindo o servio atravs desta biblioteca,

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

43/63

27/06/2016

Minhacoleo

no precisamos lidar diretamente com elas, pois existem alguns facilitadores que abstraem essa complexidade, e os formatadores apenas faro o trabalho
bidirecional sobre os bytes, o que de fato o que trafega entre as partes.
C#
privateconststringEndereco="http://localhost:43139/api/artistas/Adicionar";
privateasyncstaticvoidExecutar()
{
using(varclient=newHttpClient())
{
awaitclient.PostAsync(Endereco,newObjectContent<Artista>(newArtista()
{
Nome="PaoloMeneguzzi"
},newJsonMediaTypeFormatter())).ContinueWith(t=>
{
Console.WriteLine(t.Result.StatusCode);
});
}
}
No exemplo que temos acima, estamos recorrendo ao mtodo PostAsync, para que o objeto classe Artista seja postado. Neste caso, temos que explicitamente
mencionar que queremos que o contedo seja serializado atravs de Json. Felizmente, graas algumas extenses que j temos no ASP.NET Web API, podemos tornar
esse cdigo menos verboso:
C#
privateconststringEndereco="http://localhost:43139/api/artistas/Adicionar";
privateasyncstaticvoidExecutar()
{
using(varclient=newHttpClient())
{
awaitclient.PostAsJsonAsync(Endereco,
newArtista(){Nome="PaoloMeneguzzi"}).ContinueWith(t=>
{
Console.WriteLine(t.Result.StatusCode);
});
}
}
Da mesma forma que temos do lado do servio, a classe HttpClient tambm possui um overload do construtor que recebe a instncia de uma classe do tipo
HttpMessageHandler, qual podemos utilizar para interceptar a requisio e a resposta, injetando algum cdigo customizado, como por exemplo, efetuar o log das
mensagens, inspecionar os headers, etc. No captulo sobre estensibilidade ser abordado as opes disponveis que temos para isso.
Veja tambm:
ASP.NET Web API HTTP, REST e o ASP.NET: Para basear todas as funcionalidades expostas pela tecnologia, precisamos ter um conhecimento bsico em relao ao
que motivou tudo isso, contando um pouco da histria e evoluo, passando pela estrutura do protocolo HTTP e a relao que tudo isso tem com o ASP.NET.
ASP.NET Web API Estrutura da API: Entenderemos aqui a template de projeto que o Visual Studio fornece para a construo das APIs, bem como sua estrutura e
como ela se relaciona ao protocolo.
ASP.NET Web API Roteamento: Como o prprio nome diz, o captulo ir abordar a configurao necessria para que a requisio seja direcionada corretamente para
o destino solicitado, preenchendo e validando os parmetros que so por ele solicitado.
ASP.NET Web API Hosting: Um captulo de extrema relevncia para a API. o hosting que d vida API, disponibilizando para o consumo por parte dos clientes, e a
sua escolha interfere diretamente em escalabilidade, distribuio e gerenciamento. Existem diversas formas de se expor as APIs, e aqui vamos abordar as principais
delas.
ASP.NET Web API Consumo: Como a proposta ter uma API sendo consumido por qualquer cliente, podem haver os mais diversos meios bibliotecas de consumir
estas APIs. Este captulo tem a finalidade de exibir algumas opes que temos para este consumo, incluindo as opes que a Microsoft criou para que seja possvel
efetuar o consumo por aplicaes .NET.
ASP.NET Web API Formatadores: Os formatadores desempenham um papel importante na API. So eles os responsveis por avaliar a requisio, extrair o seu
contedo, e quando a resposta devolvida ao cliente, ele entra em ao novamente para formatar o contedo no formato em que o cliente possa entender. Aqui
vamos explorar os formatadores padres que j esto embuitdos, bem como a criao de um novo.
ASP.NET Web API Segurana: Como a grande maioria das aplicaes, temos tambm que nos preocupar com a segurana das APIs. E quando falamos de aplicaes
distribudas, alm da autenticao e autorizao, necessrio nos preocuparmos com a segurana das mensagens que so trocadas entre o cliente e o servio. Este
captulo ir abordar algumas opes que temos disponveis para tornar as APIs mais seguras.
ASP.NET Web API Testes e Tracing: Para toda e qualquer aplicao, temos a necessidade de escrever testes para garantir que a mesma se comporte conforme o
esperado. Isso no diferentes com APIs Web. Aqui iremos abordar os recursos, incluindo a prpria IDE, para a escrita, gerenciamento e execuo dos testes.
ASP.NET Web API Estensibilidade e Arquitetura: Mesmo que j tenhamos tudo o que precisamos para criar e consumir uma API no ASP.NET Web API, a customizao
de algum ponto sempre acaba sendo necessria, pois podemos criar mecanismos reutilizveis, externalizandoos do processo de negcio em si. O ASP.NET Web API
foi concebido com a estensibilidade em mente, e justamente por isso que existe um captulo exclusivo para abordar esse assunto.

| Home | Artigos Tcnicos | Comunidade

2016 Microsoft

ASP.NET Web API Formatadores


http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

44/63

27/06/2016

Minhacoleo

Israel Aece
Julho 2013
Um dos maiores benefcios ao se utilizar uma biblioteca ou um framework a facilidade que ele nos d para tornar a construo de algo mais simplificada, abstraindo
alguns pontos complexos, permitindo com que o utilizador foque diretamente e na maioria das vezes na resoluo de problemas voltados ao negcio, sem gastar
muito tempo com questes inerentes infraestrutura e/ou similares.
A finalidade do ASP.NET Web API justamente facilitar a construo de APIs para expor via HTTP. Apesar de uma das principais caractersticas de uma API abraar o
HTTP, a abstrao acaba sendo til em alguns casos, mas em outros no. A Microsoft se preocupou com isso, abstraindo alguns aspectos para tornar a construo e o
consumo destas APIs mais fceis, sem perder o poder de customizao e acesso aos recursos expostos pelo protocolo HTTP.
Como vimos nos captulos anteriores, possumos os objetos HttpRequestMessage e HttpResponseMessage, quais podemos definir na assinatura das aes do
controller e, consequentemente, ter o acesso total todos os recursos do HTTP. Apesar de que em alguns casos isso possa ser til, na sua grande maioria, temos que
lidar com alguns pontos que a abstrao poderia ajudar a nos manter mais focados no negcio do que na infraestrutura.
Um grande exemplo disso tudo o contedo payload da mensagem. Em geral, o corpo da mensagem representa um objeto que deve ser materializado e entregue
ao mtodo que tratar a requisio. A postagem que o cliente faz ao servio pode ser realizada em diferentes formatos, como por exemplo: Json, Xml, Csv, formulrio,
etc.
Como j foi dito anteriormente, o uso de um framework tem a finalidade de abstrair certos pontos para tornar a programao mais simples. Aqui temos um grande
exemplo disso. O ASP.NET Web API fornece alguns recursos intrinscos que torna a serializao e deserializao transparente ao ponto de vista do servio/mtodo.
Esses recursos so o Model Binding e os Formatadores.
As aplicaes geralmente trabalham com objetos que descrevem suas caractersticas, onde estes objetos so manipulados o tempo todo, j que na grande maioria dos
casos, ela acaba tambm sendo persistido no banco de dados, apresentado na tela, etc. Como esses objetos so parte do core da aplicao, muito comum criarmos
formulrios que apresente a instncia no mesmo na tela HTML, para que o usurio seja capaz de editlo.
Ao submeter o formulrio para o servidor, todas as informaes querystrings, body, URI, etc. chegam atravs de um dicionrio, onde cada valor est associado uma
chave. Ao invs de manualmente construirmos a instncia da classe baseada no corpo da requisio, o ASP.NET MVC j fez esse rduo trabalho para ns, e o
responsvel por isso so os model binders. Baseandose na action para qual estamos postando a requisio, ele captura o tipo do objeto que precisa ser criado,
mapeando o dicionrio para cada uma de suas propriedades.
Olhando mais de perto, os model binders so os responsveis por construir os objetos, baseandose em um dicionrio que contm as informaes que foram
extradas da requisio atravs de Value Providers. O ASP.NET Web API possui algumas implementaes embutidas, mas nada impede de criarmos alguma
customizao tanto para o value provider se quisermos customizar como extrair as informaes da requisio, bem com o model binder se quisermos customizar
como construir a instncia do objeto.
Ao efetuar uma requisio para algum recurso sobre o protocolo HTTP, o servidor identifica o mesmo, faz o processamento, gera o resultado e, finalmente, devolve o
resultado para o cliente que fez a solicitao. Por mais que isso no fica explcito, o contedo que trafega do cliente para o servidor requisio e do servidor para o
cliente resposta, sempre possui um formato especfico.
Em grande parte de todos os recursos fornecidos atravs do protocolo HTTP, uma das necessidades justamente definir o formato deste contedo, que por sua vez,
direciona a interpretao pelo navegador, por uma outra aplicao ou at mesmo de uma biblioteca, permitindo efetuar o parser do resultado e, consequentemente,
materializar o mesmo em algo "palpvel"/visvel.
Os formatos so representados por uma simples string, onde voc tem uma primeira parte para descrever qual o tipo de contedo, e depois o seu formato. Por
exemplo, ao invocar uma pgina onde o retorno um contedo HTML, o formato ser definido como text/html; ao solicitar uma imagem, o seu formato ser definido
como image/jpeg. Uma lista contendo todos os formatos de contedos disponveis na internet, gerenciada e mantida por entidade chamada IANA.
Como o ASP.NET Web API tem uma forte afinidade com as caractersticas do HTTP, ele permite receber ou gerar contedos em formatos popularmente conhecidos
pelo mercado, e vamos perceber que os servios que criamos utilizando essa API nada sabem sobre o formato em que ele chegou ou o formato em que ele ser
devolvido para o cliente. O ASP.NET Web API unifica o processo de serializao e deserializao dos modelos atravs de formatadores, que baseado em um media
type especfico, executa o trabalho para materializar a requisio em um objeto de negcio modelo.
Apesar dos principais formatadores j estarem vinculados execuo, precisamos analisar a estrutura da classe que representa um media type para realizar futuras
customizaes. Para isso, a Microsoft criou uma classe abstrata chamada de MediaTypeFormatter, e j existem algumas implementaes definidas dentro da API, como
por exemplo, as classes XmlMediaTypeFormatter e JsonMediaTypeFormatter.
Uma pergunta pertinente que aparece como o ASP.NET Web API escolhe qual dos formatadores utilizar. A escolha se baseia no formato solicitado pelo cliente. O
formato pode ser includo como um item na requisio, atravs do header Accept ou do ContentType. O ASP.NET Web API escolhe o formatador de acordo com o
valor que ele encontra em um desses headers, e caso o formato definido no for encontrado, o padro sempre devolver o contedo em formato Json.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

45/63

27/06/2016

Minhacoleo

Figura 16 Hierarquia das classes de formatadores.


Ao contrrio do que fazemos no cliente, o servio no trabalha diretamente com estes formatadores, pois isso fica sob responsabilidade de objetos internos, que
durante a execuo fazem todo o trabalho para encontrar para ler ou escrever o contedo no formato requisitado. O responsvel por fazer esta anlise e encontrar o
formatador adequado a classe DefaultContentNegotiator atravs do mtodo Negotiate fornecido pela interface IContentNegotiator.
Para percebermos a mgica que o ASP.NET Web API faz, vamos utilizar o Fiddler para criar e monitorar as requisies. No primeiro exemplo, vamos invocar um
mtodo que dado o nome do artista, ele retorna um objeto complexo contendo as caractersticas deste artista. Abaixo temos a primeira requisio sendo executada e
seu respectivo retorno.
[Requisio]
GET http://localhost:43139/api/artistas?nome=MaxPezzali HTTP/1.1
UserAgent: Fiddler
Host: localhost:43139
[Resposta]
HTTP/1.1 200 OK
ContentType: application/json; charset=utf8
ContentLength: 75

{"Id":5,"Nome":"MaxPezzali","AnoDeNascimento":1967,"QuantidadeDeAlbuns":20}
Note que no mencionamos nenhum header extra na requisio, e o objeto artista foi devolvido serializado em Json. Ns podemos requisitar que o contedo seja
devolvido em um determinado padro. Para isso, recorreremos ao atributo Accept para informar ao servio que o aceito o retorno em um determinado formato. Os
logs abaixo exibem a requisio e a resposta para o formato Xml:
[Requisio]
GET http://localhost:43139/api/artistas?nome=MaxPezzali HTTP/1.1
Host: localhost:43139
Accept: application/xml
[Resposta]
HTTP/1.1 200 OK
ContentType: application/xml; charset=utf8
ContentLength: 252

<Artista xmlns:i="http://www.w3.org/2001/XMLSchemainstance" xmlns="http://schemas.datacontract.org/2004/07/MusicStore.Models">


<AnoDeNascimento>1967</AnoDeNascimento><Id>0</Id><Nome>MaxPezzali</Nome><QuantidadeDeAlbuns>20</QuantidadeDeAlbuns></Artista>
Percebemos que a o resultado bem maior quando o resultado devolvido em Xml, pelo fato da sua estrutura ser bem mais verbosa que o Json. Alm disso, ainda h
quem defenda que se o servio no suportar o formato requisitado pelo cliente, ele no deveria acatar a requisio. Para termos este comportamento no ASP.NET
Web API, ns temos que criar cdigo customizado para conseguir rejeitar a requisio.
Como vimos acima, por padro, o ASP.NET Web API faz a busca do formato na coleo de headers da requisio, mas isso pode ser customizado. Podemos instruir o
ASP.NET Web API localizar o formato na querystring, e utilizaremos o objeto de configurao para realizar esse ajuste.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

46/63

27/06/2016

Minhacoleo

Figura 17 Hierarquia das classes referente ao mapeamento de mediatypes.


Existe uma classe chamada MediaTypeMapping, e como o nome sugere, ele traz a infraestrutura para extrair o media type de algum elemento da requisio. Como
vemos no diagrama acima, temos as classes QueryStringMapping e RequestHeaderMapping, que buscam o media type dentro da coleo de querystrings e headers,
respectivamente.
Note que no cdigo abaixo inserimos o mapeador de querystring, indicando qual a chave onde ser informado o formato, e se ele for encontrado, o media type ser
utilizado pelos componentes internos para gerar o resultado no formato que o cliente est solicitando em um local diferente do padro.
C#
publicclassWebApiApplication:System.Web.HttpApplication
{
protectedvoidApplication_Start()
{
WebApiConfig.Register(GlobalConfiguration.Configuration);
this.ConfigMediaTypeMappings(GlobalConfiguration.Configuration);
}
privatevoidConfigMediaTypeMappings(HttpConfigurationconfig)
{
config.Formatters.JsonFormatter.MediaTypeMappings.Add(
newQueryStringMapping("formato","json","application/json"));
config.Formatters.JsonFormatter.MediaTypeMappings.Add(
newQueryStringMapping("formato","xml","application/xml"));
}
}
Com o cdigo acima em funcionamento, a requisio pode ser realizada da seguinte forma:
http://localhost:43139/api/artistas?nome=MaxPezzali&formato=json
http://localhost:43139/api/artistas?nome=MaxPezzali&formato=xml

Customizao
Apesar do Xml e Json serem os principais formatos que temos atualmente, pode haver situaes onde desejamos criar um formato prprio, para que esse possa gerar
e/ou receber o contedo em um formato especfico. Como j percebemos acima, se desejarmos fazer isso, temos que recorrer implementao da classe abstrata
MediaTypeFormatter, customizando basicamente dois mtodos principais OnReadFromStream e OnWriteToStream. Vamos analisar cada um desses mtodos abaixo:
CanReadType: Dado um objeto do tipo Type, este mtodo retorna um valor boleano onde o padro True, indicando se aquele tipo ou no entendido por
aquele formatador. O tipo identifica os eventuais parmetros que existem no mtodo do servio. Aqui podemos fazer validaes, como por exemplo, identificar
se o tipo ou no serializvel, se possui um determinado atributo, etc.
ReadFromStreamAsync: Se o mtodo acima retornar True, ento este mtodo executado. Como parmetro ele recebe o tipo do objeto o mesmo que foi
passado para o mtodo acima, e um objeto do tipo Stream, que fonte das informaes estado do objeto a ser criado. Este mtodo retorna um object, que
corresponde um objeto criado dinamicamente e configurado com os valores provenientes do Stream.
CanWriteType: Dado um objeto do tipo Type, este mtodo retorna um valor boleano padro True, indicando se aquele tipo ou no entendido pelo
formatador. O tipo identifica o retorno do mtodo do servio. Aqui podemos fazer validaes, como por exemplo, identificar se o tipo ou no serializvel, se
possui um determinado atributo, etc.
WriteToStreamAsync: Se o mtodo acima retornar True, ento este mtodo executado. Como parmetro, ele recebe o tipo do objeto a ser serializado e um
object que corresponde a instncia do objeto a ser gravado. Ainda recebemos um Stream, que o destino do objeto serializado.
Como um possvel exemplo, podemos criar um formatador especfico para o formato CSV, que um padro bem tradicional, onde cada valor separado pelo caracter
";". Abaixo temos a classe CsvMediaTypeFormatter, que herda de MediaTypeFormatter. Note a definio do formato application/csv sendo adicionado coleo de
media types suportados por este formatador customizado, que est acessvel atravs da propriedade SupportedMediaTypes.
C#
publicclassCsvMediaTypeFormatter:MediaTypeFormatter
{
privateconstcharSEPARATOR=';';
publicCsvMediaTypeFormatter()
{
this.SupportedMediaTypes.Add(
newMediaTypeHeaderValue("application/csv"));
}

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

47/63

27/06/2016

Minhacoleo
//implementao
}

Como j era esperado, o que precisamos fazer a partir de agora installo execuo. E para isso, recorremos novamente a classe de configurao do ASP.NET Web
API, que atravs da propriedade Formatter que uma coleo, podemos incluir classes que herdam de MediaTypeFormatter. O que fazemos aqui instanciar e
adicionar a classe CsvMediaTypeFormatter:
Formatter
config.Formatters.Add(newCsvMediaTypeFormatter());
Com isso, ao receber ou retornar uma mensagem com o header Accept ou ContentType definido como application/csv, a API j capaz de interpretar e retornar
objetos serializados neste formato.

Veja tambm:
ASP.NET Web API HTTP, REST e o ASP.NET: Para basear todas as funcionalidades expostas pela tecnologia, precisamos ter um conhecimento bsico em relao ao
que motivou tudo isso, contando um pouco da histria e evoluo, passando pela estrutura do protocolo HTTP e a relao que tudo isso tem com o ASP.NET.
ASP.NET Web API Estrutura da API: Entenderemos aqui a template de projeto que o Visual Studio fornece para a construo das APIs, bem como sua estrutura e
como ela se relaciona ao protocolo.
ASP.NET Web API Roteamento: Como o prprio nome diz, o captulo ir abordar a configurao necessria para que a requisio seja direcionada corretamente para
o destino solicitado, preenchendo e validando os parmetros que so por ele solicitado.
ASP.NET Web API Hosting: Um captulo de extrema relevncia para a API. o hosting que d vida API, disponibilizando para o consumo por parte dos clientes, e a
sua escolha interfere diretamente em escalabilidade, distribuio e gerenciamento. Existem diversas formas de se expor as APIs, e aqui vamos abordar as principais
delas.
ASP.NET Web API Consumo: Como a proposta ter uma API sendo consumido por qualquer cliente, podem haver os mais diversos meios bibliotecas de consumir
estas APIs. Este captulo tem a finalidade de exibir algumas opes que temos para este consumo, incluindo as opes que a Microsoft criou para que seja possvel
efetuar o consumo por aplicaes .NET.
ASP.NET Web API Formatadores: Os formatadores desempenham um papel importante na API. So eles os responsveis por avaliar a requisio, extrair o seu
contedo, e quando a resposta devolvida ao cliente, ele entra em ao novamente para formatar o contedo no formato em que o cliente possa entender. Aqui
vamos explorar os formatadores padres que j esto embuitdos, bem como a criao de um novo.
ASP.NET Web API Segurana: Como a grande maioria das aplicaes, temos tambm que nos preocupar com a segurana das APIs. E quando falamos de aplicaes
distribudas, alm da autenticao e autorizao, necessrio nos preocuparmos com a segurana das mensagens que so trocadas entre o cliente e o servio. Este
captulo ir abordar algumas opes que temos disponveis para tornar as APIs mais seguras.
ASP.NET Web API Testes e Tracing: Para toda e qualquer aplicao, temos a necessidade de escrever testes para garantir que a mesma se comporte conforme o
esperado. Isso no diferentes com APIs Web. Aqui iremos abordar os recursos, incluindo a prpria IDE, para a escrita, gerenciamento e execuo dos testes.
ASP.NET Web API Estensibilidade e Arquitetura: Mesmo que j tenhamos tudo o que precisamos para criar e consumir uma API no ASP.NET Web API, a customizao
de algum ponto sempre acaba sendo necessria, pois podemos criar mecanismos reutilizveis, externalizandoos do processo de negcio em si. O ASP.NET Web API
foi concebido com a estensibilidade em mente, e justamente por isso que existe um captulo exclusivo para abordar esse assunto.

| Home | Artigos Tcnicos | Comunidade

2016 Microsoft

ASP.NET Web API Segurana


Israel Aece
Julho 2013
Como qualquer outro tipo de aplicao, servios tambm devem lidar com segurana. E quando falamos em segurana sempre abordamos dois itens: autenticao e
autorizao. A autenticao o processo que consiste em saber quem o usurio , se ele est corretamente cadastrado e configurado, enquanto a autorizao
determina se esse usurio possui permisses para acessar o recurso que ele est solicitando. A autenticao, obrigatoriamente, sempre ocorre antes da autorizao,
pois no h como avaliar/conceder permisses sem antes saber quem ele .
E como se no bastasse isso, quando estamos lidando com aplicaes que encaminham mensagens de um lado para outro, necessrio tambm nos preocuparmos
com a proteo da mesma enquanto ela viaja de um lado ao outro. Neste ponto o protocolo HTTPS ajuda bastante, j que ele popularmente conhecido e a grande
maioria dos hosts e clientes sabem lidar com ele.
Antes de falar sobre as peculiaridades do ASP.NET Web API, precisamos entender alguns conceitos de segurana que existem dentro da plataforma .NET desde a
verso 1.0. Duas interfaces so utilizadas como base para os mecanismos de autenticao e autorizao: IIdentity e IPrincipal namespace System.Security.Principal,
respectivamente. A interface IIdentity fornece trs propriedades autoexplicativas: Name, AuthenticationType e IsAuthenticated. J a segunda possui dois membros que
merecem uma ateno especial. O primeiro deles a propriedade Identity que retorna a instncia de uma classe que implemente a interface IIdentity, representando a
identidade do usurio; j o segundo membro tratase de um mtodo chamado IsInRole que, dado uma papel, retorna um valor boleano indicando se o usurio
corrente possui ou no aquele papel. Como podemos notar, as classes de autenticao e autorizao trabalham em conjunto.
Dentro do namespace System.Threading existe uma classe chamada Thread. Essa classe determina como controlar uma thread dentro da aplicao. Essa classe, entre
vrios membros, possui uma propriedade esttica chamada CurrentPrincipal que recebe e retorna uma instncia de um objeto que implementa a interface IPrincipal.
atravs desta propriedade que devemos definir qual ser a identity e principal que ir representar o contexto de segurana para a thread atual.
H algumas implementaes das interfaces IIdentity e IPrincipal dentro do .NET Framework, como o caso das classes GenericIdentity, WindowsIdentity,
GenericPrincipal e WindowsPrincipal. Essas classes so utilizadas, principalmente, quando queremos implementar no sistema o mecanismo de autorizao baseado em
papis, que dado um papel muitas vezes um departamento, indica se o usurio pode ou no acessar o recurso. Para refinar melhor isso, ao invs de nomearmos por

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

48/63

27/06/2016

Minhacoleo

departamento, podemos definir as sees e funcionalidades do sistema que ele poder acessar/executar.
Em qualquer tipo de projeto ASP.NET, h uma classe chamada HttpContext. Como o prprio nome sugere, essa classe expe uma srie de recursos que estaro
acessvel por todo o ciclo da requisio dentro do servidor, e um desses recursos o contexto de segurana do usurio, que atravs da propriedade User podemos ter
acesso ao objeto IPrincipal que define a credencial do usurio corrente. Essa propriedade tambm estar acessvel quando hospedar a API em um modelo de web
hosting. Quando utilizarmos o selfhosting, temos que recorrer a propriedade CurrentPrincipal da classe Thread. Se precisarmos hospedar a API em ambos os locais,
temos que definir a credencial em ambos os locais, mas no caso do HttpContext, temos que nos certificar que a propriedade esttica Current no seja nula, pois ela
ser se estiver em modo selfhosting.
H diversas formas de trabalhar com autenticao no ASP.NET Web API, onde a maioria j so bastante conhecidas pelos desenvolvedores e padres j estabelecidos
no mercado. Abaixo temos as principais opes:
Basic: A autenticao Basic faz parte da especificao do protocolo HTTP, que define um modelo simples bsico para transmisso de nome de usurio e senha
nas requisies. A sua simplicidade to grande quanto a sua insegurana. Por no haver qualquer meio de proteo hash, criptografia, etc., obriga a sempre
trafegar essas requisies recorrendo segurana do protocolo, e para isso, seremos obrigados a utilizarmos HTTPS.
Digest: Tambm parte da especificao do protocolo HTTP, uma modelo mais seguro quando comparado ao Basic, pois apenas o hash da senha MD5
enviado ao servio.
Windows: Como o prprio nome diz, a autenticao baseada nas credenciais do usurio que est acessando o recurso, baseandose em uma conta no
Windows Active Directory. Entretanto isso apenas til quando estamos acessando a partir de uma intranet onde conseguimos ter um ambiente controlado e
homogneo.
Forms: Desenhado para a internet a autenticao baseada em forms est presente no ASP.NET desde a sua verso 1.0, e baseada em cookies.
At ento somente foi falado sobre os tipos de autenticao, o gerenciamento da identidade e dos objetos que temos a disposio e que representam o usurio, mas
no de como e quando configurar isso. A escolha depender de como e onde quer reutilizar esse mecanismo de autenticao. Se quisermos avaliar em qualquer
modelo de hosting, ento a melhor opo recorrer ao uso de message handlers, que tratase de um pouco de estensibilidade do ASP.NET Web API e que pode rodar
para todas as requisies ou para um determinada rota. Haver um captulo para esgotar este assunto.
Para exemplificar vamos nos basear na autenticao Basic. A ideia criar um handler para interceptar a requisio e extrair o header do HTTP que representa a
credencial informada pelo usurio WWWAuthenticate, e a valida em algum repositrio de sua escolha, como uma base de dados. A partir daqui necessrio
conhecermos como funciona o processo deste modelo, para conseguirmos dialogar com o cliente, para que assim ele consiga coordenar o processo de autenticao
do usurio.

O cliente solicita um recurso pgina, servio, etc. que est protegido.


Ao detectar que o cliente no est autenticado, o servidor exige que ele se autentique e informe as credenciais a partir do modelo Basic. Isso informado a
partir de um header chamado WWWAuthenticate: Basic.
Neste momento, o servidor retorna uma resposta com o cdigo 401 Unauthorized, que instrui o cliente navegador a exigir as credenciais de acesso do
usurio que est acessando o recurso.
Uma vez informado, o browser recria a mesma requisio, mas agora envia nos headers da mesma o login e senha codificados em Base64, sem qualquer
espcie de criptografia. Na resposta, o header enviado o Authorization: Basic [Username+Password Codificado].
Quando este header acima estiver presente, o servidor IIS capaz de validlo no Windows/Active Directory, e se for um usurio vlido, permitir o acesso,
caso contrrio retornar a mesma resposta com cdigo 401, at que ele digite uma credencial vlida.
Como dito acima, o login e a senha no so enviados at que sejam efetivamente exigidos. Nesta customizao, ao identificarmos que o header no est presente na
requisio, precisamos configurar a resposta para o cliente com o cdigo 401, que representa acesso no autorizado, e informar na resposta o mesmo header, para
continuar obrigando o usurio a informar o login e senha.
Para saber se o cliente informou as credenciais, precisamos detectar a presena do header chamado Authorization. Se existir, ento precisamos decodificlo,
utilizando o mtodo FromBase64String da classe Convert, que dado uma string, retorna um array de bytes representando as credenciais separadas por um ":". Depois
disso, tudo o que precisamos fazer separlos, para que assim podermos efetuar a validao em algum repositrio.
Depois de conhecer um pouco mais sobre o processo que ocorre entre cliente e servio, vamos implementar isso no ASP.NET Web API utilizando um message handler,
que a forma que temos para interceptar as requisies que chegam para a API.
C#
publicclassAuthenticationHandler:DelegatingHandler
{
protectedoverrideTask<HttpResponseMessage>SendAsync(
HttpRequestMessagerequest,CancellationTokencancellationToken)
{
stringusername=null;
if(IsValid(request,outusername))
{
varprincipal=newGenericPrincipal(newGenericIdentity(username),null);
Thread.CurrentPrincipal=principal;
if(HttpContext.Current!=null)
HttpContext.Current.User=principal;
returnbase.SendAsync(request,cancellationToken);
}
else
{
returnTask.Factory.StartNew(()=>
{
varr=newHttpResponseMessage(HttpStatusCode.Unauthorized);
r.Headers.Add("WWWAuthenticate","Basicrealm=\"AppTeste\"");
returnr;
});
}
}
}
Ao recepcionar a requisio e ela for vlida, antes dele encaminhar a mesma adiante, para que ela chegue at a ao que o cliente requisitou, ele cria o objeto que
definir a credencial/identidade do usurio que est acessando o recurso. Ao requisitar pela primeira vez e se estivermos consumindo isso em um navegador, ao
receber esse cdigo em conjunto com este header, uma janela aberta para que voc informe o login e senha, que sero encaminhados ao servio.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

49/63

27/06/2016

Minhacoleo

Figura 18 Solicitao de login e senha pelo browser.


Ao interceptar essa requisio, podemos comprovar tudo o que foi escrito acima. Temos a resposta contendo o cdigo 401, e depois de informado o login e senha, a
nova requisio com o header Authorization contendo o valor codificado em Base64.

Figura 19 Headers referente autenticao Basic.


C#
privatestaticboolIsValid(HttpRequestMessagerequest,outstringusername)
{
username=null;
varheader=request.Headers.Authorization;
if(header!=null&&header.Scheme=="Basic")
{
varcredentials=header.Parameter;
if(!string.IsNullOrWhiteSpace(credentials))
{
vardecodedCredentials=
Encoding.Default.GetString(Convert.FromBase64String(credentials));
varseparator=decodedCredentials.IndexOf(':');
varpassword=decodedCredentials.Substring(separator+1);
username=decodedCredentials.Substring(0,separator);
returnusername==password;//Validaoemalgumrepositrio
}
}
returnfalse;
}
A classe ApiController fornece uma propriedade chamada User, que retorna um objeto do tipo IPrincipal. Isso quer dizer que, se precisar extrair as credenciais do
usurio dentro do mtodo/ao, podemos recorrer a ela. E, para finalizar, necessrio incluir este handler na coleo de handlers do servio, atravs do arquivo
Global.asax:
Global.asax
config.MessageHandlers.Add(newAuthenticationHandler());
Depois da autenticao finalizada, de sabermos quem o usurio que est acessando o recurso, chega o momento de controlarmos e sabermos e se ele tem as
devidas permisses para acesso, que o processo de autorizao.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

50/63

27/06/2016

Minhacoleo

O principal elemento que controla o acesso o atributo AuthorizeAttribute namespace System.Web.Http, e pode ser aplicado em um controller inteiro ou
individualmente em cada ao, caso precisemos de um controle mais refinado, ou at mesmo, em nvel global, onde ele deve ser executado/assegurado independente
de qualquer controller ou ao que seja executada dentro daquela aplicao. Este atributo possui duas propriedades: Roles e Users. Cada uma delas recebe um string
com o nome dos papis ou usurios que podem acessar determinado recurso, separados por vrgula.
Pelo fato deste atributo ser um filtro falaremos mais sobre eles abaixo, ele executado diretamente pela infraestrutura do ASP.NET Web API, que ir assegurar que o
usurio est acessando est dentro daqueles nomes colocados na propriedade Users ou que ele esteja contido em algum dos papis que so colocados na
propriedade Roles. E como j era de se esperar, ele extrai as informaes do usurio da propriedade CurrentPrincipal da classe Thread, qual definimos durante o
processo de autenticao, dentro do mtodo SendAsync do handler criado acima.
Depois de saber quem o usurio , podemos extrair as permisses que ele possui, que provavelmente estaro armazenadas em algum repositrio tambm. No
exemplo que vimos acima da autenticao, h um segundo parmetro na classe GenericPrincipal que um array de strings, que representam os papis do usurio.
Abaixo temos aquele mesmo cdigo ligeiramente alterado para buscar pelas permisses do usurio:
C#
varprincipal=
newGenericPrincipal(
newGenericIdentity(username),
CarregarPermissoes(username));
//....
privatestaticstring[]CarregarPermissoes(stringusername)
{
if(username=="Israel")
returnnew[]{"Admin","IT"};
returnnew[]{"Normal"};
}
Como comentado acima, temos trs nveis que podemos aplicar o atributo AuthorizeAttribute: no mtodo, no controller e em nvel global. O cdigo abaixo ilustra o
uso destas trs formas de utilizao:
C#
//NveldeMtodo
publicclassClientesController:ApiController
{
[Authorize(Roles="Admin,IT")]
publicIEnumerable<Cliente>Get()
{
//...
}
}
//NveldeController
[Authorize(Roles="Admin")]
publicclassClientesController:ApiController
{
publicIEnumerable<Cliente>Get()
{
//...
}
}
//NvelGlobal
config.Filters.Add(newAuthorizeAttribute());
E se quisermos refinar ainda mais a autorizao, podemos levar a validao disso para dentro do mtodo. Basta remover o atributo e recorrer ao mtodo IsInRole
atravs da propriedade User, que dado o nome do papel, retorna um valor boleano indicando se o usurio atual est ou no contido nele.
C#
publicIEnumerable<Cliente>Get()
{
if(User.IsInRole("Admin"))
//Retornartodososclientes.
//Retornarapenasosclientesdacarteira
}
Somente o fato de utilizar o atributo AuthorizeAttribute aplicado em alguns dos nveis que vimos, o suficiente para que o ASP.NET Web API consiga assegurar que
ele somente aquele determinado mtodo/controller se ele estiver autenticado, independente dos papis que ele possua. Se quisermos flexibilizar o acesso alguns
mtodos, podemos recorrer ao atributo AllowAnonymousAttribute para conceder o acesso um determinado mtodo, mesmo que o controller esteja marcado com o
atributo AuthorizeAttribute.

Veja tambm:
ASP.NET Web API HTTP, REST e o ASP.NET: Para basear todas as funcionalidades expostas pela tecnologia, precisamos ter um conhecimento bsico em relao ao
que motivou tudo isso, contando um pouco da histria e evoluo, passando pela estrutura do protocolo HTTP e a relao que tudo isso tem com o ASP.NET.
ASP.NET Web API Estrutura da API: Entenderemos aqui a template de projeto que o Visual Studio fornece para a construo das APIs, bem como sua estrutura e
como ela se relaciona ao protocolo.
ASP.NET Web API Roteamento: Como o prprio nome diz, o captulo ir abordar a configurao necessria para que a requisio seja direcionada corretamente para
o destino solicitado, preenchendo e validando os parmetros que so por ele solicitado.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

51/63

27/06/2016

Minhacoleo

ASP.NET Web API Hosting: Um captulo de extrema relevncia para a API. o hosting que d vida API, disponibilizando para o consumo por parte dos clientes, e a
sua escolha interfere diretamente em escalabilidade, distribuio e gerenciamento. Existem diversas formas de se expor as APIs, e aqui vamos abordar as principais
delas.
ASP.NET Web API Consumo: Como a proposta ter uma API sendo consumido por qualquer cliente, podem haver os mais diversos meios bibliotecas de consumir
estas APIs. Este captulo tem a finalidade de exibir algumas opes que temos para este consumo, incluindo as opes que a Microsoft criou para que seja possvel
efetuar o consumo por aplicaes .NET.
ASP.NET Web API Formatadores: Os formatadores desempenham um papel importante na API. So eles os responsveis por avaliar a requisio, extrair o seu
contedo, e quando a resposta devolvida ao cliente, ele entra em ao novamente para formatar o contedo no formato em que o cliente possa entender. Aqui
vamos explorar os formatadores padres que j esto embuitdos, bem como a criao de um novo.
ASP.NET Web API Segurana: Como a grande maioria das aplicaes, temos tambm que nos preocupar com a segurana das APIs. E quando falamos de aplicaes
distribudas, alm da autenticao e autorizao, necessrio nos preocuparmos com a segurana das mensagens que so trocadas entre o cliente e o servio. Este
captulo ir abordar algumas opes que temos disponveis para tornar as APIs mais seguras.
ASP.NET Web API Testes e Tracing: Para toda e qualquer aplicao, temos a necessidade de escrever testes para garantir que a mesma se comporte conforme o
esperado. Isso no diferentes com APIs Web. Aqui iremos abordar os recursos, incluindo a prpria IDE, para a escrita, gerenciamento e execuo dos testes.
ASP.NET Web API Estensibilidade e Arquitetura: Mesmo que j tenhamos tudo o que precisamos para criar e consumir uma API no ASP.NET Web API, a customizao
de algum ponto sempre acaba sendo necessria, pois podemos criar mecanismos reutilizveis, externalizandoos do processo de negcio em si. O ASP.NET Web API
foi concebido com a estensibilidade em mente, e justamente por isso que existe um captulo exclusivo para abordar esse assunto.

| Home | Artigos Tcnicos | Comunidade

2016 Microsoft

ASP.NET Web API Testes e Tracing


Israel Aece
Julho 2013
importante testarmos a maioria dos cdigos que escrevemos, e quando estamos falando em testes, no estamos necessariamente nos referindo sobre testes de alto
nvel, onde colocamos o usurio para realizar os testes. Nos referimos a testes automatizados, onde conseguimos escrever cdigos para testar cdigos, possibilitando
a criao de diversos cenrios para se certificar de que tudo funcione como esperado.
Como comentamos no decorrer dos captulos anteriores, o ASP.NET Web API possibilita a construo de servios de modelo tradicional, ou seja, definir tipos que
refletem o nosso negcio Cliente, Produto, Pedido, etc., bem como tipos mais simples inteiro, string, boleano, etc.. Como sabemos, a finalidade conseguir
desenhar um servio que nada saiba sobre a infraestrutura, como ele exposto, caractersticas, etc.
Ainda temos a possibilidade de receber e/ou retonar objetos que refletem e fazem uso de algumas informaes do protocolo HTTP, que um detalhe muito
importante na estrutura REST. Ao utilizar as classes que descrevem a requisio HttpRequestMessage e a resposta HttpResponseMessage, podemos interagir com
detalhes do protocolo.
No h muito mistrio em aplicar testes em cima da classe que representa o servio quando estamos lidando com tipos customizados. Isso se deve ao fato de que
neste modelo, como so simples classes, com mtodos que executam tarefas e, eventualmente, retornam algum resultado, isso acaba sendo tratado como sendo uma
classe de negcio qualquer.
Mas e quando queremos receber e/ou enviar dados para este servio, utilizando instncias das classes HttpRequestMessage e HttpResponseMessage? Felizmente,
assim como no ASP.NET MVC, a Microsoft desenvolveu o ASP.NET Web API com a possibilidade de testlo sem estar acoplado infraestrutura do ASP.NET, o que
permite testar a classe do servio, mesmo que ela receba ou devolva objetos caractersticos do protocolo HTTP.
Supondo que temos um servio que possui dois mtodos Ping e PingTipado, podemos escrever testes e, consequentemente, utilizar a IDE do Visual Studio para
executlos, e como isso, nos antecipamos eventuais problemas que possam acontecer, pois talvez seja possvel capturar alguns desses problemas antes mesmo de
levar o mesmo ao ambiente de produo.
C#
publicclassServicoDeExemplo:ApiController
{
publicHttpResponseMessagePing(HttpRequestMessagerequest)
{
returnnewHttpResponseMessage()
{
StatusCode=HttpStatusCode.OK,
Content=newStringContent(request.Content.ReadAsStringAsync().Result)
};
}
publicHttpResponseMessagePingTipado(HttpRequestMessagerequest)
{
if(request.Content==null)
returnrequest.CreateErrorResponse(HttpStatusCode.BadRequest,
newHttpError("Contedonodefinido"));
returnnewHttpResponseMessage()
{
StatusCode=HttpStatusCode.OK,
Content=
newObjectContent<Informacao>(
request.Content.ReadAsAsync<Informacao>().Result,
newJsonMediaTypeFormatter())
};

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

52/63

27/06/2016

Minhacoleo
}
}

No primeiro exemplo, estamos testando o mtodo Ping, instanciando a classe que representa o servio, e passando ao mtodo Ping a instncia da classe
HttpRequestMessage. Neste momento, poderamos abastecer informaes na coleo de headers da requisio, com o intuito de fornecer tudo o que necessrio
para o que o mtodo/teste possa executar com sucesso. Depois da requisio realizada, verificamos se o status da resposta corresponde ao status OK. Alm disso
verificamos tambm se o contedo da resposta est igual informao que enviamos.
C#
[TestMethod]
publicvoidDadoUmaRequisicaoSimplesDeveRetornarStatusComoOK()
{
varinfo="teste";
varresponse=newServicoDeExemplo().Ping(newHttpRequestMessage()
{
Content=newStringContent(info)
});
Assert.AreEqual(HttpStatusCode.OK,response.StatusCode);
Assert.AreEqual(info,response.Content.ReadAsStringAsync().Result);
}
O prximo passo construir um teste para o mtodo PingTipado. Esse mtodo recebe como parmetro a instncia da classe HttpRequestMessage, definindo o
contedo uma instncia da classe ObjectContent<T>, onde definimos o tipo genrio T como sendo do tipo Informacao. A finalidade do teste assegurar que, se
passarmos uma instncia nula da classe Informacao, uma resposta ser retornada definindo o cdigo de status como 400 Bad Request.
C#
[TestMethod]
publicvoidDadoUmObjetoInfoNuloDeveRetornarComoErro()
{
varresponse=
newServicoDeExemplo().PingTipado(newHttpRequestMessage());
Assert.AreEqual(HttpStatusCode.BadRequest,response.StatusCode);
}
Finalmente, o prximo passo consiste em criar um teste, tambm para o mtodo PingTipado, mas agora fornecendo a instncia do objeto Informacao em um estado
vlido, para que o teste possa suceder se o servio retornar a mesma instncia da classe Informacao, onde os membros da requisio reflitam o que est sendo
retornado como reposta. Abaixo o cdigo que efetua o tal teste:
C#
[TestMethod]
publicvoidDadoUmObjetoInfoDeveRetornarEleComInformacoesExtra()
{
varinfo=newInformacao(){Codigo="123",Dado="AlgumaInfo"};
varresponse=
newServicoDeExemplo()
.PingTipado(newHttpRequestMessage()
{
Content=
newObjectContent<Informacao>(info,newJsonMediaTypeFormatter())
})
.Content
.ReadAsAsync<Informacao>().Result;
Assert.AreEqual(info.Dado,response.Dado);
}
Para abstrair ainda o que est sendo testado, a Microsoft criou uma interface chamada IHttpActionResult, que encapsula o resultado dos retornos de aes. A
implementao desta classe ser responsvel por criar a mensagem de retorno, e a ao dentro do controller passa a retornar uma classe que implemente esta
interface, facilitando os testes unitrios. O ASP.NET j est preparado para tambm entender este tipo resultado, processando o retorno normalmente.
J temos nativamente cinco implementaes: FormattedContentResult<T>, NegotiatedContentResult<T>, StatusCodeResult, ContinuationResult e MessageResult.
Cada uma delas responsvel por receber um determinado tipo de resultado, preparlo e repassar para o sistema de testes ou para o pipeline ASP.NET um tipo
genrico, que nada mais que a instncia da classe HttpResponseMessage.
C#
publicIHttpActionResultGet(stringnome)
{
varartista=
newArtista(){Id=12,Nome=nome};
returnnewFormattedContentResult<Artista>(
HttpStatusCode.OK,
artista,
newJsonMediaTypeFormatter(),
newMediaTypeHeaderValue("application/json"),
this.Request);
}
Estamos recorrendo classe FormattedContentResult<T> para retornar a instncia da classe Artista no formato Json e com status de nmero 200 OK. O ASP.NET

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

53/63

27/06/2016

Minhacoleo

entender o retorno normalmente, e quando estivermos criando os testes unitrios para esta ao, independente do tipo de retorno que ela internamente definda um
objeto customizado, uma string, etc., os testes sempre iro lidar a instncia da classe HttpResponseMessage, e a partir dela, realizar todas as conferncias necessrias
para determinar se os testes executaram com sucesso ou no.
C#
[TestMethod]
publicvoidDeveRetornarRespostaCorreta()
{
using(varrequest=newHttpRequestMessage())
{
varnome="MaxPezzali";
varresponse=
newArtistasController(){Request=request}
.Get(nome)
.ExecuteAsync(CancellationToken.None)
.Result;
Assert.AreEqual(HttpStatusCode.OK,response.StatusCode);
Assert.AreEqual(nome,response.Content.ReadAsAsync<Artista>().Result.Nome);
}
}
O que vimos at agora neste captulo consiste em realizar os testes apenas nas classes que representam os servios. Como os servios REST usam o HTTP como parte
do processo, muitas vezes somente a execuo do controller o suficiente para entender que ele foi executado com sucesso, o que nos obriga a recorrer recursos do
prprio HTTP para complementar a tarefa que est sendo executada e, consequentemente, tambm devemos compor isso em nossos testes.
Felizmente, pelo fato do ASP.NET Web API ser complemente desvinculado da infraestrutura, isso nos permite considerar os objetos que representam o proxy do
cliente e o hosting do servio nos testes, e validar se ao enviar, processar e retornar uma determinada requisio, se ela passa por todas os estgios de processamento
dentro do pipeline do ASP.NET.
Os objetos HttpServer e o HttpClient foram construdos totalmente desvinculados de qualquer necessidade de somente executlos em ambiente real. Com isso,
podemos fazer uso destes mesmos objetos em um projeto de testes, onde podemos simular a mesma estrutura de objetos, suas configuraes e seus interceptadores,
que ao executar os testes, a requisio e resposta percorrero todo o fluxo que percorreria quando ele for colocado em produo.
Para exemplificar isso, vamos considerar que temos um servio que possui apenas dois mtodos: um onde ele adiciona um objeto Cliente em um repositrio qualquer,
e outro que dado o Id deste Cliente, ele retorna o respectivo registro. No vamos nos preocupar neste momento com boas prticas, mas no interior do controller
podemos visualizar o repositrio criado e sendo utilizado pelos dois mtodos.
C#
publicclassClientesController:ApiController
{
privatestaticRepositorioDeClientesrepositorio=newRepositorioDeClientes();
[HttpGet]
publicClienteRecuperar(intid)
{
returnrepositorio.RecuperarPorId(id);
}
[HttpPost]
publicHttpResponseMessageAdicionar(HttpRequestMessagerequest)
{
varcliente=request.Content.ReadAsAsync<Cliente>().Result;
repositorio.Adicionar(cliente);
varresposta=Request.CreateResponse<Cliente>(HttpStatusCode.Created,cliente);
resposta.Headers.Location=
newUri(string.Format("http://xpto/Clientes/Recuperar/{0}",cliente.Id));
returnresposta;
}
}
Depois do servio criado resta hospedarmos e consumirmos o mesmo atravs do projeto de testes.
C#
[TestClass]
publicclassAcessoAosClientes
{
privatestaticHttpConfigurationconfiguracao;
privatestaticHttpServerservidor;
privatestaticHttpClientproxy;
[ClassInitialize]
publicstaticvoidInicializar(TestContextcontext)
{
configuracao=newHttpConfiguration();
configuracao.Routes.MapHttpRoute(
name:"DefaultApi",
routeTemplate:"{controller}/{action}/{id}"
);
servidor=newHttpServer(configuracao);
proxy=newHttpClient(servidor);
}

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

54/63

27/06/2016

Minhacoleo
[TestMethod]
publicvoidDeveSerCapazDeFazerPingComUmNovoRegistro()
{
varresultadoDaCriacao=
proxy.PostAsync(
"http://xpto/Clientes/Adicionar",
newStringContent(
"{\"Nome\":\"Israel\",\"Cidade\":\"Valinhos\"}",
Encoding.Default,"application/json"))
.Result;
Assert.AreEqual(HttpStatusCode.Created,resultadoDaCriacao.StatusCode);
Assert.IsNotNull(resultadoDaCriacao.Headers.Location);
varresultadoDaBusca=proxy.GetAsync(resultadoDaCriacao.Headers.Location).Result;
varcliente=resultadoDaBusca.Content.ReadAsAsync<Cliente>().Result;
Assert.AreEqual(1,cliente.Id);
Assert.AreEqual("Israel",cliente.Nome);
Assert.AreEqual("Valinhos",cliente.Cidade);
}
[ClassCleanup]
publicstaticvoidFinalizar()
{
proxy.Dispose();
servidor.Dispose();
}
}

As classes que representam o proxy e o hosting so declarados em nvel de classe teste. interessante notar a construo destes objetos realizada durante a
incializao da classe que representa o teste. No construtor do hosting HttpServer recebe como parmetro as configuraes para o servio; j a classe HttpClient
recebe como parmetro o HttpServer, para que internamente, quando solicitarmos a requisio para este cliente, ele encaminhe para o servio. A URI aqui pouco
importa, j que o trfego ser realizado diretamente. Isso possvel porque a classe HttpServer herda da classe HttpMessageHandler.

Dependncias
No h como falarmos de testes unitrios sem que se tenha uma API que seja bem construda. As boas prticas pregam que uma classe no deve ter mais
responsabilidade do que seu propsito, ou seja, se voc tem uma API que expe as msicas de um determinado lbum, ela a API deve coordenar como essa listagem
ser montada, mas no responsabilidade dela conhecer detalhes, por exemplo, do banco de dados.
Ao desenhar uma classe, antes de colocar um cdigo dentro dela, necessrio analisar se ela quem deveria realizar essa atividade. Quanto mais a classe depender de
uma abstrao ao invs de uma implementao, ser muito mais fcil substituir isso durante a escrita dos testes. No exemplo abaixo temos um controller que
necessita de um repositrio para extrair o lbum de um artista.
C#
publicinterfaceIRepositorio
{
AlbumBuscarAlbumPor(stringartista);
}
publicclassArtistasController:ApiController
{
privatereadonlyIRepositoriorepositorio;
publicArtistas(IRepositoriorepositorio)
{
this.repositorio=repositorio;
}
[HttpGet]
publicAlbumRecuperarAlbum(stringartista)
{
returnthis.repositorio.BuscarAlbumPor(artista);
}
}
Durante a escrita dos testes unitrios, podemos criar e passar classe Artistas uma representao em memria do repositrio e, consequentemente, avaliar se o
mtodo RecuperarAlbum est atendendo o necessidade. A questo como isso ser realizado durante a execuo da API.
Felizmente o ASP.NET Web API j possui internamente um local onde podemos adicionar todas as dependncias do nosso controller, que durante a execuo, ele ser
capaz de analisar a necessidade, construir o objeto, e entreglo API para que seja utilizada. Para isso temos a interface IDependencyResolver namespace
System.Web.Http.Dependencies, qual podemos utilizar para customizar a criao dos controllers, onde poderemos abastecer manualmente toda a necessidade que
cada um possui.
C#
publicclassHardcodeResolver:IDependencyResolver
{
publicIDependencyScopeBeginScope()
{
returnthis;
}
publicobjectGetService(TypeserviceType)
{
if(serviceType==typeof(ArtistasController))

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

55/63

27/06/2016

Minhacoleo
returnnewArtistasController(newRepositorioXml("Artistas.xml"));
returnnull;
}
publicIEnumerable<object>GetServices(TypeserviceType)
{
returnnewList<object>();
}
publicvoidDispose(){}
}

Para que a classe HardcodeResolver funcione durante a execuo, temos que apontar ao ASP.NET Web API que o objeto que criar a instncia da classe que
representar a API, resolver todas as dependncias e entregar para atender as requisies ela. Novamente vamos recorrer ao objeto de configurao, que atravs da
propriedade DependencyResolver podemos definir qualquer classe que implemente a interface IDependencyResolver.
C#
config.DependencyResolver=newHardcodeResolver();
Os mtodos BeginScope e Dispose so utilizados para controlar o tempo de vida dos objetos que so criados. Quando o controller ou qualquer objeto que ele seja
capaz de resolver e criar criado, podemos criar um objeto que define um escopo para ele, e aps o runtime utilizlo, ele devolvido para que seja adequadamente
descartado, incluindo suas dependncias internas que ela possa utilizar. Isso pode ser til quando est utilizando algum container de inverso de controle IoC. Se os
objetos criados no tiverem a necessidade de gerenciamento de escopo para o descarte de recursos, ento podemos retornar o this.
Tracing
Tracing a forma que temos para monitorar a execuo da aplicao enquanto ela est rodando. Isso extremamente til para diagnosticar problemas que ocorrem
em tempo de execuo, e que geralmente, por algum motivo especfico faz com que a aplicao no se comporte como esperado.
O ASP.NET Web API j traz um mecanismo de captura extremamente simples de se trabalhar e to poderoso quanto. Tudo acaba sendo realizado atravs da interface
ITraceWriter namespace System.Web.Http.Tracing, que dado uma implementao dela, o ASP.NET Web API captura detalhes referentes as mensagens HTTP e
submete para que ela armazene no local de sua escolha.
Ele no vem com nenhuma implementao nativa, o que nos obriga a criar uma e acoplarmos execuo. Isso nos permitir escolher qualquer meio de logging, como
por exemplo o log4net, ETW, Logging Application Block, System.Diagnostics, etc. Esta interface fornece um nico mtodo chamado Trace, que recebe os seguintes
parmetros:
request: recebe o objeto HttpRequestMessage associado com as informaes que sero coletadas.
category: uma string que determina a categoria em que as informao sero gravadas, permitindo agrupar informaes que est relacionadas em pontos
distintos da coleta.
level: um enumerador com as opes j conhecidas que definem o nvel de severidade da informao.
traceAction: representa um delegate que permite ao chamador definir qualquer ao, que ser executada quando o mecanismo de trace decidir coletar alguma
informao.
Para termos uma ideia das informaes que so coletadas, abaixo temos um logging que se exibe as informaes em uma aplicao console. A utilizao da aplicao
console para mostrar o funcionamento do mecanismo, mas como j falado acima, poderamos criar vrias implementaes. Quando estamos lidando com aplicaes
do mundo real, necessrio recorrermos a alguma biblioteca j existente e que faa grande parte do trabalho para armazenar e, principalmente, fornea uma forma
simples para monitorar.
C#
publicclassConsoleLogging:ITraceWriter
{
publicvoidTrace(HttpRequestMessagerequest,stringcategory,
TraceLevellevel,Action<TraceRecord>traceAction)
{
varrecord=newTraceRecord(request,category,level);
traceAction(record);
View(record);
}
privatevoidView(TraceRecordrecord)
{
Console.WriteLine(record.RequestId);
Console.WriteLine("{0}{1}",record.Category,record.Level);
Console.WriteLine("{0}{1}",record.Request.Method,record.Request.RequestUri);
Console.WriteLine("{0}{1}",record.Operator,record.Operation);
Console.WriteLine();
}
}
A classe TraceRecord representa um item de rastreamento e ele que deve ser catalogado para futuras anlises. No interior do mtodo Trace construmos o objeto
TraceRecord e antes de passarmos para o delegate traceAction, podemos customizar com informaes especficas. E no exemplo acima, depois de configurado o
TraceRecord, exibimos as propriedades deste projeto na console:

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

56/63

27/06/2016

Minhacoleo

Figura 20 Logs sendo exibidos na console.


claro que a implementao no suficiente para que tudo isso funcione. Para que ele seja acionado, necessrio acoplarmos execuo, e para isso, recorremos ao
objeto de configurao do ASP.NET Web API. Neste momento, tudo o que precisamos saber para que o logging customizado funcione adicionar o seguinte
comando na configurao da API:
C#
config.Services.Replace(typeof(ITraceWriter),newConsoleLogging());
E para finalizar, como pudemos perceber, somente informaes inerentes aos estgios do processamento da requisio foram logados. E se desejarmos tambm
incluir informaes referentes as regraas de negcio, ou melhor, incluir informaes que so geradas no interior do controller? A classe ApiController possui uma
propriedade chamada Configuration, que expe o objeto de configurao a API e, consequentemente, nos permite acessar o tracing para incluir qualquer informao
que achemos importante e necessrio para quando precisarmos monitorar.
Para facilitar a insero destas informaes customizadas, a Microsoft incluiu uma classe esttica com mtodos de estenses interface ITraceWriter com mtodos
nomeados com as severidades.
C#
usingSystem.Web.Http;
usingSystem.Web.Http.Tracing;
publicclassTestController:ApiController
{
publicstringGet()
{
this.Configuration
.Services
.GetTraceWriter()
.Info(this.Request,"Aes","AlgumaInfo","xpto");
return"test";
}
}

Figura 21 Informao customizada sendo exibida.

Veja tambm:
ASP.NET Web API HTTP, REST e o ASP.NET: Para basear todas as funcionalidades expostas pela tecnologia, precisamos ter um conhecimento bsico em relao ao
que motivou tudo isso, contando um pouco da histria e evoluo, passando pela estrutura do protocolo HTTP e a relao que tudo isso tem com o ASP.NET.
ASP.NET Web API Estrutura da API: Entenderemos aqui a template de projeto que o Visual Studio fornece para a construo das APIs, bem como sua estrutura e
como ela se relaciona ao protocolo.
ASP.NET Web API Roteamento: Como o prprio nome diz, o captulo ir abordar a configurao necessria para que a requisio seja direcionada corretamente para
o destino solicitado, preenchendo e validando os parmetros que so por ele solicitado.
ASP.NET Web API Hosting: Um captulo de extrema relevncia para a API. o hosting que d vida API, disponibilizando para o consumo por parte dos clientes, e a
sua escolha interfere diretamente em escalabilidade, distribuio e gerenciamento. Existem diversas formas de se expor as APIs, e aqui vamos abordar as principais
delas.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

57/63

27/06/2016

Minhacoleo

ASP.NET Web API Consumo: Como a proposta ter uma API sendo consumido por qualquer cliente, podem haver os mais diversos meios bibliotecas de consumir
estas APIs. Este captulo tem a finalidade de exibir algumas opes que temos para este consumo, incluindo as opes que a Microsoft criou para que seja possvel
efetuar o consumo por aplicaes .NET.
ASP.NET Web API Formatadores: Os formatadores desempenham um papel importante na API. So eles os responsveis por avaliar a requisio, extrair o seu
contedo, e quando a resposta devolvida ao cliente, ele entra em ao novamente para formatar o contedo no formato em que o cliente possa entender. Aqui
vamos explorar os formatadores padres que j esto embuitdos, bem como a criao de um novo.
ASP.NET Web API Segurana: Como a grande maioria das aplicaes, temos tambm que nos preocupar com a segurana das APIs. E quando falamos de aplicaes
distribudas, alm da autenticao e autorizao, necessrio nos preocuparmos com a segurana das mensagens que so trocadas entre o cliente e o servio. Este
captulo ir abordar algumas opes que temos disponveis para tornar as APIs mais seguras.
ASP.NET Web API Testes e Tracing: Para toda e qualquer aplicao, temos a necessidade de escrever testes para garantir que a mesma se comporte conforme o
esperado. Isso no diferentes com APIs Web. Aqui iremos abordar os recursos, incluindo a prpria IDE, para a escrita, gerenciamento e execuo dos testes.
ASP.NET Web API Estensibilidade e Arquitetura: Mesmo que j tenhamos tudo o que precisamos para criar e consumir uma API no ASP.NET Web API, a customizao
de algum ponto sempre acaba sendo necessria, pois podemos criar mecanismos reutilizveis, externalizandoos do processo de negcio em si. O ASP.NET Web API
foi concebido com a estensibilidade em mente, e justamente por isso que existe um captulo exclusivo para abordar esse assunto.

| Home | Artigos Tcnicos | Comunidade

2016 Microsoft

ASP.NET Web API Estensibilidade e Arquitetura


Israel Aece
Julho 2013
Para que seja possvel tirar um maior proveito do que qualquer biblioteca ou framework tem a oferecer, termos o conhecimento mais profundo de sua arquitetura.
Apesar de ser opcional no primeiro momento, de grande importncia o conhecimento destes mecanismos, pois podem ser teis durante alguma depurao que seja
necessria ou durante a estenso de algum ponto para uma eventual customizao, algo que tambm ser abordado neste captulo.
O entendimento da arquitetura nos dar uma viso bem detalhada do processamento das mensagens, sabendo o ponto correto para interceptar uma requisio a fim
customizar algum elemento, interferir na escolha de alguma ao, aplicao de segurana autenticao e autorizao, implementar uma camada de caching, etc.
Muito desses pontos j vimos no decorrer dos captulos anteriores, e a prprio Microsoft fez uso deles para implementar algum elementos que j esto embutidos no
ASP.NET Web API.
Antes de falarmos sobre a arquitetura do ASP.NET Web API, precisamos recapitular de forma resumida como a infraestrutura do ASP.NET, e depois disso,
veremos a bifurcao onde temos o desvio para o MVC, Web Forms e Web API.
Tudo comea com a criao da classe HttpApplication, que o objeto que ir coordenar e gerenciar toda a execuo das requisies que chegam para uma aplicao.
Dentro deste objeto temos uma coleo de mdulos, que so classes que implementam a interface IHttpModule, que so como filtros onde podemos examinar e
modificar o contedo da mensagem que chega e que parte atravs do pipeline.
Depois que a mensagem passar pelos mdulos, chega o momento de escolher o handler que tratar a requisio. O handler o alvo da requisio, que ir receber a
requisio e tratla, e devolver a resposta. Os handlers implementam a interface IHttpHandler ou IHttpAsyncHandler para implementao assncrona, e existem
diversas classes dentro do ASP.NET, onde uma trata a requisio para uma pgina do Web Forms, para uma aplicao MVC, para um servio ASMX, etc. Depois do
handler executado, a mensagem de retorno gerada, passa pelos mdulos que interceptam o retorno, e parte para o cliente que solicitou o recurso.

Figura 22 Caminho percorrido pela requisio nos mdulos e handlers.


Independentemente de qual recurso ser acessado, o estgio inicial comum para todos eles. Tudo o que falamos at aqui vale para quando estamos utilizando o
hosting baseado na web IIS/ASP.NET. No caso de selfhosting, onde hospedamos a API em nosso prprio processo, o caminho para a ser igual.

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

58/63

27/06/2016

Minhacoleo

Figura 23 Comparao entre web e selfhosting.


Como h comentado anteriormente, a classe HttpSelfHostServer que herda da classe HttpServer, utilizada quando optamos pelo modelo de selfhosting, faz uso de
recursos fornecidos pelo WCF, e depois de coletar as informaes que chegam at o servio, ele cria e passa adiante a instncia da classe HttpRequestMessage.
importante notar que do lado do webhosting temos a classe HttpControllerHandler, que a implementao da classe IHttpHandler, responsvel por materializar a
requisio HttpRequest no objeto do tipo HttpRequestMessage, enviandoa para a classe HttpServer.
Depois que a requisio pela classe HttpServer, um novo pipeline iniciado, que possui vrios pontos, e o primeiro deles chamado de Message Handlers. Como o
prprio nome diz, eles esto logo no primeiro estgio do pipeline, ou seja, independentemente de qual sua inteno para com o servio, elas sero sempre sero
executadas, a menos que haja algum critrio que voc avalie e rejeite a solicitao, o que proibir o avano do processamento para os prximos handlers.
Basicamente esses handlers recebem a instncia de uma classe do tipo HttpRequestMessage, que traz toda a solicitao do usurio, e retornam a instncia da classe
HttpResponseMessage, contendo a resposta gerada para aquela solicitao. E como j ficou subententido, podemos ter vrios handlers adicionados ao pipeline, onde
cada um deles pode ser responsvel por executar uma tarefa distinta, como logging, autenticao, autorizao, etc. A imagem abaixo ilustra esse fluxo:

Figura 24 Estrutura dos message handlers.


Para a criao que um message handler customizado, necessrio herdar da classe abstrata DelegatingHandler. Essa classe pode receber em seu construtor um objeto
do tipo HttpMessageChannel. A finalidade deste objeto que passado no construtor, com o intuito de cada handler seja responsvel por executar uma determinada
tarefa, e depois passar para o prximo, ou seja, uma implementao do padro Decorator.
C#
publicclassApiKeyVerification:DelegatingHandler
{
privateconststringApiKeyHeader="ApiKey";
privatestaticstring[]ValidKeys=newstring[]{"18372","92749"};
protectedoverrideTask<HttpResponseMessage>SendAsync(
HttpRequestMessagerequest,CancellationTokencancellationToken)
{
if(IsValidKey(request))
returnbase.SendAsync(request,cancellationToken);
returnTask.Factory.StartNew(()=>
newHttpResponseMessage(HttpStatusCode.Unauthorized));
}
privatestaticboolIsValidKey(HttpRequestMessagerequest)
{
varheader=request.Headers.FirstOrDefault(h=>h.Key==ApiKeyHeader);
return
header.Value!=null&&
ValidKeys.Contains(header.Value.FirstOrDefault());
}
}

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

59/63

27/06/2016

Minhacoleo

A classe acima intercepta a requisio e procura se existe um header chamado ApiKey. Se no houver ou se existir e no for uma chamada vlida, ele rejeita a
requisio retornando o cdigo 401 Unauthorized ao cliente, que significa que ele no est autorizado a visualizar o contedo. importante ressaltar que se a chave
no for vlida, a requisio no vai adiante, ou seja, ela j abortada quando a primeira inconsistncia for encontrada.
Podemos acoplar os message handlers em dois nveis para serem executados. Eles podem ser globais, que como o prprio nome sugere, sero executadas para todas
as requisies que chegam a API, ou serem especficos para uma determinada rota. No primeiro caso, a instncia do message handler adicionada coleo de
handlers, atravs da propriedade MessageHandlers. J a segunda opo, recorremos um overload do mtodo MapHttpRoute, onde em seu ltimo parmetro temos
a opo de incluir o message handler especfico para ela. Abaixo temos o exemplo de como fazemos para utilizar uma ou outra opo:
message handler
//Global
config.MessageHandlers.Add(newApiKeyVerification());
//Porrota
config.Routes.MapHttpRoute(
name:"Default",
routeTemplate:"api/{controller}",
defaults:null,
constraints:null,
handler:
HttpClientFactory.CreatePipeline(
newHttpControllerDispatcher(config),
newDelegatingHandler[]{newApiKeyVerification()}));
Se encaminharmos a requisio com uma chave invlida, podemos perceber que no somos autorizados a acessar o recurso. A partir do momento que colocamos uma
chave que o servio entende como vlida, o resultado retornado. A imagem abaixo comprova essa anlise.

Figura 25 Headers customizados para controle de acesso.


Existem dois message handlers embutidos no ASP.NET Web API que desempenham um papel extremamente importante no pipeline. O primeiro deles
HttpRoutingDispatcher, que avalia se existe um message handler especfico para a rota que foi encontrada. Se houver, ele deve ser executado.
Caso no seja, a requisio e encaminhada para um outro message handler chamado HttpControllerDispatcher. Uma vez que passamos por todos os handlers
configurados, este ser responsvel por encontrar e ativar o controller. No cdigo acima mencionamos a classe HttpControllerDispatcher quando configuramos o
message handler ApiKeyVerification em nvel de rota.
A procura, escolha e ativao do controller so tarefas realizadas por elementos que tambm so estensveis. Eles so representados pelas seguintes interfaces:
IHttpControllerSelector e IHttpControllerActivator. Depois do controller encontrado, o momento de saber qual ao mtodo dentro dele ser executada. Da mesma
forma, se quisermos customizar, basta recorrer a implementao da interface IHttpActionSelector.
Acima vimos os message handlers no contexto do lado do servidor, mas pela simetria que existe na codificao do servidor comparado ao cliente, podemos recorrer
aos mesmos recursos para interceptar e manipular tanto a requisio quanto a resposta do lado do cliente. O construtor da classe HttpClient pode receber como
parmetro a instncia de uma classe do tipo HttpMessageHandler. Ao omitir qualquer inicializao, por padro, o handler padro o HttpClientHandler, que herda de
HttpMessageHandler, que responsvel pela comunicao com o HTTP, j em nvel de rede.
Se quisermos customizar, incluindo handlers para analisar e/ou alterar a sada ou o retorno da requisio no cliente, podemos recorrer ao mtodo de estenso
chamado Create da classe HttpClientFactory, que recebe um array contendo todos os handlers que sero disparados, quais sero disparados em ordem inversa ao que
inserido na coleo. Este mesmo mtodo faz o trabalho para tambm inserir o handler HttpClientHandler que se faz necessrio em qualquer situao.
C#
using(varclient=
HttpClientFactory.Create(newValidacaoDeSessao()))
{
//...
}
publicclassValidacaoDeSessao:DelegatingHandler
{
//...
}

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

60/63

27/06/2016

Minhacoleo

Figura 26 Estrutura dos message handlers do lado do cliente.


Apesar do controller e a ao dentro dele terem sido encontrados, podemos ainda realizar alguma espcie de interceptao para que ainda faamos alguma tarefa
antes de executarmos a ao. Eis que surgem os filtros, que servem como uma forma de concetrar alguuns elementos de crosscutting, como segurana, traduo de
excees em erros HTTP, etc.
Os filtros podem ser aplicados em aes especficas dentro do controller, no controller como um todo, ou para todas as aes em todos os controllers global. O
benefcio que temos na utilizao de filtros a granularidade onde podemos apliclos. Talvez interromper a requisio logo nos primeiros estgios via handlers
possa ser mais eficaz, pois muitas vezes voc no precisa passar por todo o pipeline para tomar essa deciso.
H um namespace chamada System.Web.Http.Filters, que possui vrios filtros j predefinidos. Todo filtro herda direta ou indiretamente da classe abstrata
FilterAttribute, que j possui a estrutura padro para todos os filtros. O diagrama abaixo ilustra essa hierarquia.

Figura 27 Hierarquia das classes dos filtros existentes dentro do framework.


Alm da classe base para os filtros, j temos algumas outras, tambm abstratas, que definem a estrutura para que seja criado um filtro para controlarmos a
autorizao, outro para controlarmos o tratamento de erros e um que nos permite interceptar a execuo de alguma ao dentro do controller.
Para e exemplificar a customizao de um filtro, podemos criar um que impossibilite o acesso uma ao se ela no estiver protegida por HTTPS. A classe
ActionFilterAttribute fornece dois mtodos que podemos sobrescrever na classe derivada: OnActionExecuting e OnActionExecuted. Como podemos perceber, um deles
disparado antes e o outro depois da ao executada.
C#
publicclassValidacaoDeHttps:ActionFilterAttribute
{
publicoverridevoidOnActionExecuting(HttpActionContextactionContext)
{
varrequest=actionContext.Request;
if(request.RequestUri.Scheme!=Uri.UriSchemeHttps)
{
actionContext.Response=
request.CreateResponse(
HttpStatusCode.Forbidden,
newStringContent("necessrioquearequisiosejaHTTPS."));
}
}
}
O fato da classe ActionFilterAttribute herdar da classe Attribute, podemos aplicar este atributo tanto no controller quanto em um ou mais aes, ou seja, podemos ter
um refinamento mais apurado, pois temos condies de aplicar isso em certos casos, em outros no. No exemplo abaixo optamos apenas por proteger por HTTPS a
ao Teste2. Se quisermos que todos as aes dentro deste controller sejam protegidas, basta apenas elevarmos o atributo, decorando a classe com o filtro criado.
C#
publicclassTestController:ApiController
{
[HttpGet]
publicstringTeste1()
{
return"teste1";
}
[HttpGet]
[ValidacaoDeHttps]

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

61/63

27/06/2016

Minhacoleo
publicstringTeste2()
{
return"teste2";
}
}

Finalmente, se desejarmos que este atributo seja aplicado em todas as aes de todos os controllers, adicionamos este filtro em nvel global, atravs da configurao
da API:
API
config.Filters.Add(newValidacaoDeHttps());

Sobrescrita de Filtros
Ao aplicar o filtro em nvel global, evita termos que decorarmos cada nova ao ou cada novo controller com um determinado atributo, evitando assim que, por
algum descuido, um determinado cdigo deixe de rodar antes e/ou depois de cada ao. Sendo assim, o nvel global nos permite aplicar incondicionalmente para
todas as aes, e se quisermos aplicar um filtro para uma ou outra ao, decoramos o atributo diretamente nele.
S que ainda h uma outra situao, que quando precisamos aplicar determinados filtros para a grande maioria das aes, mas em poucas delas no queremos que
o filtro seja aplicado. Para isso, quando configurarmos um filtro em nvel global, podemos sobrescrever uma determinada ao para que os filtros no sejam aplicados
nela. Para isso, entra em cena um atributo chamado OverrideActionFiltersAttribute, que quando aplicado em uma determinada ao, ele ignora os filtros aplicados em
nvel global.
C#
publicclassTestController:ApiController
{
[HttpGet]
publicstringTeste1()
{
return"teste1";
}
[HttpGet]
[OverrideActionFilters]
publicstringTeste2()
{
return"teste2";
}
}
Alm deste atributo, temos outros trs com a mesma finalidade, ou seja, interromper a execuo de determinados tipos de filtros que foram aplicados em nvel global.
Os outros atributos que temos para isso so: OverrideAuthenticationAttribute, OverrideAuthorizationAttribute e OverrideExceptionAttribute.
Configuraes
Durante todos os captulos vimos diversas configuraes que so realizadas em nvel global. Para todas elas recorremos ao objeto HttpConfiguration. Ele fornece
diversas propriedades e mtodos que nos permite interagir com todos os recursos que so utilizados durante a execuo das APIs. Uma das propriedades que vale
ressaltar a Services do tipo ServicesContainer. Essa classe consiste em armazenar todos os recursos que so utilizados pelo ASP.NET Web API para fornecer ao
runtime os responsveis por executar cada tarefa especfica, tais como: criao do controller, gestor de dependncias, gestor de tracing, etc.

Figura 28 Classes para a customizao das configuraes.


A propriedade Services da classe ServicesContainer inicializada com a instncia da classe DefaultServices, que vale para todos e qualquer controller dentro da
aplicao. Podemos variar certas configuraes para cada controller, e justamente para isso que temos a classe ControllerServices.
Se quisermos customizar a configurao por controller, onde cada um deles possui uma necessidade especfica, basta implementarmos a interface
IControllerConfiguration namespace System.Web.Http.Controllers, onde atravs do mtodo Initialize, realizamos todas as configuraes especficas, e durante a
execuo o ASP.NET ir considerar essas configuraes, sobrescrevendo as globais, e para aquelas que no alterarmos, a configurao global ser utilizada.
C#
publicclassConfiguracaoPadrao:Attribute,IcontrollerConfiguration
{
publicvoidInitialize(
HttpControllerSettingscontrollerSettings,
HttpControllerDescriptorcontrollerDescriptor)
{
controllerSettings.Formatters.Add(newCsvMediaTypeFormatter());
}
}

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

62/63

27/06/2016

Minhacoleo
[ConfiguracaoPadrao]
publicclassTestController:ApiController
{
//aes
}

Veja tambm:
ASP.NET Web API HTTP, REST e o ASP.NET: Para basear todas as funcionalidades expostas pela tecnologia, precisamos ter um conhecimento bsico em relao ao
que motivou tudo isso, contando um pouco da histria e evoluo, passando pela estrutura do protocolo HTTP e a relao que tudo isso tem com o ASP.NET.
ASP.NET Web API Estrutura da API: Entenderemos aqui a template de projeto que o Visual Studio fornece para a construo das APIs, bem como sua estrutura e
como ela se relaciona ao protocolo.
ASP.NET Web API Roteamento: Como o prprio nome diz, o captulo ir abordar a configurao necessria para que a requisio seja direcionada corretamente para
o destino solicitado, preenchendo e validando os parmetros que so por ele solicitado.
ASP.NET Web API Hosting: Um captulo de extrema relevncia para a API. o hosting que d vida API, disponibilizando para o consumo por parte dos clientes, e a
sua escolha interfere diretamente em escalabilidade, distribuio e gerenciamento. Existem diversas formas de se expor as APIs, e aqui vamos abordar as principais
delas.
ASP.NET Web API Consumo: Como a proposta ter uma API sendo consumido por qualquer cliente, podem haver os mais diversos meios bibliotecas de consumir
estas APIs. Este captulo tem a finalidade de exibir algumas opes que temos para este consumo, incluindo as opes que a Microsoft criou para que seja possvel
efetuar o consumo por aplicaes .NET.
ASP.NET Web API Formatadores: Os formatadores desempenham um papel importante na API. So eles os responsveis por avaliar a requisio, extrair o seu
contedo, e quando a resposta devolvida ao cliente, ele entra em ao novamente para formatar o contedo no formato em que o cliente possa entender. Aqui
vamos explorar os formatadores padres que j esto embuitdos, bem como a criao de um novo.
ASP.NET Web API Segurana: Como a grande maioria das aplicaes, temos tambm que nos preocupar com a segurana das APIs. E quando falamos de aplicaes
distribudas, alm da autenticao e autorizao, necessrio nos preocuparmos com a segurana das mensagens que so trocadas entre o cliente e o servio. Este
captulo ir abordar algumas opes que temos disponveis para tornar as APIs mais seguras.
ASP.NET Web API Testes e Tracing: Para toda e qualquer aplicao, temos a necessidade de escrever testes para garantir que a mesma se comporte conforme o
esperado. Isso no diferentes com APIs Web. Aqui iremos abordar os recursos, incluindo a prpria IDE, para a escrita, gerenciamento e execuo dos testes.
ASP.NET Web API Estensibilidade e Arquitetura: Mesmo que j tenhamos tudo o que precisamos para criar e consumir uma API no ASP.NET Web API, a customizao
de algum ponto sempre acaba sendo necessria, pois podemos criar mecanismos reutilizveis, externalizandoos do processo de negcio em si. O ASP.NET Web API
foi concebido com a estensibilidade em mente, e justamente por isso que existe um captulo exclusivo para abordar esse assunto.

| Home | Artigos Tcnicos | Comunidade

2016 Microsoft

http://pabprod.blob.core.windows.net/books/65082045cd0446a698248f99c5505248.html

63/63

Das könnte Ihnen auch gefallen