Web API - Blog da TreinaWeb
.NET CoreASP .NETC#Padrões de Projeto 8 de maio de 2020
Com a biblioteca MediatR a implementação deste padrão em uma aplicação ASP.NET Core é facilitada. Mas é importante frisar que este o Mediator não deve ser utilizado em qualquer projeto, dependendo do caso, a "sobrecarga " necessária para implementá-lo não compensará os benefícios que fornece.
.NET CoreC#Desenvolvimento Back-end 18 de dezembro de 2019
Serviços gRPC no ASP.NET Core
No âmbito de aplicações, quando estamos falando de serviços, o desenvolvedor imagina uma API RESTful. Não dá para negar que o casamento de HTTP+JSON faz um grande sucesso, mas em alguns momentos esta combinação possui limitações.
Em larga escala, ou quando se lida com aplicações críticas, a performance de uma API REST pode significar seu gargalo, principalmente quando estamos lidando com microserviços. É por causa disso que grandes empresas, como Netflix, Digital Ocean, SoundClound e Google, optaram pelo gRPC para melhorar e otimizar a comunicação dos seus microserviços.
O gRPC é um framework RPC open source criado pelo Google, como forma de melhorar a comunicação do grande número de microserviços que possuem. Com suporte à várias linguagens, na versão 3.0 do .NET Core 3.0, a Microsoft adicionou um template que facilita a criação de serviços gRPC.
Antes de conhecer este template e criar um serviço, você precisa conhecer mais sobre o gRPC.
Curso de C# (C Sharp) - APIs REST com ASP.NET Web API
O que seria o gRPC?
Como dito, o gRPC é um framework RPC. O RPC é a sigla de Remote Procedure Call, chamada de procedimento remoto, que basicamente trata-se de uma tecnologia para comunicação de processos. Permitindo que um computador possa invocar um procedimento de outro computador, independente da linguagem ou plataforma.
No manifesto de motivação e princípios do gRPC o Google conta que já utilizava uma infraestrutura RPC denominada Stubby. Mas por ser muito associada a infraestrutura da empresa e não ser baseado em nenhum padrão, ela não poderia ser aberta a todos. Com o advento do HTTP/2, o Stubby foi refeito e nasceu o gRPC, que hoje é parte da CNCF, Cloud Native Computer Foundation.
Porque o HTTP/2 é importante?
O gRPC não trabalha sob o protocolo HTTP 1.1, que é o protocolo utilizado por todos os servidores web, devido suas limitações. A principal é a forma que as solicitações são tratadas.
Por mais que não seja aparente, no HTTP 1.1 um servidor só pode receber e responder uma requisição por vez. Para tentar contornar este limite, ele trabalha com paralelismo, mas o canal de comunicação trabalha em apenas uma via. Quando está recebendo não pode enviar e vice-versa.
Já no HTTP/2 as conexões são "multiplexadas" (multiplex), o que significa que trabalha de forma bidirecional, recebendo e enviando várias solicitações ao mesmo tempo.
As duas imagens abaixo ilustram este cenário:
Aqui é importante ressaltar que devido ao uso do HTTP/2, um serviço do gRPC só pode ser hospedado em um servidor que fornece suporte a esta versão do protocolo. Felizmente na versão 3.0 do .NET Core, o Kestrel passou a suportar esta versão.
Para conhecer as características deste tipo de serviço, vamos colocar a mão na massa.
Criando um serviço gRPC no ASP.NET Core
A partir da versão 3.0 do .NET core é possível criar um serviço gRPC através do comando abaixo:
dotnet new grpc -o ServicoGrpc
Ou no Visual Studio 2019, selecione o template gRPC Service.
A aplicação criada terá a estrutura abaixo:
Vamos ver em detalhes seus arquivos.
Contrato com Protobuf
Dentro da pasta Protos temos o arquivo greet.proto:
option csharp_namespace = "ServicoGrpc";
Este é o arquivo de contrato. Baseado no padrão Protobuf, ele que definirá a estrutura do serviço gRPC e precisa existir no cliente e no servidor. É a partir dele que o gRPC irá gerar as operações do serviço.
Acima é definido dentro do pacote Greet um serviço Greeter, que contém uma operação, SayHello. Em seguida é definida a estrutura dos dados recebidos na solicitação e os dados retornados.
Nos bastidores, a biblioteca do gRPC, Grpc.AspNetCore, irá criar classes, que nos permitirá definir o serviço no C#.
Os serviços são definidos dentro da pasta Services, que no momento possui apenas a classe GreeterService:
Esta classe herda Greeter.GreeterBase, que foi gerada pelo gRPC com base no arquivo .proto. O mesmo ocorreu com as classes HelloRequest e HelloReply.
Por fim, no arquivo appsettings.json é definido que o Kestrel utilizará o protocolo HTTP/2:
E na classe Startup, além de registrar o serviço gRPC, cria-se um fallback para caso de o usuário acessar o serviço pelo navegador ou utilizando um client sem suporte ao gRPC:
Para acessar um serviço gRPC necessitamos de um cliente com suporte a este tipo de serviço, para isso, irei utilizar uma aplicação console simples:
new HelloRequest { Name = "Treinaweb Blog" });
Console.WriteLine("Saudacao: " + reply.Message);
Console.WriteLine("Pressione qualquer coisa para sair...");
Que precisa referenciar as bibliotecas Google.Protobuf, Grpc.Net.Client e Grpc.Tools:
<PackageReference Include="Google.Protobuf" Version="3.11.1" />
<PackageReference Include="Grpc.Net.Client" Version="2.25.0" />
<PackageReference Include="Grpc.Tools" Version="2.25.0">
Além claro do arquivo greet.proto definido do servidor:
No servidor, o atributo GrpcServices é definido com o valor Server.
Ao executar ambas as aplicações, inicialmente o serviço e por fim o cliente, poderemos ver a comunicação sendo realizada:
No momento há poucos servidores web com suporte ao gRPC, mas esta tecnologia possui muito potencial. Em uma arquitetura de microserviços é altamente recomendado que ela seja utilizada para a comunicação entre os microserviços. Neste ambiente a comunicação externa pode se manter com a tradicional combinação HTTP+JSON.
ASP .NETC#Desenvolvimento Back-end 3 de dezembro de 2019
No início deste ano comentei o quanto o ASP.NET Web API é quase uma unanimidade na criação de APIs no .NET, mas que haviam outras opções, tão boas quanto ele.
No artigo em questão abordei a criação de uma API com o framework NancyFX. E ao longo deste ano ganhou destaque outro framework para criação de APIs, que podemos chamar de um derivado do Nancy, o Carter.
O Carter foi criado por Jonathan Channon, e é mantido por ele e a Carter Community, seguindo a mesma filosofia do Nancy (onde o Jonathan Channon também contribui), facilitar a vida do desenvolvedor.
Implementado como uma extensão do ASP.NET Core, o Carter permite que o código seja mais direto, elegante e agradável. Seu principal objetivo é facilitar a definição das rotas e controllers.
Para compreendê-lo, vamos ver um exemplo simples de API.
Criando a aplicação para utilizar o Carter
O Carter pode ser adicionado em qualquer tipo de aplicação ASP.NET Core, mesmo uma aplicação existente. Caso queria trabalhar apenas com este framework é necessário criar uma aplicação web vazia:
dotnet new web -n CarterAPI
E adicionar o pacote carter:
dotnet add package carter
Em seguida ele deve ser configurado na classe Startup:
services.AddCarter();
app.UseEndpoints(endpoints => endpoints.MapCarter());
Também é possível instalar o CarterTemplate:
dotnet new -i CarterTemplate
Com isso, é possível criar a aplicação utilizando este template:
dotnet new Carter -n CarterAPI
Nesta opção a aplicação é criada com o Carter configurado e um módulo definido. Como não optamos por esta opção, vamos criar o módulo na nossa aplicação.
Assim como no Nancy, no Carter os endpoints devem ser definidos em módulos. Um módulo nada mais é que uma classe que herde a classe CarterModule. Esta classe pode ser definida em qualquer ponto da aplicação. O importante é que seja pública, por exemplo:
using Carter;
namespace CarterAPI.Modules
Get("/", (req, res) => res.WriteAsync("Hello from Carter!"));
Como é possível supor, acima estamos definindo uma solicitação GET, que será invocada quando o usuário acessar a rota /. Ao executar a aplicação, teremos o resultado:
Para cada verbo do HTTP há um método disponível:
Delete = DELETE;
Post = POST;
Put = PUT;
Patch = PATCH.
Criando o CRUD
Para exemplificar uma API REST completa, vamos definir os métodos CRUD.
Inicialmente defina uma entidade:
E um repositório:
public class PessoaRepository
public List<Pessoa> GetAll(){
return pessoas.Values.ToList();
public Pessoa Get(int id){
return pessoas.GetValueOrDefault(id);
public void Add(Pessoa pessoa){
public void Edit(Pessoa pessoa){
pessoas.Remove(id);
Por fim, podemos definir os endpoints:
public class PessoaModule : CarterModule
public readonly PessoaRepository repository;
public PessoaModule()
repository = new PessoaRepository();
Get("/pessoa/", (req, res) => {
var pessoas = repository.GetAll();
return res.AsJson(pessoas);
Get("/pessoa/{id:int}", (req, res) =>
var id = req.RouteValues.As<int>("id");
var pessoa = repository.Get(id);
return res.Negotiate(pessoa);
Post("/pessoa/", async (req, res) =>
var pessoa = await req.Bind<Pessoa>();
repository.Add(pessoa);
await res.Negotiate(pessoa);
Put("/pessoa/{id:int}", async (req, res) =>
pessoa.Id = req.RouteValues.As<int>("id");
repository.Edit(pessoa);
Delete("/pessoa/{id:int}", (req, res) =>
Nestes endpoints podemos notar algumas particularidades do framework, como o fato dos parâmetros da URL definem um tipo de dado:
Isso permite que o valor seja validado no momento que a solicitação está sendo processada. Este valor é obtido através do método do RouteValues:
Já os dados passados no corpo da solicitação serão obtidos através do Bind:
Podemos testar este endpoint pelo Postman, mas outro recurso do Carter é a geração do JSON definido pelo OpenAPI, que abordei no meu artigo sobre o Swagger.
O JSON do OpenAPI criado pelo Carter pode ser acessado pela URL /openapi, mas infelizmente ele não configura os endpoints automaticamente. Cada endpoint precisa ser configurado em uma classe que herde RouteMetaData.
Para os endpoints deste artigo, defini as classes abaixo:
public class GetPessoa : RouteMetaData
public override string Tag { get; } = "Pessoa";
public override string Description { get; } = "Retorna uma lista de pessoas";
public override RouteMetaDataResponse[] Responses { get; } =
new RouteMetaDataResponse
Description = $"Uma lista de Pessoas",
Response = typeof(IEnumerable<Pessoa>)
public override string OperationId { get; } = "Pessoa_GetPessoa";
public class GetPessoaById: RouteMetaData
public override string Description { get; } = "Obtém pessoa pelo id";
Description = $"Uma Pessooa",
Response = typeof(Pessoa)
Code = 404,
Description = $"Pessoa não encontrada"
public override string OperationId { get; } = "Pessoa_GetPessoaById";
public class PostPessoa: RouteMetaData
public override string Description { get; } = "Adiciona uma pessoa";
public override RouteMetaDataRequest[] Requests { get; } =
new RouteMetaDataRequest
Request = typeof(Pessoa),
Code = 204,
Description = "Pessoa adicionada"
public override string OperationId { get; } = "Pessoa_PostPessoa";
public class PutPessoa: RouteMetaData
public override string Description { get; } = "Atualiza uma pessoa";
Description = "Pessoa atualizada"
public override string OperationId { get; } = "Pessoa_PutPessoa";
public class DeletePessoa: RouteMetaData
public override string Description { get; } = "Exclui uma pessoa";
Description = "Exclui Pessoa"
public override string OperationId { get; } = "Pessoa_DeletePessoa";
Agora é necessário definir esses meta dados em cada endpoint:
Get<GetPessoa>("/pessoa/", (req, res) => {
Get<GetPessoaById>("/pessoa/{id:int}", (req, res) =>
if(pessoa == null)
Post<PostPessoa>("/pessoa/", async (req, res) =>
Put<PutPessoa>("/pessoa/{id:int}", async (req, res) =>
Delete<DeletePessoa>("/pessoa/{id:int}", (req, res) =>
Note que eles são especificados no método do endpoint:
Ao defini-los e acessar /openapi, será retornado o JSON:
Para visualizarmos em uma interface gráfica, é possível adicionar o SwaggerUi da biblioteca Swashbuckle:
dotnet add package Swashbuckle.AspNetCore.SwaggerUi --version 5.0.0-rc4
Configurá-lo no projeto:
app.UseSwaggerUI(opt =>
opt.RoutePrefix = "openapi/ui";
opt.SwaggerEndpoint("/openapi", "Carter OpenAPI Sample");
Desta forma, ao acessar a URL /openapi/ui teremos acesso a interface gráfica:
E por ela é possível testar todos os endpoints.
Devido a sua simplicidade e grande gama de recursos o Carter é um framework que merece ser acompanhado. Caso tenha se interessado por ele, recomendo que dê uma olhada no seu repositório.
Infelizmente no momento ele não possui nenhuma documentação detalhada.
Você pode obter os códigos da aplicação demonstrada neste artigo, no meu Github.
.NET CoreASP .NETC# 16 de agosto de 2019
Alguns artigos passados falei sobre as ferramentas de linha de comando que permitem diagnosticar uma aplicação no .NET Core 3.0. Por serem ferramentas de linha de comando, elas requerem acesso a máquina onde a aplicação está instalada. Infelizmente em muitos cenários algo assim não é possível, mas o monitoramento do status da aplicação não deixa de ser importante nesses casos.
Se tratando de aplicações ASP.NET, antigamente o comum era criar um endpoint que retornasse o estado da aplicação ou menos nada era definido. Mas com a adoção cada vez maior de microsserviços e a criação de aplicações para um ambiente distribuído, implementar a verificação da integridade da aplicação se tornou algo essencial.
Felizmente, a partir da versão 2.2 do ASP.NET Core, foi introduzido os Health Checks que facilitam este trabalho.
Conhecendo os Health Checks
Health check é um middleware que fornece um endpoint que retorna o status da aplicação. Na sua versão básica, a aplicação é considerada saudável caso retorne o código 200 (OK) para uma solicitação web. Mas também são fornecidas bibliotecas que nos permite verificar o status de serviços utilizados pela aplicação, como: banco de dados, sistema de mensageria, cache, logging, serviços externos ou mesmo a criação de um health check customizado.
Aplicação que terá a integridade verificada
Para exemplificar o uso do health check, vou utilizar uma aplicação ASP.NET Core Web API simples, que já foi mostrada no artigo sobre a documentação de uma ASP.NET Core Web API com o Swagger, que você pode ver no meu Github.
Adicionando o Health Check na aplicação
Agora que já temos a aplicação, já podemos ativar o health check nela. Para isso, basta adicionar o service no método ConfigureServices da classe Startup e indicar a URL dele no método Configure:
//Ativa o HealthChecks
app.UseHealthChecks("/status");
Agora, ao executar a aplicação e acessar a URL /status será exibido se ela está saudável ou não:
Como está sendo testado apenas se ela responde a uma requisição, a aplicação é considerada saudável.
Existem várias formas de testar a integridade do banco de dados. É fornecido uma gama de pacotes que nos permite testar a integridade do banco de acordo com o SGBD:
SQL Server: AspNetCore.HealthChecks.SqlServer;
MySQL: AspNetCore.HealthChecks.MySql;
PostgreSQL: AspNetCore.HealthChecks.Npgsql;
SQLite: AspNetCore.HealthChecks.SqLite;
Oracle: AspNetCore.HealthChecks.Oracle;
MongoDb: AspNetCore.HealthChecks.MongoDb.
Caso esteja trabalhando com o Entity Framework, também há o pacote Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore, que será o que utilizaremos na aplicação:
dotnet add package Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
Com isso, basta adicionar a classe DbContext, que o estado da conexão com o banco será verificada:
.AddDbContextCheck<TodoContext>();
Se o banco estiver saudável, o resultado não será alterado:
Caso haja algum problema com a conexão com o banco, a aplicação não será considerada saudável:
Alterando as informações exibidas
No momento, somos informados apenas se a aplicação está ou não saudável. Para uma aplicação pequena, isso pode ser útil, mas imagine uma aplicação que verifica vários serviços? Apenas com esta informação não conseguiremos saber qual serviço não está funcionando corretamente.
Para obter esses dados, podemos customizar as informações de saída do health check, definindo um delegate na opção ResponseWriter:
app.UseHealthChecks("/status", new HealthCheckOptions()
// WriteResponse é um delegate que permite alterar a saída.
ResponseWriter = (httpContext, result) => {
return httpContext.Response.WriteAsync(json.ToString(Formatting.Indented));
Com isso, obteremos a causa do problema da aplicação:
Criando health checks customizados
Existe uma grande gama de health checks definidos, mas em algumas situações, pode ser necessário definir um customizado. Para isso, é necessário definir uma classe que implemente a interface IHealthCheck e definir no método CheckHealthAsync qual tipo de verificação ele fará:
public class SelfHealthCheck : IHealthCheck
public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
HealthStatus.Healthy,
description: "API up!"));
Acima é definido um health check simples, que apenas indica que a API está funcionando.
Agora é necessário adicioná-lo ao serviço com o método AddCheck:
.AddDbContextCheck<TodoContext>()
.AddCheck<SelfHealthCheck>("Self");
Também pode ser definido um método de extensão:
public static class HealthCheckBuilderExtensions
public static IHealthChecksBuilder AddSelfCheck(this IHealthChecksBuilder builder, string name, HealthStatus? failureStatus = null, IEnumerable<string> tags = null)
// Register a check of type SelfHealthCheck
builder.AddCheck<SelfHealthCheck>(name, failureStatus ?? HealthStatus.Degraded, tags);
E utilizá-lo para registrar o health check:
.AddSelfCheck("Self");
Ao acessar a aplicação, ele também será mostrado:
Adicionando uma interface
No momento o resultado do status da aplicação é um JSON, mas existe um pacote que nos permite visualizar as informações em uma interface gráfica. Para isso, adicione na aplicação os pacotes AspNetCore.HealthChecks.UI e AspnetCore.HealthChecks.UI.Client:
dotnet add package AspnetCore.HealthChecks.UI.Client
Em seguida é necessário habilitar o Health Checks UI nos métodos ConfigureServices e Configure da classe Startup:
// WriteResponse is a delegate used to write the response.
//Ativa o HealthChecks utilizado pelo HealthCheckUI
app.UseHealthChecks("/status-api", new HealthCheckOptions()
app.UseHealthChecksUI(opt => {
opt.UIPath = "/status-dashboard";
Além de habilitar o Health Checks UI note que também é definido um novo endpoint para o health check, configurado para o delegate UIResponseWriter.WriteHealthCheckUIResponse. Este é um delegate criado pelo Health Checks UI, e configura um arquivo JSON que será lido pela biblioteca.
Para que ele seja lido, é necessário especificá-lo no arquivo appsettings.json:
"Name": "Status-API",
"Uri": "https://localhost:5001/status-api"
Com isso, ao executar a aplicação e acessar a URL /status-dashboard a interface será exibida:
Por hoje é isso 🙂
Lembrando que você pode ver o código da aplicação no Github.
.NET CoreASP .NETC#DesenvolvimentoDesenvolvimento Back-endWeb Services 5 de novembro de 2018
Documentando uma ASP.NET Core Web API com o Swagger
Com cada vez mais aplicações multiplataformas, é comum definir uma API REST que será consumida pelas várias versões da aplicação. Mas com vários times tendo acesso a API, não basta mais apenas desenvolvê-la e esperar que todos consigam utilizá-la institivamente.
Na época do web service, existia o WSDL que funcionava como uma documentação, já que facilitava a criação dos clientes que iria consumí-lo. Com as APIs REST não temos esta facilidade, assim, torna-se imprescindível que ela seja bem documentada.
Mas como realizar esta documentação? Existem algumas ferramentas que podem nos auxiliar neste processo, como: API Blueprint, RAML, Swagger, entre outras.
Como o nome deste artigo sugere, aqui abordaremos o Swagger.
O Swagger é uma aplicação open source que auxilia os desenvolvedores a definir, criar, documentar e consumir APIs REST. Sendo uma das ferramentas mais utilizadas para esta função, a empresa por trás dela (a SmartBear Software), decidiu criar o Open API Iniciative e renomearam as especificações do Swagger para OpenAPI Specification.
Ela visa padronizar as APIs REST, desta forma descreve os recursos que uma API deve possuir, como endpoints, dados recebidos, dados retornados, códigos HTTP, métodos de autenticação, entre outros.
Para facilitar o processo de especificação/documentação de uma API, o Swagger fornece algumas ferramentas, como:
Swagger Editor: Editor que permite especificar uma API. Há uma versão online grátis e aplicativos para desktop;
Swagger UI: Interface interativa para a documentação da API;
Swagger Codegen: Gera templates de código (mais de 20 linguagens estão disponíveis) de acordo com uma especificação de API.
Neste artigo vamos focar na documentação de uma API existente, criada em ASP.NET Core Web API.
Especificação do Swagger
O ponto mais importante do Swagger é a sua especificação, que era chamada de Swagger specification e agora é OpenAPI Specification. Esta especificação trata-se de um documento, JSON ou YAML, que define a estrutura da API. Indicando os endpoints, formatos de entrada, de saída, exemplos de requisições, forma de autenticação, etc.
Abaixo você pode ver um exemplo desta especificação definida em JSON:
"title": "API V1"
"/api/Example": {
"operationId": "ApiExampleGet",
"/api/Example/{id}": {
"securityDefinitions": {}
É possível definir esta especificação na mão, olhando as opções na documentação, através do Swagger Editor ou utilizando outra ferramenta para gerá-la.
No ASP.NET Core podemos utilizar duas bibliotecas para gerar este documento:
Swashbuckle.AspNetCore.
NSwag.
Por ser mais completa, faremos uso da Swashbuckle.
Adicionando o Swashbuckle na aplicação
Para este exemplo, estou utilizando uma aplicação ASP.NET Core Web API, baseada no exemplo fornecido pela documentação da Microsoft, que pode ser vista aqui. Você pode ver a aplicação que criei no meu Github.
Com a aplicação Web API criada, inicialmente é necessário adicionar o pacote do Swashbuckle na aplicação. Ele possui três componentes:
Swashbuckle.AspNetCore.Swagger;
Swashbuckle.AspNetCore.SwaggerGen;
Swashbuckle.AspNetCore.SwaggerUI;
Mas é necessário instalar apenas o pacote Swashbuckle.AspNetCore. Por se tratar de uma aplicação .NET Core, este pacote pode ser adicionado com o comando abaixo:
Após isso, para que o arquivo de especificação da API do Swagger seja criado, é necessário adicionar o gerador dele nos serviços da aplicação, no método ConfigureServices da classe Startup:
//... código omitido
c.SwaggerDoc("v1", new Info { Title = "TodoAPI", Version = "v1" });
Para a classe Info, defina o using do namespace abaixo:
Agora, no método Configure é necessário ativar o Swagger e indicar o local onde o seu arquivo de especificação será criado:
//Ativa o Swagger
// Ativa o Swagger UI
opt.SwaggerEndpoint("/swagger/v1/swagger.json", "TodoAPI V1");
Com isso, através de reflection a biblioteca consegue especificar os endpoints da aplicação.
Caso seja executada, podemos acessar o Swagger UI da aplicação no caminho /swagger:
Caso queira que o Swagger UI seja acessado a partir da raiz da aplicação, na ativação dela, no método Configure, atribua vazio para a propriedade RoutePrefix:
c.SwaggerEndpoint("/swagger/v1/swagger.json", "TodoAPI V1");
Customizando o Swagger
Como o Swashbuckle trabalha com reflection, podemos fazê-lo gerar mais informações das nossas APIs com base em configurações definidas nela.
Sabemos que no C# podemos adicionar comentários de documentação nos nossos códigos, como:
/// Lista os itens da To-do list.
/// <returns>Os itens da To-do list</returns>
/// <response code="200">Returna os itens da To-do list cadastrados</response>
public ActionResult<List<Item>> Get()
É possível fazer o Swashbuckle ler esses comentários e assim tornar a especificação da API mais detalhada.
Para isso, na definição de geração do arquivo de especificação, no método ConfigureServices deve ser adicionado a informação abaixo:
opt.SwaggerDoc("v1", new Info { Title = "TodoAPI", Version = "v1" });
opt.IncludeXmlComments(xmlPath);
Note que estamos indicando que ele deve ler os comentários do código a partir de um arquivo XML. Para que eles sejam gerados neste arquivo indicado, no arquivo de configuração do projeto (o .csproj), adicione o trecho abaixo:
O <NoWarn> é definido para que a IDE não exiba um alerta sobre os códigos que não possuírem comentários de documentação.
Agora ao acessar o Swagger API, o que foi definido em <summary> será mostrado:
Também podemos o <remarks> para indicar um exemplo de requisição:
/// Cria um item na To-do list.
/// Exemplo:
/// <returns>Um novo item criado</returns>
/// <response code="201">Retorna o novo item criado</response>
/// <response code="400">Se o item não for criado</response>
public ActionResult<Item> Post([FromBody] Item value)
Console.WriteLine(value?.Name);
var item = _repository.Save(value);
Com as anotações ProducesResponseType e Produces podemos indicar os códigos HTTP e o tipo de dado que os endpoints irão retornar:
//..código omitido
Especificando a autenticação
Uma das principais vantagens de adicionar o Swagger na aplicação, é poder testar os endpoints pela Swagger UI. Quando a aplicação define autenticação, é necessário indicar isso para o Swashbuckle, para que ele também gere uma especificação desde detalhe.
Com isso, será possível testar os endpoints pela Swagger UI utilizando a autenticação definida.
Para fazer isso, devemos adicionar a informação abaixo, na definição de geração do arquivo de especificação, no método ConfigureServices:
opt.AddSecurityDefinition(
new ApiKeyScheme
Description = "Copie 'Bearer ' + token'",
opt.AddSecurityRequirement(security);
Acima estamos definindo que a aplicação faz uso de autenticação do tipo JWT Token ("Bearer Token"). Na documentação do Swagger, você pode ver os outros tipos de autenticação suportados.
Ao acessar o Swagger UI, ele irá mostrar o botão "Autorize":
Ao clicar nele, é possível informar o tipo de autenticação especificado:
Com isso, mesmo que necessite de autenticação, será possível realizar as requisições dos endpoints da aplicação pelo Swagger UI.
Por fim, é possível descrever um pouco da aplicação através das propriedades da classe Info da especificação do Swagger:
opt.SwaggerDoc("v1", new Info
Description = "Um exemplo de aplicação ASP.NET Core Web API",
TermsOfService = "Não aplicável",
Name = "Wladimilson",
Email = "contato@treinaweb.com.br",
Url = "https://treinaweb.com.br"
Name = "CC BY",
Url = "https://creativecommons.org/licenses/by/4.0"
O Swagger é uma ótima forma de documentar APIs REST e com a biblioteca Swashbuckle, podemos gerar o arquivo de especificação do Swagger com facilidade. Assim, não há mais desculpa para se definir documentações interativas e detalhadas para as suas APIs REST.
Javascript 8 de outubro de 2018
Gerando sons com a Web Audio API do JavaScript
Sabiam que podemos gerar sons com JavaScript? Isso graças à Web Audio API, que nos fornece poderosas funcionalidades para se trabalhar com áudio. Podemos fazer coisas como adicionar efeitos a um arquivo de áudio ou criar músicas a partir do JavaScript.
Começando com um beep
Para começar, vamos gerar um simples beep.
let context = new AudioContext(),
Primeiro nós instanciamos o AudioContext, que é o principal objeto para podermos gerar um som. A partir dele nós criamos um oscilador, que é responsável por emitir um sinal contínuo, que será o nosso som.
Precisamos indicar o tipo de onde que nosso oscilador irá gerar. Indicamos que queremos uma onda senoidal (sine).
Depois conectamos o nosso oscilador ao context.destination, que representa o destino final do áudio. Se você está no computador, provavelmente isso indica as suas caixas de som.
Por fim, executamos a função start() para iniciar o som.
Para parar o som, basta executar oscillator.stop().
Ao parar o som você pode notar um pequeno clique. Isso acontece basicamente quando paramos o som em um lugar qualquer que não seja o ponto zero da onda, como mostrado na imagem abaixo.
Encerrando o som
Um modo de acabar com esse som de clique ao pararmos o som (e que pode ser bem desconfortável) é alterar a nossa onda, como se estivéssemos diminuindo ela.
Para isso, usamos a função exponentialRampToValueAtTime(), que vai alterando de forma exponencial o valor do nosso som.
Vamos então fazer uma pequena alteração em nosso código:
oscillator = context.createOscillator(),
contextGain = context.createGain();
oscillator.connect(contextGain);
contextGain.connect(context.destination);
Agora criamos um ganho, um objeto que nos permitirá trabalhar com a função exponentialRampToValueAtTime(). Ligamos ele ao oscilador e depois ligamos ao destino de saída do som.
Para parar o som, ao invés de simplesmente executarmos a função stop(), vamos executar o seguinte código:
contextGain.gain.exponentialRampToValueAtTime(
0.00001, context.currentTime + 0.04
O que fizemos aqui foi alterar o valor do ganho, que basicamente seria como se estivéssemos abaixando o volume aos poucos.
Veja que o primeiro parâmetro que passamos é bem próximo de zero. Isso porque essa função não pode receber um valor zerado ou negativo.
O segundo parâmetro é o tempo em que queremos que a alteração seja feita.
Abaixo você pode conferir que não importa mais em que momento pare o som, ele não terá mais aquele clique.
Efeitos ao parar o som
Quando paramos o som, passamos um tempo bem pequeno para que a alteração no ganho fosse realizada (0.4).
Dependendo do tempo que passarmos, podemos ter efeitos interessantes.
Isso acaba nos dando sensações diferentes. E essa sensação fica ainda mais evidente quando iniciamos e já encerramos o som logo em seguida.
Sons bens mais agradáveis do que aquele som contínuo, não é mesmo?
Diferentes ondas, diferentes osciladores
O que criamos até agora foi um som a partir de um oscilador usando uma onda senoidal. Há outros tipos de ondas, como podemos ver na seguinte imagem:
Para alterar o tipo de onda, basta passarmos um dos seguintes códigos:
oscillator.type = 'sawtooth';
Até o momento nós só tocamos um simples beep. Mas se quisermos tocar algo, precisamos tocar notas musicais diferentes.
Cada nota é um som emitido a uma determinada frequência. Abaixo temos uma tabela que indica cada nota e sua respectiva frequência:
Para alterar a frequência, basta indicar um valor em oscillator.frequency.value. Para tocar um "Dó" (C4):
const C4 = 261.6,
D4 = 293.7,
E4 = 329.6,
F4 = 349.2,
G4 = 392.0,
A4 = 440.0,
B4 = 493.9;
oscillator.frequency.value = C4;
No exemplo, passei a frequência para uma constante apenas para o nosso código ficar mais legível. É bem mais simples e legível deixar o nome das notas do que deixar o número da frequência.
Caso queira se aprofundar, procure saber mais sobre bibliotecas e frameworks como o Tone.js, uma ferramenta completa com várias funcionalidades para se trabalhar com música interativa no navegador.
http://hoch.github.io/WAAX/
.NET CoreASP .NETC# 12 de abril de 2018
Criando uma aplicação distribuída com ASP.NET Core e o Microsoft Orleans
Este é mais um artigo de uma série sobre o Microsoft Orleans. Caso não tenha visto o primeiro, recomendo que o leia: Conhecendo o Microsoft Orleans.
Como dito no artigo passado, o Orleans está na segunda versão e uma das novidades dela é o suporte ao .NET Standard 2.0, desta forma, como o título indica, a aplicação demonstrada aqui utilizará este framework.
Antes de colocarmos a mão na massa, é importante entender como funciona a solução do Orleans. Esta biblioteca recomenda que um projeto que a implemente seja estruturado com no mínimo quatro projetos:
OrleansHost: Este projeto irá criar um executável que iniciará os silos, os hosts do Orleans que conterá as instâncias dos grãos. É possível iniciar vários silos, que irão trabalhar em conjunto e compartilhar a carga.
GrainsInterfaces: Este projeto contém as interfaces que definem todos os grãos contido nos silos.
Grains: Este projeto contém a implementação de todos os grãos definidos em GrainsInterfaces. Por isso, ele é implementado em conjunto com o OrleansHost.
Inteface: Este projeto pode ser qualquer projeto de interface, mas geralmente trata-se de API. Ele irá se conectar ao OrleansHost, por TCP, para ter acesso aos grãos.
Durante o desenvolvimento, o projeto interface e o OrleansHost podem ser executados em conjunto na mesma máquina. Mas em produção, geralmente eles são executados separadamente. O OrleansHost é implementado em um cluster e a interface em um servidor web.
Neste artigo, a solução será feita em uma máquina Mac OSX, utilizando a versão 2.1.4, em conjunto com o Visual Studio Code, pois amo este ambiente. Mas o Orleans fornece um plugin de templates para o Visual Studio, que facilita a criação de projetos com esta biblioteca. Desta forma, caso esteja utilizando esta IDE recomendo que instale este plugin.
Criando o projeto GrainsInterfaces
Como o projeto Grains necessita do GrainsInterfaces e o OrleansHost fará uso do Grains, o primeiro projeto que precisa ser criado é o GrainsInterfaces.
Caso esteja utilizando o Visual Studio com o plugin do Orleans instalado, crie um projeto com base no template "Orleans Grain Interface Collection. No meu ambiente, incialmente irei criar uma pasta chamada OrleansDotNet, e dentro dela uma solução:
dotnet new sln -n OrleansDotNet
Em seguida, um projeto Class Library:
dotnet new classlib -n GraosInterfaces
Neste projeto adicione a biblioteca Microsoft.Orleans.OrleansCodeGenerator.Build:
dotnet add package Microsoft.Orleans.OrleansCodeGenerator.Build
E adicione nele a interface abaixo:
namespace OrleansDotNet.GraosInterfaces
public interface IGraoContador: IGrainWithStringKey
Task Incremento(int incremento);
Task<int> GetContador();
As interfaces grãos devem definir a implementação de uma das interfaces "GrainWith*" do Orleans e definir métodos que retornem uma Task, para métodos void, ou Task, caso o método retorne algum valor.
A interface implementada acima, IGrainWithStringKey, é utilizada para indicar que o código de identificação do grão será definido com uma string. Infelizmente a documentação do Orleans ainda não documenta bem todas as interfaces disponíveis, mas em um artigo futuro abordo todas.
Criando o projeto Grains
Com a interface definida podemos implementá-la um um projeto Grains. Caso esteja utilizando o Visual Studio, crie um projeto com o template Orleans Grain Class Collection. No meu ambiente, irei criar um projeto Class Library chamado Graos:
dotnet new classlib -n Graos
E este projeto também precisa da referência abaixo:
Em seguida, referencie o projeto de interface:
dotnet add Graos.csproj reference ../GraosInterfaces/GraosInterfaces.csproj
Agora podemos implementar o nosso grão:
using OrleansDotNet.GraosInterfaces;
namespace OrleansDotNet.Graos
public class GraoContador: Grain, IGraoContador
private int _contador;
public Task Incremento(int incremento)
_contador += incremento;
public Task<int> GetContador()
return Task.FromResult(_contador);
Esta classe não tem segredo, o importante é implementar a nossa interface grão e herdar a classe Grain. Dentro dela é definido um contador simples.
Criando o projeto OrleansHost
Com o grão definido, podemos definir o nosso silo (host). Caso esteja utilizando o Visual Studio, crie um projeto com base no template "Orleans Dev/Test Host".
No meu ambiente irei criar uma aplicação console chamada Silo:
dotnet new console -n Silo
Nele adicione adicione uma referência para a biblioteca Microsoft.Orleans.Server:
dotnet add package Microsoft.Orleans.Server
Como iremos registrar o log do silo do console, adicione a referencia abaixo:
Por fim, adicione a referencia do projeto Graos:
dotnet add Silo.csproj reference ../Graos/Graos.csproj
E na classe Program adicione o código abaixo:
using Orleans.Runtime.Configuration;
using Orleans.Hosting;
using Orleans.Configuration;
using OrleansDotNet.Graos;
namespace OrleansDotNet.Silo
private static ISiloHost silo;
private static readonly ManualResetEvent siloStopped = new ManualResetEvent(false);
silo = new SiloHostBuilder()
options.ClusterId = "OrleansDotNet-cluster";
options.ServiceId = "OrleansDotNet";
.ConfigureApplicationParts(parts => parts.AddApplicationPart(typeof(GraoContador).Assembly).WithReferences())
Task.Run(StartSilo);
AssemblyLoadContext.Default.Unloading += context =>
Task.Run(StopSilo);
siloStopped.WaitOne();
private static async Task StartSilo()
await silo.StartAsync();
Console.WriteLine("Silo iniciado");
private static async Task StopSilo()
await silo.StopAsync();
Console.WriteLine("Silo parado");
siloStopped.Set();
Nesta classe, estamos definindo que o Silo irá utilizar as configurações de um cluster local (UseLocalhostClustering()), também é definido as identificações do cluster, bem com o seu IP (Configure()). Por fim, se define o grão que será adicionado ao silo e onde o seu log deve ser exibido.
Com o silo definido, ele é iniciado. Ele só irá parar em caso de algum erro ou quando o usuário forçar a sua parada.
Criando o projeto Interface
Com o Silo definido podemos criar a nossa aplicação interface. Neste projeto vou criar uma aplicação WebAPI chamada InterfaceAPI:
dotnet new webapi -n InterfaceApi
Aproveite e já vincule os projetos a solução:
dotnet sln OrleansDotNet.sln add **/*.csproj
Na api é necessário adicionar a referência Microsoft.Orleans.Client:
dotnet add package Microsoft.Orleans.Client
E referenciar o projeto GraosInterfaces:
dotnet add InterfaceApi.csproj reference ../GraosInterfaces/GraosInterfaces.csproj
Para trabalhar com "dependency injection", vamos configurar o cliente do Orleans na classe Startup conforme o código abaixo:
namespace InterfaceApi
services.AddSingleton<IClusterClient>(provider =>
var client = new ClientBuilder()
.ConfigureApplicationParts(parts => parts.AddApplicationPart(typeof(IGraoContador).Assembly).WithReferences())
StartClientWithRetries(client).Wait();
private static async Task StartClientWithRetries(IClusterClient client)
public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHostingEnvironment env)
Note que a configuração do cliente é parecida com o do host:
As diferenças é que agora estamos utilizando a classe ClientBuilder e se adiciona a interface IGraoContador (em detrimento a GraoContador definida no host.
Nesta classe também foi definido o método StartClientWithRetries que tenta se conectar ao host 5 vezes antes de desistir. Quando a conexão for obtida, o objeto client é retornado.
Este cliente será obtido no controller, conforme o código abaixo:
namespace InterfaceApi.Controllers
public class ContadorController : Controller
private IClusterClient client;
public ContadorController(IClusterClient client){
public async Task<int> Get()
var contador = client.GetGrain<IGraoContador>("TW-1");
return await contador.GetContador();
await contador.Incremento(1);
Para obter o grão, utilizamos o método GetGrain. A este método deve ser passado a chave do grão:
Como definimos que a chave dele será uma string, acima estou passando uma string arbitrária. A partir da instância obtida os métodos do grão são chamados, como o GetContador():
Com isso, nós estamos obtendo informações do nosso grão contido no silo.
Para finalizar, criei dentro da pasta wwwroot um arquivo HTML, onde os métodos da api são chamados:
<title>Exemplo de Orleans, no ASP.NET Core *.*</title>
Contador: <spam id="countValor">0</spam>
<button id="btnIncrement" class="btn-primary">Incrementar</button>
$.get("api/contador/", function (value) {
console.log('GET contador=' + value);
$('#countValor').html(value);
$('#btnIncrement').click(function () {
$.post("api/contador/", function () {
Pronto, a nossa aplicação está finalizada. Para testá-la, primeiro é necessário iniciar o Silo:
Em seguida a aplicação web:
No navegador teremos o resultado abaixo:
Ao clicar em "Incrementar", veremos o valor do contador ser incrementado:
Este é um exemplo simples, porém funcional, que nos dá uma noção do poder do Orleans. Em artigos futuros mostrarei mais detalhes dele.