> ## Content Index
> Fetch the complete content index at: https://www.azurebrasil.cloud/llms.txt
> Use this file to discover other available public pages before exploring further.

# Uma introdução ao .NET Aspire
- URL: https://www.azurebrasil.cloud/blog/uma-introducao-ao-net-aspire/
- Published: 2023-11-23T20:51:49.000Z
- Updated: 2023-11-23T20:51:49.000Z
- Author: Talles Valiatti

O [.NET Aspire](https://learn.microsoft.com/en-us/dotnet/aspire/get-started/aspire-overview?ref=azurebrasil.cloud) é uma plataforma lançada juntamente com o .NET 8, composto de aplicativos distribuídos, otimizados para a nuvem, observáveis e prontos para produção. Ele é disponibilizado por meio de um conjunto de pacotes NuGet que abordam preocupações específicas relacionadas à nuvem. Aplicativos nativos da nuvem são geralmente compostos por pequenos microsserviços interconectados, em vez de um único código monolítico, e costumam consumir diversos serviços, como bancos de dados, mensageria e armazenamento em cache.

Para esse post, vamos precisar que você possua os seguintes itens em sua máquina local:

- [.NET 8](https://dotnet.microsoft.com/pt-br/download/dotnet/8.0?ref=azurebrasil.cloud);
- [VS Code](https://code.visualstudio.com/?ref=azurebrasil.cloud);
- [C# extension para VS Code](https://code.visualstudio.com/docs/languages/csharp?ref=azurebrasil.cloud).

Além disso, vamos precisar do [.NET Aspire workload](https://learn.microsoft.com/en-us/dotnet/aspire/setup-tooling?tabs=dotnet-cli&ref=azurebrasil.cloud#install-net-aspire) que pode ser instalado diretamente via CLI:

```
dotnet workload install aspire
```

Case você esteja utilizando o [Visual Studio](https://visualstudio.microsoft.com/pt-br/?ref=azurebrasil.cloud), recomendo a leitura [**dessa parte**](https://learn.microsoft.com/en-us/dotnet/aspire/setup-tooling?tabs=visual-studio&ref=azurebrasil.cloud#install-net-aspire)!

Para construir o *template* padrão do .NET Aspire*,* vamos executar o seguinte comando:

```
dotnet new aspire-starter
```

Temos a estrutura da solução:

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2023/11/Screen-Shot-2023-11-16-at-14.15-1.png)

- *ServicesDefault*: projeto responsável em configurar as dependências que serão usadas na solução (Cache, banco de dados, etc ...) além das configurações gerais;
- *AppHost*: projeto responsável pela orquestração dos outros serviços. Esse projeto que deve ser executado (via VS Code, Visual Studio ou CLI) para levantar toda a solução;
- *ApiService*: projeto de *backend*. É uma aplicação do tipo [minimal API](https://learn.microsoft.com/en-us/aspnet/core/tutorials/min-web-api?view=aspnetcore-8.0&tabs=visual-studio&ref=azurebrasil.cloud);
- *Web*: Projeto de frontend. É uma aplicação [blazor](https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-8.0?view=aspnetcore-8.0&ref=azurebrasil.cloud#blazor).

Antes de executarmos o *template*, vamos fazer uma pequena modificação no *Program.cs* do projeto *apiService.* Iremos fazer a [injeção da interface ](https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection?ref=azurebrasil.cloud)[*ILogger<Program>*](https://learn.microsoft.com/pt-br/dotnet/core/extensions/logging?tabs=command-line&ref=azurebrasil.cloud)e fazer um registro de *log* logo no começo da execução do endpoint */weatherforecast.*

```
app.MapGet("/weatherforecast", ([FromServices] ILogger<Program> logger) =>
{
    
    logger.LogInformation("Weatherforecast endpoint executed!");
    
    var forecast =  Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
});
```

Além disso, o VS Code irá pedir para criar os arquivos necessários para execução da solução. Com os arquivos prontos, vamos apenas trocar o valor de *internalConsole* para *integratedTerminal,* como mostrado abaixo*:*

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2023/11/Group-1191.png)

Com as modificações prontas, vamos executar a solução via VS Code (Estamos executando o projeto *.AppHost*).

```
Ctrl + F5
```

Podemos verificar que a solução está rodando com sucesso. Vamos acessar o [*dashboard*](https://learn.microsoft.com/en-us/dotnet/aspire/dashboard?ref=azurebrasil.cloud)*!*

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2023/11/Group-1192.png)

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2023/11/Group-1195.png)

Como mostrado acima, podemos ver que temos dois projetos sendo executados: o *frontend* (*webfrontend*) e o *backend (apiservice).* Além disso, podemos ver quais são as portas do *localhost* que estão reservadas para essas aplicações.

Vamos acessar o *frontend* no caminho */weatherforecast.*

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2023/11/Screen-Shot-2023-11-21-at-16.19.14.png)

Essa página faz a busca de dados no *backend* e renderiza os dados no *browser.* Voltando ao *dashboard*, podemos ver foram gerados [Logs, Structured logs e Traces](https://learn.microsoft.com/en-us/dotnet/aspire/telemetry?ref=azurebrasil.cloud)dessa requisição!

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2023/11/Group-1193.png)

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2023/11/Group-1194.png)

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2023/11/Screen-Shot-2023-11-21-at-16.22.png)

Vamos simular uma [*exception*](https://learn.microsoft.com/en-gb/dotnet/csharp/fundamentals/exceptions/exception-handling?ref=azurebrasil.cloud) nessa chamada e verificar como que esse erro é mostrado pelo *dashboard.* No endpoint */weatherforecast,* vamos remover o *log* e lançar uma *exception* genérica.

```
app.MapGet("/weatherforecast", ([FromServices] ILogger<Program> logger) =>
{
    throw new Exception("Error!");

    var forecast =  Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
});
```

Executando novamente a solução e refazendo a chamada, podemos ver que o *frontend* realizou 4 chamada HTTP, e para cada chamada, f0i lançada uma *exception*. Isso aconteceu porque existe uma integração do [*IHttpClientFactory*](https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests?ref=azurebrasil.cloud) *do frontend* com o [Polly](https://tallesvaliatti.com/como-criar-chamadas-http-resilientes-com-o-polly-24d50f276387?ref=azurebrasil.cloud)!

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2023/11/Screen-Shot-2023-11-21-at-16.28.png)

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2023/11/Group-1198.png)

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2023/11/Group-1197.png)

Vale um estudo mais profundo sobre o [Polly](https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/implement-http-call-retries-exponential-backoff-polly?ref=azurebrasil.cloud)!

No .NET Aspire, existe o conceito de [components](https://learn.microsoft.com/en-us/dotnet/aspire/components-overview?ref=azurebrasil.cloud). Esses componentes são pacotes NuGet especializados em simplificar a integração de plataformas e serviços populares as soluções criadas com o Aspire. Esses serviços podem ser: bancos de dados, *cache*, *storage* e outros!

Por exemplo, para adicionarmos o *component* do [Azure cosmos DB](https://tallesvaliatti.com/introdu%C3%A7%C3%A3o-ao-azure-cosmos-db-asp-net-core-parte-1-da0ece0ac039?ref=azurebrasil.cloud) a nossa solução, basta seguirmos os seguintes passos: 

- Adicionar o componente via pacote NuGet:

```
dotnet add package Aspire.Microsoft.Azure.Cosmos --prerelease
```

- Fazer o registro do componente:

```
builder.AddAzureCosmosDB("cosmosConnectionName");
```

- Configuração da C*onnectionString* (via *appsettings.json*):

```json
{
  "ConnectionStrings": {
    "cosmosConnectionName": "<your-connection-string>"
  }
}

```

Dessa forma, teremos o [*CosmosClient*](https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.cosmos.cosmosclient?ref=azurebrasil.cloud) pronto para ser injetado via [DI](https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection?ref=azurebrasil.cloud) como *singleton* em nossa solução! 

Ainda falaremos muito sobre o .NET Aspire! Recomendo que você veja a [documentação oficial](https://learn.microsoft.com/pt-br/dotnet/aspire/?ref=azurebrasil.cloud) e aprofunde mais nos conceitos que essa ferramenta tem a oferecer!

Você já pode baixar o projeto por esse [](https://github.com/TallesValiatti/AzureAILanguage?ref=azurebrasil.cloud)[link](https://github.com/TallesValiatti/AspireGetstarted?ref=azurebrasil.cloud), e não esquece de me seguir no [LinkedIn](https://www.linkedin.com/in/tallesvaliatti/?ref=azurebrasil.cloud)!

Até a próxima, abraços!