<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rodrigo Schemes</title>
    <description>The latest articles on DEV Community by Rodrigo Schemes (@rodrigoschemes).</description>
    <link>https://dev.to/rodrigoschemes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1153568%2F2bcb16d3-3169-4f4d-99b6-99f7c180ddf1.jpeg</url>
      <title>DEV Community: Rodrigo Schemes</title>
      <link>https://dev.to/rodrigoschemes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rodrigoschemes"/>
    <language>en</language>
    <item>
      <title>🎮 Singleton e Concorrência em C# — Um Joguinho pra Aprender de Verdade</title>
      <dc:creator>Rodrigo Schemes</dc:creator>
      <pubDate>Tue, 10 Jun 2025 01:41:13 +0000</pubDate>
      <link>https://dev.to/rodrigoschemes/singleton-e-concorrencia-em-c-um-joguinho-pra-aprender-de-verdade-1k4o</link>
      <guid>https://dev.to/rodrigoschemes/singleton-e-concorrencia-em-c-um-joguinho-pra-aprender-de-verdade-1k4o</guid>
      <description>&lt;p&gt;Fiz esse exemplo pra entender melhor como o padrão &lt;strong&gt;Singleton&lt;/strong&gt; funciona na prática e como lidar com concorrência em C#. A ideia foi criar uma simulação de um jogo onde vários jogadores disputam uma pontuação limitada. No caminho, explorei técnicas de sincronização e execução paralela.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔄 O que é Singleton, afinal?
&lt;/h2&gt;

&lt;p&gt;O Singleton é um padrão de projeto que garante que uma classe tenha &lt;strong&gt;apenas uma instância&lt;/strong&gt; durante toda a execução do programa.&lt;/p&gt;

&lt;h3&gt;
  
  
  Por que usar isso?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;É útil quando precisamos de &lt;strong&gt;um ponto centralizado de controle&lt;/strong&gt;, como um serviço de log, um gerenciador de configuração ou — no nosso caso — uma pontuação global.&lt;/li&gt;
&lt;li&gt;Evita instanciar objetos repetidamente sem necessidade.&lt;/li&gt;
&lt;li&gt;Garante que todo mundo (todas as threads, inclusive) estejam olhando pro mesmo objeto.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No meu código usei &lt;code&gt;Lazy&amp;lt;T&amp;gt;&lt;/code&gt; pra deixar isso &lt;strong&gt;thread-safe&lt;/strong&gt; e garantir que a instância só seja criada quando for realmente usada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PlacarGlobal&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;Lazy&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GlobalScore&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_instancia&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;PlacarGlobal&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;PlacarGlobal&lt;/span&gt; &lt;span class="n"&gt;Instancia&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_instancia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;PlacarGlobal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🕹️ O jogo: como funciona?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Temos 500 pontos no total.&lt;/li&gt;
&lt;li&gt;5 jogadores jogam ao mesmo tempo, cada um numa thread (ou Task).&lt;/li&gt;
&lt;li&gt;A cada jogada, o jogador tenta pegar entre &lt;strong&gt;1 e 10 pontos aleatoriamente&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Quando os pontos acabam, o jogo termina e mostramos o ranking final.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚙️ Como fiz funcionar direitinho (sem bugs de concorrência)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;code&gt;lock&lt;/code&gt; para proteger a pontuação
&lt;/h3&gt;

&lt;p&gt;Como todos os jogadores acessam e alteram os mesmos dados (pontuação total e placar), usei um &lt;code&gt;lock&lt;/code&gt; pra evitar bagunça:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_lock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Acesso seguro&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso garante que &lt;strong&gt;só uma thread por vez&lt;/strong&gt; consiga pegar pontos.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Um cuidado com o &lt;code&gt;Random&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Se você usar &lt;code&gt;new Random()&lt;/code&gt; direto em várias threads, pode acabar com números repetidos. Resolvi isso gerando a semente com &lt;code&gt;Guid.NewGuid().GetHashCode()&lt;/code&gt;. Assim cada thread tem um gerador único:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;rng&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewGuid&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;GetHashCode&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Execução concorrente com &lt;code&gt;Task.Run&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Cada jogador roda numa &lt;code&gt;Task&lt;/code&gt;, e eu espero todas terminarem com &lt;code&gt;Task.WhenAll&lt;/code&gt;. Simples e eficiente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;jogadorId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ObterPontos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jogadorId&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rng&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;500&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WhenAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Ranking final com &lt;code&gt;ConcurrentDictionary&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Usei um &lt;code&gt;ConcurrentDictionary&lt;/code&gt; pra armazenar o placar de cada jogador. Ele já é thread-safe, então não precisei de mais &lt;code&gt;lock&lt;/code&gt; pra isso.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏁 Resultado típico
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Iniciando partida! ###
### Jogador 1 pegou 8 pontos. Restantes: 492 ###
...
### Jogador 3 terminou. ###

### Ranking Final: ###
#1 - Jogador 4 : 142 pontos
#2 - Jogador 2 : 129 pontos
#3 - Jogador 1 : 113 pontos
#4 - Jogador 5 : 74 pontos
#5 - Jogador 3 : 42 pontos

### Pontos distribuídos: 500/500 ###
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💭 O que eu aprendi com isso
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Singleton com &lt;code&gt;Lazy&amp;lt;T&amp;gt;&lt;/code&gt; é super simples e seguro.&lt;/li&gt;
&lt;li&gt;Concorrência em C# não precisa ser um bicho de sete cabeças se você usar &lt;code&gt;lock&lt;/code&gt; e &lt;code&gt;Task&lt;/code&gt; com cuidado.&lt;/li&gt;
&lt;li&gt;E dá pra se divertir criando um joguinho simples e ver os conceitos funcionando na prática.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se quiser, dá pra adaptar esse mesmo código pra outras situações onde vários processos disputam um recurso limitado.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔗 Código-fonte no GitHub
&lt;/h2&gt;

&lt;p&gt;Todo o código apresentado neste artigo está disponível no repositório:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/rodrigo-schemes/csharp-designpatterns/tree/main/Creational/Singleton" rel="noopener noreferrer"&gt;github.com/rodrigo-schemes/csharp-designpatterns&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sinta-se à vontade para clonar, estudar e até contribuir com sugestões ou melhorias. Esse projeto faz parte de uma série voltada para estudo e prática de Design Patterns com C#.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>singleton</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>Decorator Pattern com Scrutor no Asp.Net Core</title>
      <dc:creator>Rodrigo Schemes</dc:creator>
      <pubDate>Wed, 20 Sep 2023 19:47:41 +0000</pubDate>
      <link>https://dev.to/rodrigoschemes/decorator-pattern-com-scrutor-no-aspnet-core-2f2l</link>
      <guid>https://dev.to/rodrigoschemes/decorator-pattern-com-scrutor-no-aspnet-core-2f2l</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Uma das vantagens do ASP.NET Core é a sua capacidade de usar injeção de dependência para gerenciar serviços e componentes. No entanto, às vezes você pode precisar adicionar funcionalidades adicionais a esses serviços sem modificar seu código. É aí que o &lt;strong&gt;Decorator Pattern&lt;/strong&gt; entra em jogo, e uma ótima maneira de implementá-lo é usando a biblioteca &lt;strong&gt;Scrutor&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decorator Pattern
&lt;/h2&gt;

&lt;p&gt;O Decorator Pattern é um padrão de design estrutural que permite adicionar comportamento adicional a um objeto existente, sem modificar sua estrutura. Isso é feito criando classes decoradoras que envolvem o objeto original e adicionam as funcionalidades desejadas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scrutor
&lt;/h2&gt;

&lt;p&gt;O Scrutor é uma biblioteca para facilitar a implementação do Decorator Pattern ao injetar serviços em tempo de execução. Ele fornece uma maneira simples e limpa de adicionar funcionalidades a serviços existentes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementando o Decorator Pattern com Scrutor
&lt;/h2&gt;

&lt;p&gt;Vamos dar uma olhada em como implementar o Decorator Pattern com o Scrutor em um exemplo prático.&lt;/p&gt;

&lt;p&gt;Suponha que você tenha um repositório &lt;code&gt;IClienteRepositorio&lt;/code&gt; que realiza operações relacionadas a Clientes em sua API. Você deseja adicionar uma camada de cache a esse serviço sem modificar seu código existente.&lt;/p&gt;

&lt;p&gt;1. &lt;strong&gt;Crie uma Interface do seu Repositório de Clientes:&lt;/strong&gt; Essa interface é usada para representar um repositório de clientes, onde você pode buscar um cliente por seu ID.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IClienteRepositorio&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Cliente&lt;/span&gt;&lt;span class="p"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;ObterPorIdAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2. &lt;strong&gt;Implemente a Interface do Repositório&lt;/strong&gt;: Esta classe &lt;code&gt;ClienteRepositorio&lt;/code&gt; implementa a interface &lt;code&gt;IClienteRepositorio&lt;/code&gt; e fornece uma implementação para o método &lt;code&gt;ObterPorIdAsync&lt;/code&gt;, que busca um cliente pelo seu ID em um contexto de banco de dados.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ClienteRepositorio&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IClienteRepositorio&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;AppDbContexto&lt;/span&gt; &lt;span class="n"&gt;_appDbContexto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

       &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ClienteRepositorio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppDbContexto&lt;/span&gt; &lt;span class="n"&gt;appDbContexto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="n"&gt;_appDbContexto&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;appDbContexto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;

       &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Cliente&lt;/span&gt;&lt;span class="p"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;ObterPorIdAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_appDbContexto&lt;/span&gt;
               &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Cliente&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
               &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefaultAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cliente&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cliente&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClienteId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3. &lt;strong&gt;Crie a Classe do Decorator&lt;/strong&gt;: Essa classe será a implementação do Cache. Ela deverá implementar a interface original do repositório de Clientes.  Para simplificar o exemplo, vou utilizar o próprio serviço de Cache em memória do Asp.Net Core, o &lt;code&gt;IMemoryCache&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ClienteCacheRepositorio&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IClienteRepositorio&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IClienteRepositorio&lt;/span&gt; &lt;span class="n"&gt;_clienteRepositorio&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IMemoryCache&lt;/span&gt; &lt;span class="n"&gt;_memoryCache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ClienteCacheRepositorio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IClienteRepositorio&lt;/span&gt; &lt;span class="n"&gt;clienteRepositorio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;IMemoryCache&lt;/span&gt; &lt;span class="n"&gt;memoryCache&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_clienteRepositorio&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clienteRepositorio&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;_memoryCache&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;memoryCache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Cliente&lt;/span&gt;&lt;span class="p"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;ObterPorIdAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;chave&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"cliente-&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_memoryCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetOrCreateAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chave&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;cacheEntry&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;cacheEntry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetAbsoluteExpiration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromMinutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_clienteRepositorio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ObterPorIdAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4. &lt;strong&gt;Instale o pacote Scrutor:&lt;/strong&gt; você pode usar o gerenciador de pacotes NuGet com o seguinte comando: &lt;code&gt;dotnet add package Scrutor&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;5. &lt;strong&gt;Configure a Injeção de Dependência com o Scrutor&lt;/strong&gt;: No &lt;code&gt;Program.cs&lt;/code&gt;, configure a injeção de dependência para usar a classe do Decorator quando o &lt;code&gt;IClienteRepositorio&lt;/code&gt; for solicitado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddMemoryCache&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScoped&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IClienteRepositorio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ClienteRepositorio&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Decorate&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IClienteRepositorio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ClienteCacheRepositorio&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testando a implementação
&lt;/h2&gt;

&lt;p&gt;Podemos validar o funcionamento do padrão Decorator com o Scrutor através do Debug. Se colocarmos um breakpoint na implementação do método &lt;code&gt;ObterPorIdAsync&lt;/code&gt;, ele será executado apenas na primeira vez. Na segunda chamada, será utilizado o Memory Cache.&lt;/p&gt;

&lt;p&gt;Podemos verificar o resultado através do tempo de resposta no Postman. Na primeira chamada da API, obtemos o cliente com o código "1". O tempo de resposta foi de 413 ms.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RJ4l6yL0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cpwl3jix2zdar3vurhk8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RJ4l6yL0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cpwl3jix2zdar3vurhk8.png" alt="Postman - Primeira Chamada" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Na segunda chamada, podemos perceber a diferença no tempo de resposta, que foi de 10 ms, pois ele estava utilizando o cache de memória.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h6sTxGmp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qcxmkp9n0p73xa4dgjhy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h6sTxGmp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qcxmkp9n0p73xa4dgjhy.png" alt="Postman - Segunda Chamada" width="800" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;O Decorator Pattern é uma ferramenta poderosa para adicionar funcionalidades a objetos sem modificar seu código existente. Com o Scrutor em ASP.NET Core, você pode implementar facilmente o padrão Decorator ao injetar serviços em tempo de execução. Isso permite que você mantenha seu código limpo, modular e facilmente extensível.&lt;/p&gt;

&lt;p&gt;Em resumo, os benefícios do Decorator Pattern são:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Flexibilidade&lt;/strong&gt;: Permite adicionar funcionalidades extras a objetos sem modificar seu código original.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manutenção Simples&lt;/strong&gt;: Facilita a manutenção e evita classes excessivamente complexas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composição Dinâmica&lt;/strong&gt;: Permite combinar funcionalidades de maneira flexível.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reutilização de Código&lt;/strong&gt;: Os decoradores podem ser reutilizados em diferentes partes do sistema.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Segregação de Responsabilidades&lt;/strong&gt;: Mantém as classes com responsabilidades únicas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adere aos Princípios SOLID&lt;/strong&gt;: Segue princípios de design de software sólidos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escalabilidade&lt;/strong&gt;: Facilita a adição de novas funcionalidades sem alterar o código existente.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://refactoring.guru/design-patterns/decorator"&gt;Decorator Pattern - Refactoring Guru&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/khellang/Scrutor"&gt;Scrutor - Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/pt-br/aspnet/core/performance/caching/memory?view=aspnetcore-7.0"&gt;IMemoryCache - Documentação Microsoft&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rodrigo-schemes/aspnetcore-decorator-pattern"&gt;Repositório do GitHub - Rodrigo Bitencourt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=i_3I6XLAOt0"&gt;Youtube - Milan Jovanovic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dotnetcore</category>
      <category>csharp</category>
      <category>braziliandevs</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>CI/CD ASP.NET Core com GitHub Actions e Azure</title>
      <dc:creator>Rodrigo Schemes</dc:creator>
      <pubDate>Sun, 10 Sep 2023 00:53:53 +0000</pubDate>
      <link>https://dev.to/rodrigoschemes/cicd-aspnet-core-com-github-actions-e-azure-591j</link>
      <guid>https://dev.to/rodrigoschemes/cicd-aspnet-core-com-github-actions-e-azure-591j</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;A implantação contínua (CI/CD) é uma prática essencial no desenvolvimento de software moderno. Ela permite automatizar o processo de construção, teste e implantação de aplicativos, garantindo atualizações rápidas e confiáveis. Neste artigo, vamos explorar como configurar um pipeline de CI/CD para um aplicativo ASP.NET Core, usando o GitHub Actions e implantando-o no Serviço de Aplicativo do Azure.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é o GitHub Actions?
&lt;/h2&gt;

&lt;p&gt;O GitHub Actions é um serviço de automação oferecido pelo GitHub para ajudar os desenvolvedores a automatizar seus fluxos de trabalho de desenvolvimento de software. Ele permite que você crie, teste e implante seu código diretamente no GitHub. O melhor de tudo é que o GitHub Actions é gratuito para repositórios públicos e oferece uma generosa quantidade de minutos de execução para repositórios privados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pré-requisitos
&lt;/h2&gt;

&lt;p&gt;Antes de começarmos, certifique-se de ter o seguinte:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uma conta no GitHub.&lt;/li&gt;
&lt;li&gt;Um repositório contendo um aplicativo ASP.NET Core.&lt;/li&gt;
&lt;li&gt;Uma conta no Azure com acesso para criar um Serviço de Aplicativo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Configurando o Pipeline
&lt;/h2&gt;

&lt;p&gt;A seguir, veremos como configurar um pipeline de CI/CD para uma aplicação ASP.NET Core usando o GitHub Actions e implantá-la no Serviço de Aplicativo do Azure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Etapa 1: Adicione um arquivo de configuração para o GitHub Actions
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Acesse o seu repositório no GitHub.&lt;/li&gt;
&lt;li&gt;No menu superior do seu repositório, clique na guia "Actions".&lt;/li&gt;
&lt;li&gt;Na página "Actions", você verá uma opção chamada "Set up a workflow yourself" no lado direito. Clique nela.&lt;/li&gt;
&lt;li&gt;Você será direcionado para um editor de código. Substitua todo o conteúdo por este código YAML de exemplo:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;AZURE_WEBAPP_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;exemplo-api&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;publish&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup .NET&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-dotnet@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;dotnet-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;7.0.x'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Restore&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dotnet restore ./Exemplo/Exemplo.sln&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dotnet build ./Exemplo/Exemplo.sln --configuration Release --no-restore&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dotnet publish ./Exemplo/Exemplo.sln --configuration Release --no-build --property PublishDir=${{env.DOTNET_ROOT}}/myapp&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;azure/webapps-deploy@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;app-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.AZURE_WEBAPP_NAME }}&lt;/span&gt;
          &lt;span class="na"&gt;publish-profile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AZURE_PUBLISH_PROFILE }}&lt;/span&gt;
          &lt;span class="na"&gt;package&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{env.DOTNET_ROOT}}/myapp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Etapa 2: Configure o ambiente de implantação no Azure
&lt;/h3&gt;

&lt;p&gt;No Portal do Azure, crie um Serviço de Aplicativo (Web App) onde você deseja implantar seu aplicativo ASP.NET Core. Como essa etapa não é o foco deste tutorial, deixarei alguns artigos de referência para ajudar nesse processo.  Entretanto precisamos baixar o Perfil de Publicação para continuar a configuração no GitHub.&lt;/p&gt;

&lt;p&gt;Para esta etapa, na página do Serviço de Aplicativo criado, no menu superior, clique em “Baixar Perfil de Publicação”. O perfil de publicação será baixado como um arquivo XML. Salve esse arquivo em um local seguro no seu computador.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bT6JZq_B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tc0qnqe0uzvprb03jqwm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bT6JZq_B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tc0qnqe0uzvprb03jqwm.png" alt="Perfil de Publicação" width="800" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Etapa 3: Configure o Perfil de Publicação no Github Secrets
&lt;/h3&gt;

&lt;p&gt;Volte para o GitHub e acesse o seu repositório. Vá para as "Settings" (Configurações) do repositório e clique em "Secrets and variables" e depois em “Actions”. Adicione um novo segredo chamado &lt;code&gt;AZURE_PUBLISH_PROFILE&lt;/code&gt; e, como valor, insira o conteúdo do arquivo XML que você baixou (o conteúdo do perfil de publicação).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IMPORTANTE&lt;/strong&gt;: Nunca compartilhe ou exponha o Perfil de Publicação do Azure publicamente. Ele contém informações sensíveis de autenticação e autorização que podem comprometer a segurança do seu aplicativo e dos seus recursos no Azure. Mantenha-o em um local seguro e restrito, acessível apenas para aqueles que realmente precisam dele para fins de implantação.&lt;/p&gt;

&lt;h3&gt;
  
  
  Etapa 4: Realizando o Deploy
&lt;/h3&gt;

&lt;p&gt;Agora, com seu pipeline de CI/CD configurado, você pode monitorar seu funcionamento e fazer ajustes conforme necessário. O GitHub Actions se encarregará de construir, testar e implantar seu aplicativo no Azure sempre que houver um push na branch &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Na barra de navegação superior do repositório, você verá a guia "Actions". Clique nela para acessar a página de ações. Você verá uma lista de todos os workflows (fluxos de trabalho) configurados para esse repositório. Os workflows são organizados por nome e exibem o status atual de execução. Você verá informações como o nome do workflow, a data da execução mais recente e o status (por exemplo, sucesso, falha, em execução).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BLlADqBJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7b62nop8i0ox6p9cmoj2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BLlADqBJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7b62nop8i0ox6p9cmoj2.png" alt="Workflows" width="800" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para obter mais informações sobre uma execução específica, clique no número da execução na lista. Isso o levará a uma página com detalhes completos sobre a execução, incluindo logs de cada etapa executada. Dentro dos detalhes da execução, você pode acessar os logs de cada etapa individual do workflow. Isso permite que você veja informações detalhadas sobre o que aconteceu em cada etapa da execução.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z6W3v5Mp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uu1zrof0dk7f6gboxpt2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z6W3v5Mp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uu1zrof0dk7f6gboxpt2.png" alt="Detalhe do Workflow" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No Azure, na página do Serviço de Aplicativo, é possível verificar o log de implantações. Para isso, acesse o menu "Centro de Implantação" e, em seguida, clique em "Logs".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uNUvMw2D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1906igc7tjvb3q7vdg4j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uNUvMw2D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1906igc7tjvb3q7vdg4j.png" alt="Centro de Implantação" width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Configurar um pipeline de CI/CD para um aplicativo ASP.NET Core com o GitHub Actions é uma maneira eficaz de automatizar o processo de construção, teste e implantação. Isso permite que você entregue atualizações mais rapidamente e com mais confiança. Com as configurações e ajustes corretos, você pode criar um fluxo de trabalho robusto que melhora a qualidade e a eficiência do seu desenvolvimento de software.&lt;/p&gt;

&lt;p&gt;Lembre-se de que as configurações e os ambientes de implantação podem variar de acordo com suas necessidades específicas, mas este guia serve como um ponto de partida para configurar seu próprio pipeline de CI/CD com o GitHub Actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/pt/actions"&gt;Documentação do Github Actions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/pt-br/azure/app-service/quickstart-dotnetcore?tabs=net70&amp;amp;pivots=development-environment-azure-portal"&gt;Criar um Serviço de Aplicativo Azure em Asp.Net Core&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rodrigo-schemes/aspnetcore-github-actions"&gt;Repositório do Github - Rodrigo Schemes Bitencourt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=QP0pi7xe24s&amp;amp;list=PLYpjLpq5ZDGu8RXq5HoLqTll3YLBr3PNY&amp;amp;index=3"&gt;Youtube - Milan Jovanovic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aspnetcore</category>
      <category>braziliandevs</category>
      <category>github</category>
      <category>azure</category>
    </item>
    <item>
      <title>Tratamento de Exceção Global no Asp.Net Core</title>
      <dc:creator>Rodrigo Schemes</dc:creator>
      <pubDate>Tue, 05 Sep 2023 01:14:17 +0000</pubDate>
      <link>https://dev.to/rodrigoschemes/tratamento-de-excecao-global-no-aspnet-core-4l7b</link>
      <guid>https://dev.to/rodrigoschemes/tratamento-de-excecao-global-no-aspnet-core-4l7b</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;O tratamento de exceção é uma parte importante do desenvolvimento de software. Quando algo dá errado em uma aplicação, é importante ter um mecanismo para lidar com a exceção e fornecer um feedback adequado para o usuário. No Asp.Net Core, podemos usar o Middleware &lt;code&gt;UseExceptionHandler&lt;/code&gt; para lidar com exceções globalmente em toda a aplicação. Neste post, vamos apresentar um tutorial detalhado sobre como implementar um controle de erros de forma simples em sua API.&lt;/p&gt;

&lt;p&gt;Implementar um tratamento de erro global em uma API pode trazer uma série de benefícios significativos para o desenvolvimento e manutenção do seu aplicativo. Aqui estão alguns dos principais benefícios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Padronização do tratamento de erro&lt;/strong&gt;: ajuda a garantir que a abordagem de tratamento de erro seja igual em todos os endpoints e evita duplicação de código.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resposta amigável ao usuário:&lt;/strong&gt; Você pode retornar respostas amigáveis e compreensíveis aos usuários quando ocorrerem erros. Evite mensagens técnicas!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Segurança:&lt;/strong&gt; Tratar erros de forma adequada ajuda a evitar a exposição de informações sensíveis ou detalhes técnicos aos usuários ou a pessoas mal-intencionadas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoramento e análise&lt;/strong&gt;: Permite que você tenha uma visão geral dos tipos de erros que estão acontecendo com mais frequência.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tratamento de exceções não previstas:&lt;/strong&gt; Um tratamento de erro global permite capturar exceções não previstas.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Criando o Middleware
&lt;/h2&gt;

&lt;p&gt;Para criar o Middleware de tratamento de exceção, crie uma nova classe e nomeie-a como &lt;em&gt;TratamentoErroGlobal.cs&lt;/em&gt;. Em seguida, adicione o seguinte código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TratamentoErroGlobal&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;AdicionarTratamentoErroGlobal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;IApplicationBuilder&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseExceptionHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;applicationBuilder&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;applicationBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;contexto&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;contexto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusCode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;HttpStatusCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InternalServerError&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;erroNoRequest&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;contexto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Features&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IExceptionHandlerFeature&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;erroNoRequest&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;detalheProblema&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ProblemDetails&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;Status&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;HttpStatusCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InternalServerError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Erro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Erro no servidor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;Detail&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Ocorreu um erro interno."&lt;/span&gt;
                    &lt;span class="p"&gt;};&lt;/span&gt;

                    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;contexto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteAsJsonAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;detalheProblema&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui está uma explicação sobre como essa classe funciona:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;public static void AdicionarTratamentoErroGlobal(this IApplicationBuilder app)&lt;/code&gt;&lt;/strong&gt; 

&lt;ul&gt;
&lt;li&gt;Isso define um método de extensão para a interface &lt;strong&gt;&lt;code&gt;IApplicationBuilder&lt;/code&gt;&lt;/strong&gt; que adiciona o Middleware de tratamento de erro global.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;app.UseExceptionHandler(applicationBuilder =&amp;gt; { ... })&lt;/code&gt;&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Aqui, o método &lt;strong&gt;&lt;code&gt;UseExceptionHandler&lt;/code&gt;&lt;/strong&gt; é chamado no &lt;strong&gt;&lt;code&gt;IApplicationBuilder&lt;/code&gt;&lt;/strong&gt;, configurando o Middleware de tratamento de exceção. O código dentro do bloco é uma função de Callback que lida com a exceção e cria uma resposta apropriada.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;contexto.Response.StatusCode = (int)HttpStatusCode.InternalServerError&lt;/code&gt;&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Define o status code da resposta HTTP para 500 (InternalServerError) para indicar um erro no servidor.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;var erroNoRequest = contexto.Features.Get&amp;lt;IExceptionHandlerFeature&amp;gt;()&lt;/code&gt;&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Obtém as informações sobre a exceção que ocorreu durante o processamento da requisição.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;var detalheProblema = new ProblemDetails{ ... }&lt;/code&gt;&lt;/strong&gt; 

&lt;ul&gt;
&lt;li&gt;Aqui, criamos um objeto &lt;strong&gt;&lt;code&gt;ProblemDetails&lt;/code&gt;&lt;/strong&gt;, que é uma classe padrão do ASP.NET Core usada para representar detalhes de um problema. Definimos o status, o tipo, o título e os detalhes do erro.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;await contexto.Response.WriteAsJsonAsync(detalheProblema)&lt;/code&gt;&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Escreve a resposta como JSON contendo os detalhes do problema (representados pelo objeto &lt;strong&gt;&lt;code&gt;ProblemDetails&lt;/code&gt;&lt;/strong&gt;), utilizando o método assíncrono &lt;strong&gt;&lt;code&gt;WriteAsJsonAsync&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Configurando a Injeção de Dependência do Middleware
&lt;/h2&gt;

&lt;p&gt;Para configurar o Middleware de tratamento de exceção, precisamos adicionar o seguinte código em nossa classe &lt;em&gt;Program.cs&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AdicionarTratamentoErroGlobal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O método &lt;code&gt;AdicionarTratamentoErroGlobal&lt;/code&gt;é um método de extensão da classe &lt;code&gt;TratamentoErroGlobal&lt;/code&gt;. Isso significa que ele estende a funcionalidade da interface &lt;code&gt;IApplicationBuilder&lt;/code&gt;, permitindo adicionar um novo Middleware de tratamento de erros global à pipeline de processamento de solicitações do ASP.NET Core. Quando chamado no contexto da configuração da aplicação, ele configura o tratamento de erros global de forma apropriada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testando o Tratamento de Exceção Global
&lt;/h2&gt;

&lt;p&gt;Para testar o tratamento de exceção global, podemos adicionar um código que gera uma exceção não tratada em uma de nossas Controllers. Quando executarmos a aplicação e acessarmos essa rota, o Middleware de tratamento de exceção retornará uma resposta em JSON para o usuário com os tratamentos que criamos anteriormente.&lt;/p&gt;

&lt;p&gt;Crie uma classe chamada &lt;em&gt;ExemploController.cs&lt;/em&gt; e adicione o seguinte código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api/exemplo"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExemploController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ControllerBase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;ObterExemplo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Exceção causada intencionalmente"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;        
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos compilar e iniciar a API e, em seguida, através do Postman, fazer uma chamada GET para a rota &lt;a href="http://localhost:%5BPorta%5D/api/exemplo"&gt;http://localhost:[Porta]/api/exemplo&lt;/a&gt;. O retorno esperado deve ser o seguinte:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Erro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Erro no servidor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"detail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ocorreu um erro interno."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Wxa5wAW8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/frbr7cr5bej1710zai9c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Wxa5wAW8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/frbr7cr5bej1710zai9c.png" alt="Retorno do Tratamento de Erro Global da API" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;O tratamento de exceção é uma parte importante do desenvolvimento de software. No Asp.Net Core, podemos usar o Middleware &lt;code&gt;UseExceptionHandler&lt;/code&gt; para lidar com exceções globalmente em toda a aplicação. Neste post, vimos como configurar o Middleware de tratamento de exceção e devolver uma resposta personalizada para o usuário.&lt;/p&gt;

&lt;p&gt;Esta abordagem apresenta os seguintes benefícios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simplicidade&lt;/strong&gt;: &lt;code&gt;UseExceptionHandler&lt;/code&gt; é simples de configurar. Você pode simplesmente fornecer um Middleware para tratamento de erros e o ASP.NET Core cuida do resto.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recursos integrados:&lt;/strong&gt; fornece suporte integrado para exibir páginas de erro amigáveis ao desenvolvedor ou retornar respostas de erro no formato JSON, dependendo do tipo de solicitação.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistência&lt;/strong&gt;: por ser um recurso padrão do ASP.NET Core, ele garante uma abordagem consistente de tratamento de erros em diferentes partes do seu aplicativo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuração centralizada:&lt;/strong&gt; você pode configurar facilmente o tratamento de erros em um só lugar, facilitando o gerenciamento e a atualização.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Como contras desta abordagem, destaco o seguinte:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Customização limitada:&lt;/strong&gt; embora forneça algumas opções de personalização, &lt;code&gt;UseExceptionHandler&lt;/code&gt; pode não cobrir todos os cenários específicos de tratamento de erros que seu aplicativo exige.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controle de log limitado&lt;/strong&gt;: você pode ter controle limitado sobre como os erros são logados. O comportamento de log personalizado pode exigir soluções alternativas adicionais.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Em resumo, se as necessidades de tratamento de erros do seu aplicativo puderem ser atendidas pelos recursos fornecidos pelo &lt;code&gt;UseExceptionHandler&lt;/code&gt;Middleware, é uma abordagem conveniente e direta. Por outro lado, se você precisar de mais controle, personalização e flexibilidade, construir um Middleware customizado implementando a interface &lt;code&gt;IMiddleware&lt;/code&gt;pode ser a melhor escolha (e tema para um próximo post). Tenha em mente a complexidade da sua aplicação, a familiaridade da sua equipe com a tecnologia e as considerações de manutenção a longo prazo ao tomar esta decisão.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/pt-br/aspnet/core/web-api/handle-errors?view=aspnetcore-8.0"&gt;Como lidar com erros em APIs Web do ASP.NET Core&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-7.0"&gt;Asp.Net Core Middlewares&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rodrigo-schemes/aspnetcore-tratamento-erro-global"&gt;Repositório do Github - Rodrigo Schemes Bitencourt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dotnet</category>
      <category>braziliandevs</category>
      <category>tutorial</category>
      <category>csharp</category>
    </item>
  </channel>
</rss>
