<?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: Gabriel Amarantes</title>
    <description>The latest articles on DEV Community by Gabriel Amarantes (@amarantess).</description>
    <link>https://dev.to/amarantess</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%2F2553676%2Fc2e9a90e-8364-44fb-af89-6660ac4a2d54.jpeg</url>
      <title>DEV Community: Gabriel Amarantes</title>
      <link>https://dev.to/amarantess</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amarantess"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Gabriel Amarantes</dc:creator>
      <pubDate>Wed, 08 Oct 2025 11:07:56 +0000</pubDate>
      <link>https://dev.to/amarantess/-2j5c</link>
      <guid>https://dev.to/amarantess/-2j5c</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/willem_janssen_ca51a0bfba" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3510871%2F05072808-1ebc-4e41-a543-6b6b4aca12b8.png" alt="willem_janssen_ca51a0bfba"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/willem_janssen_ca51a0bfba/understanding-codecs-containers-and-bitrates-what-every-developer-using-ffmpeg-should-know-2m5" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Understanding Codecs, Containers, and Bitrates: What Every Developer Using FFmpeg Should Know&lt;/h2&gt;
      &lt;h3&gt;Willem Janssen ・ Oct 7&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#ffmpeg&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#video&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#dotnet&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#media&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>ffmpeg</category>
      <category>video</category>
      <category>dotnet</category>
      <category>media</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Gabriel Amarantes</dc:creator>
      <pubDate>Tue, 30 Sep 2025 11:17:38 +0000</pubDate>
      <link>https://dev.to/amarantess/-1cmc</link>
      <guid>https://dev.to/amarantess/-1cmc</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/willem_janssen_ca51a0bfba/how-to-build-a-command-line-video-converter-with-net-8-and-ffmpeg-3fkd" class="crayons-story__hidden-navigation-link"&gt;How to Build a Command-Line Video Converter with .NET 8 and FFmpeg&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/willem_janssen_ca51a0bfba" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3510871%2F05072808-1ebc-4e41-a543-6b6b4aca12b8.png" alt="willem_janssen_ca51a0bfba profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/willem_janssen_ca51a0bfba" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Willem Janssen
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Willem Janssen
                
              
              &lt;div id="story-author-preview-content-2878898" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/willem_janssen_ca51a0bfba" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3510871%2F05072808-1ebc-4e41-a543-6b6b4aca12b8.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Willem Janssen&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/willem_janssen_ca51a0bfba/how-to-build-a-command-line-video-converter-with-net-8-and-ffmpeg-3fkd" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Sep 30 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/willem_janssen_ca51a0bfba/how-to-build-a-command-line-video-converter-with-net-8-and-ffmpeg-3fkd" id="article-link-2878898"&gt;
          How to Build a Command-Line Video Converter with .NET 8 and FFmpeg
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/csharp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;csharp&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/dotnet"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;dotnet&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/cli"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;cli&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/willem_janssen_ca51a0bfba/how-to-build-a-command-line-video-converter-with-net-8-and-ffmpeg-3fkd" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/willem_janssen_ca51a0bfba/how-to-build-a-command-line-video-converter-with-net-8-and-ffmpeg-3fkd#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              2&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>csharp</category>
      <category>tutorial</category>
      <category>dotnet</category>
      <category>cli</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Gabriel Amarantes</dc:creator>
      <pubDate>Fri, 26 Sep 2025 11:28:12 +0000</pubDate>
      <link>https://dev.to/amarantess/-4hka</link>
      <guid>https://dev.to/amarantess/-4hka</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/tal7aouy" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F621422%2F86459b07-707e-41b8-b0f8-7c3144622f95.jpeg" alt="tal7aouy"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/tal7aouy/clean-commit-messages-why-how-1p3i" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;🚀 Clean Commit Messages: Why &amp;amp; How&lt;/h2&gt;
      &lt;h3&gt;Mhammed Talhaouy ・ Sep 26&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#commit&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#git&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#development&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#ai&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>commit</category>
      <category>git</category>
      <category>development</category>
      <category>ai</category>
    </item>
    <item>
      <title>C# Parallelism - A Quick Overview</title>
      <dc:creator>Gabriel Amarantes</dc:creator>
      <pubDate>Fri, 05 Sep 2025 13:00:00 +0000</pubDate>
      <link>https://dev.to/amarantess/c-parallelism-a-quick-overview-2391</link>
      <guid>https://dev.to/amarantess/c-parallelism-a-quick-overview-2391</guid>
      <description>&lt;p&gt;Have you ever wondered how your PC can run so many apps at the same time? Or why your application &lt;strong&gt;freezes&lt;/strong&gt; while processing something intensive?&lt;/p&gt;

&lt;p&gt;In this article, we'll explore the concepts of &lt;strong&gt;Parallelism&lt;/strong&gt; and &lt;strong&gt;Concurrency&lt;/strong&gt;, specifically in C#. What are they? How are they different? And most importantly, how can we &lt;strong&gt;write parallel code&lt;/strong&gt; to make our applications faster?&lt;/p&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Concurrency?
&lt;/h2&gt;

&lt;p&gt;Concurrency means managing multiple tasks over the same period, but not necessarily executing them at the exact same instant.&lt;/p&gt;

&lt;p&gt;Imagine a restaurant with just &lt;strong&gt;one chef&lt;/strong&gt;. To be efficient, the chef starts boiling water for pasta. While the water is heating up (a waiting period), they start chopping vegetables for a salad. The chef is &lt;strong&gt;making progress on both tasks by switching between them&lt;/strong&gt;. This is concurrency.&lt;/p&gt;

&lt;p&gt;In computing, this is what happens on a single-core CPU. The CPU performs &lt;strong&gt;context switching&lt;/strong&gt;: it runs a small piece of one task, then quickly switches to another. It does this so fast that it creates the &lt;strong&gt;illusion&lt;/strong&gt; of tasks running at the same time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Parallelism?
&lt;/h2&gt;

&lt;p&gt;Parallelism is when multiple tasks are executed at the &lt;strong&gt;exact same time&lt;/strong&gt;, each on its own CPU core.&lt;/p&gt;

&lt;p&gt;Let's return to our restaurant. Now, it has &lt;strong&gt;two cooks&lt;/strong&gt;. Cook 1 can make the pasta while Cook 2 makes the salad, &lt;strong&gt;simultaneously&lt;/strong&gt;. They are working in &lt;strong&gt;parallel&lt;/strong&gt;. This approach truly saves time because more work gets done in the same period.&lt;/p&gt;

&lt;p&gt;Parallel programming uses this exact approach. Instead of running tasks one after another, we execute them simultaneously to &lt;strong&gt;maximize&lt;/strong&gt; the use of our hardware. For example, an application processing video from multiple cameras can handle each feed at the same time.&lt;/p&gt;

&lt;p&gt;True parallelism is &lt;strong&gt;only possible&lt;/strong&gt; when you have more than one CPU core (or in our analogy, more than one cook!).&lt;/p&gt;

&lt;h2&gt;
  
  
  Threads
&lt;/h2&gt;

&lt;p&gt;A thread is the smallest unit of execution within a process (a process is your running program, like an &lt;code&gt;.exe&lt;/code&gt;). Every C# application starts with a &lt;strong&gt;main thread&lt;/strong&gt;, but we can create additional threads (called &lt;strong&gt;worker threads)&lt;/strong&gt; to run tasks in parallel or concurrently.&lt;/p&gt;

&lt;p&gt;To create a thread manually, you instantiate the &lt;code&gt;System.Threading.Thread&lt;/code&gt; class and pass it the method you want to execute. Then, you call the &lt;code&gt;Start()&lt;/code&gt; method to begin execution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymvx5xdb57jqnujggg01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymvx5xdb57jqnujggg01.png" alt="How create and start a Thread" width="800" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can request a thread to stop using a CancellationToken or pause it using Thread.Sleep. However, manually creating and destroying threads is resource-intensive, consuming significant CPU time and memory. Because of this complexity and cost, you should be careful when using the Thread class directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Task Parallel Library (TPL)
&lt;/h2&gt;

&lt;p&gt;Fortunately, .NET provides a much better way to write parallel code without needing to manage threads manually. It’s a powerful library called the &lt;strong&gt;Task Parallel Library (TPL)&lt;/strong&gt;, and it handles all the complex work of dividing tasks among CPU cores for you. The TPL dynamically scales the degree of concurrency to use all available processor most efficiently.&lt;/p&gt;

&lt;p&gt;Under the hood, the TPL uses the &lt;strong&gt;ThreadPool&lt;/strong&gt;, which is a pool of pre-created worker threads ready to execute work. This avoids the high cost of creating and destroying threads for every small task.&lt;/p&gt;

&lt;h2&gt;
  
  
  TPL Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Scenario 1: Processing a Collection
&lt;/h3&gt;

&lt;p&gt;Let’s look at a common scenario: processing a large collection of items. Imagine we have a method that performs a CPU-intensive operation, like converting thousands of videos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sequential code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwu9jzc9w2j7qni7ddnwy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwu9jzc9w2j7qni7ddnwy.png" alt="Scenario 1: Sequential Code" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Parallel code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fat5i361pm4t7aqnfreat.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fat5i361pm4t7aqnfreat.png" alt="Scenario 1: Parallel Code" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By simply switching from &lt;code&gt;foreach&lt;/code&gt; to &lt;code&gt;Parallel.ForEach&lt;/code&gt; , we told the TPL to run the &lt;code&gt;ConvertToMp4&lt;/code&gt; operation on multiple CPU cores at the same time. The TPL automatically manages everything, and the result is a massive performance boost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 2: Running Independent Operations
&lt;/h3&gt;

&lt;p&gt;Now, let’s look another scenario: running two independent operations concurrently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sequential Code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xmc1lv3lz2ouhb3je5k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xmc1lv3lz2ouhb3je5k.png" alt="Scenario 2: Sequential Code" width="800" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Parallel Code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkdwm709u107j5cablm8e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkdwm709u107j5cablm8e.png" alt="Scenario 2: Parallel Code" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the sequential code, we wait for &lt;code&gt;GetMkvVideos()&lt;/code&gt; to finish completely before we even start &lt;code&gt;GetMp4Videos()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By using Task.WhenAll, we start both operations at the same time and wait for them both to complete. This is ideal for asynchronous I/O operations (like database queries or API calls). While one operation is waiting for a response from the network, the other can be running. This overlaps the waiting periods, drastically reducing the total time and making better use of resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use&lt;/strong&gt; &lt;code&gt;Parallel&lt;/code&gt; &lt;strong&gt;for CPU-Bound Work&lt;/strong&gt;. Is your code doing heavy calculations, image processing, or complex transformation? &lt;code&gt;Parallel.ForEach&lt;/code&gt; is an excellent choice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use&lt;/strong&gt; &lt;code&gt;async/await&lt;/code&gt; &lt;strong&gt;for I/O-Bound Work&lt;/strong&gt;. Is your code waiting for a database, an API call, or reading a file from network? &lt;code&gt;async/await&lt;/code&gt; with &lt;code&gt;Task.WhenAll&lt;/code&gt; is the right tool. It prevents threads from being blocked while waiting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Always Prefer the TPL over&lt;/strong&gt; &lt;code&gt;Thread&lt;/code&gt;. The Task Parallel Library (&lt;code&gt;Task, Parallel.ForEach&lt;/code&gt;) is safer, more efficient, and easier to use than creating threads manually. Avoid &lt;code&gt;new Thread()&lt;/code&gt; unless you have a very specific reason.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure, Don’t Guess!&lt;/strong&gt; Parallelism has a small overhead. For very small or very fast loops, it can sometimes be slower than a sequential one. Always use a &lt;code&gt;Stopwatch&lt;/code&gt; to measure your code and confirm you’re getting a real performance benefit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Parallelism is a powerful tool in the modern C# developer’s toolkit. By understanding the basics of the TPL, you can unlock the full potential of today’s multi-core processors and build faster, more responsive applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;For more informartion, check out the official Microsoft documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/" rel="noopener noreferrer"&gt;Parallel Programming in .NET&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/task-parallel-library-tpl" rel="noopener noreferrer"&gt;Task Parallel Library (TPL)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/threading/managed-threading-basics" rel="noopener noreferrer"&gt;Managed Threading Basics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>learning</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Desvendando o HTTP: O Protocolo por Trás da Web e das APIs</title>
      <dc:creator>Gabriel Amarantes</dc:creator>
      <pubDate>Tue, 01 Jul 2025 23:36:55 +0000</pubDate>
      <link>https://dev.to/amarantess/desvendando-o-http-o-protocolo-por-tras-da-web-e-das-apis-5j3</link>
      <guid>https://dev.to/amarantess/desvendando-o-http-o-protocolo-por-tras-da-web-e-das-apis-5j3</guid>
      <description>&lt;p&gt;Imagine a internet como uma conversa global entre milhões de computadores. Para que essa comunicação funcione sem ruídos, todos precisam falar o mesmo "idioma". Esse idioma universal da web é o &lt;strong&gt;HTTP (Hypertext Transfer Protocol)&lt;/strong&gt;.&lt;br&gt;
É graças a ele que seu navegador consegue carregar esta página e que as APIs RESTful, que você constrói e consome, trocam dados de forma estruturada e previsível.&lt;/p&gt;

&lt;p&gt;Neste artigo vamos entender o HTTP. Desmontaremos suas mensagens, entenderemos seus métodos e códigos de status e veremos como tudo isso se aplica na prática com exemplos em &lt;strong&gt;ASP.NET Core&lt;/strong&gt;. O objetivo é dar a você, desenvolvedor, o conhecimento necessário para construir sistemas mais robustos, eficientes e seguros.&lt;/p&gt;




&lt;h2&gt;
  
  
  O que é HTTP?
&lt;/h2&gt;

&lt;p&gt;O &lt;strong&gt;HTTP (Hypertext Transfer Protocol)&lt;/strong&gt;, ou Protocolo de Transferência de Hipertexto, é um protocolo da camada de aplicação que funciona como o alicerce para a troca de dados na World Wide Web. Embora o nome "Hipertexto" remeta aos primórdios da web (links e documentos), hoje ele é usado para transferir qualquer tipo de dado: JSON, imagens, vídeos, etc.&lt;/p&gt;

&lt;p&gt;Podemos pensar em um protocolo como um conjunto de regras para uma conversa. O HTTP define exatamente como essa conversa deve acontecer entre dois participantes principais: o &lt;strong&gt;cliente&lt;/strong&gt; e o &lt;strong&gt;servidor&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cliente-Servidor
&lt;/h3&gt;

&lt;p&gt;A comunicação HTTP segue um fluxo rigoroso e unidirecional:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;O Cliente Faz a Requisição:&lt;/strong&gt; O cliente (um navegador, seu aplicativo C# ou até uma geladeira inteligente) sempre inicia a comunicação, enviando uma mensagem de requisição (request) a um servidor para solicitar um recurso ou ação (ex: "me dê a página de login" ou "crie este novo usuário").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O Servidor Envia a Resposta:&lt;/strong&gt; O servidor (onde sua API ASP.NET Core está hospedada, por exemplo) processa a requisição e devolve uma mensagem de resposta (response), contendo o resultado daquela solicitação. O servidor nunca inicia uma conversa; ele apenas responde.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Essa comunicação é feita através de mensagens de texto legíveis por humanos (no HTTP/1.1) e transportada de forma confiável pelo &lt;strong&gt;TCP (Transmission Control Protocol)&lt;/strong&gt;, que garante que as mensagens cheguem sem erros e na ordem correta.&lt;/p&gt;

&lt;p&gt;O protocolo HTTP não é exclusivo de navegadores, qualquer dispositivo conectado a rede pode usa-lo, como Smartphones, Carros, Geladeiras, SmartWatchs, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stateless
&lt;/h3&gt;

&lt;p&gt;Uma das características mais importantes e definidoras do HTTP é que ele é &lt;strong&gt;stateless&lt;/strong&gt; (sem estado). Isso significa que cada requisição é um evento completamente independente. O servidor não tem nenhuma memória das requisições anteriores feitas pelo mesmo cliente.&lt;/p&gt;

&lt;p&gt;Imagine uma conversa onde, a cada frase que você fala, precisa se reapresentar e dar todo o contexto novamente. É assim que o HTTP funciona. Se você faz login em uma requisição, o servidor não se lembrará de você na próxima.&lt;/p&gt;

&lt;p&gt;Embora pareça uma limitação, esse design torna o sistema mais simples e escalável. Para contornar essa "amnésia" e manter o contexto (como um usuário logado), os desenvolvedores utilizam estratégias como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tokens de Autorização (JWT):&lt;/strong&gt; O cliente recebe um "crachá" (token) após o login e o apresenta em cada requisição futura para provar quem é.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cookies:&lt;/strong&gt; O servidor envia um pequeno dado (cookie) para o cliente armazenar. O cliente, então, envia esse mesmo cookie de volta a cada nova requisição para aquele servidor, ajudando a "lembrá-lo" de informações passadas.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Estrutura de uma mensagem HTTP
&lt;/h2&gt;

&lt;p&gt;Tanto as requisições do cliente quanto as respostas do servidor seguem uma estrutura padrão, composta por três partes principais: uma linha inicial (&lt;em&gt;Start-Line&lt;/em&gt;), um bloco de cabeçalhos (&lt;em&gt;Headers&lt;/em&gt;) e, opcionalmente, um corpo (&lt;em&gt;Body&lt;/em&gt;). Vamos entender cada uma.&lt;/p&gt;

&lt;h3&gt;
  
  
  Requisição (Request)
&lt;/h3&gt;

&lt;p&gt;Imagine que nosso aplicativo C# precisa criar um novo usuário através de uma API. A mensagem HTTP enviada ao servidor seria parecida com esta:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fia00ywaemrstd252mi34.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fia00ywaemrstd252mi34.png" alt="Exemplo de Requisição" width="800" height="496"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos analisar a estrutura:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start-Line (Linha de Requisição):&lt;/strong&gt; &lt;code&gt;POST /api/usuarios HTTP/1.1&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Método (Verbo):&lt;/strong&gt; &lt;code&gt;POST&lt;/code&gt;. A ação que o cliente deseja executar;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URI (Request Target):&lt;/strong&gt; &lt;code&gt;/api/usuarios&lt;/code&gt;. O caminho do recurso no servidor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versão do HTTP:&lt;/strong&gt; &lt;code&gt;HTTP/1.1&lt;/code&gt;. A versão do protocolo que está sendo usada.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Headers (Cabeçalhos):&lt;/strong&gt; O bloco de texto seguinte, contendo pares de chave-valor (&lt;code&gt;Host&lt;/code&gt;, &lt;code&gt;Content-Type&lt;/code&gt;, etc.), que fornecem metadados essenciais sobre a requisição.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Linha em Branco:&lt;/strong&gt; Note que existe uma linha vazia que separa os cabeçalhos do corpo da mensagem. &lt;strong&gt;Isso não é opcional!&lt;/strong&gt; É essa linha que sinaliza para o servidor o fim dos cabeçalhos e o início do corpo.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Body (Corpo):&lt;/strong&gt; &lt;code&gt;{"nome": "Usuario", ...}&lt;/code&gt;. É aqui que os dados são efetivamente enviados. O corpo é opcional e geralmente usado com métodos como &lt;code&gt;POST&lt;/code&gt;, &lt;code&gt;PUT&lt;/code&gt; e &lt;code&gt;PATCH&lt;/code&gt;.&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Resposta (Response)
&lt;/h3&gt;

&lt;p&gt;Se o usuário for criado com sucesso, o servidor poderia responder com a seguinte mensagem:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jvfcjse8ea9fel4po7e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jvfcjse8ea9fel4po7e.png" alt="Exemplo de Resposta" width="800" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A estrutura é muito similar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start-Line (Linha de Status):&lt;/strong&gt; &lt;code&gt;HTTP/1.1 201 Created&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Versão do HTTP:&lt;/strong&gt; &lt;code&gt;HTTP/1.1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Código de Status (Status Code):&lt;/strong&gt; &lt;code&gt;201&lt;/code&gt;. Um número que indica o resultado da requisição.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mensagem de Status (Reason Phrase):&lt;/strong&gt; &lt;code&gt;Created&lt;/code&gt;. Uma breve descrição textual do código.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Headers (Cabeçalhos):&lt;/strong&gt; Metadados sobre a resposta (&lt;code&gt;Date&lt;/code&gt;, &lt;code&gt;Content-Type&lt;/code&gt;, etc.).&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Linha em Branco:&lt;/strong&gt; Separa os cabeçalhos do corpo.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Body (Corpo):&lt;/strong&gt; O recurso que foi criado ou solicitado, neste caso, o JSON do novo usuário.&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Headers
&lt;/h3&gt;

&lt;p&gt;Os cabeçalhos são o coração dos metadados no HTTP. Eles são pares de chave-valor, onde a chave não diferencia maiúsculas de minúsculas (&lt;em&gt;case-insensitive&lt;/em&gt;). Abaixo estão alguns dos mais comuns que todo desenvolvedor deve conhecer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Host&lt;/code&gt;&lt;/strong&gt;: (Requisição) Especifica o domínio do servidor (e a porta, se não for a padrão). Essencial para que o servidor saiba qual site ou API está sendo chamado. Ex: &lt;code&gt;Host: api.github.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Authorization&lt;/code&gt;&lt;/strong&gt;: (Requisição) Fornece as credenciais para autenticar o cliente no servidor. Muito usado com o padrão &lt;em&gt;Bearer Token&lt;/em&gt; para enviar JWTs. Ex: &lt;code&gt;Authorization: Bearer &amp;lt;token&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Accept&lt;/code&gt;&lt;/strong&gt;: (Requisição) Informa ao servidor quais tipos de conteúdo (MIME types) o cliente é capaz de entender. Ex: &lt;code&gt;Accept: application/json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Content-Type&lt;/code&gt;&lt;/strong&gt;: (Requisição/Resposta) Indica o tipo de mídia do corpo da mensagem. Ex: &lt;code&gt;Content-Type: application/json; charset=utf-8&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Content-Length&lt;/code&gt;&lt;/strong&gt;: (Requisição/Resposta) O tamanho do corpo da mensagem em bytes. Ex: &lt;code&gt;Content-Length: 56&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;User-Agent&lt;/code&gt;&lt;/strong&gt;: (Requisição) Uma string que identifica o cliente (navegador, aplicação C#, etc.). Ex: &lt;code&gt;User-Agent: MeuAppC#/1.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Allow&lt;/code&gt;&lt;/strong&gt;: (Resposta) Em uma resposta &lt;code&gt;405 Method Not Allowed&lt;/code&gt;, o servidor informa quais métodos são permitidos para aquele recurso. Ex: &lt;code&gt;Allow: GET, POST&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Location&lt;/code&gt;&lt;/strong&gt;: (Resposta) Usado em redirecionamentos (status &lt;code&gt;3xx&lt;/code&gt;) ou em respostas de criação (status &lt;code&gt;201&lt;/code&gt;) para indicar a URL do novo recurso. Ex: &lt;code&gt;Location: /api/usuarios/123&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Cookie&lt;/code&gt;&lt;/strong&gt;: (Requisição) Contém os cookies previamente enviados pelo servidor com o cabeçalho &lt;code&gt;Set-Cookie&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Set-Cookie&lt;/code&gt;&lt;/strong&gt;: (Resposta) Envia um cookie do servidor para ser armazenado pelo cliente. Ex: &lt;code&gt;Set-Cookie: sessionId=abc123; HttpOnly&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Métodos (ou verbos) HTTP
&lt;/h2&gt;

&lt;p&gt;Se as mensagens HTTP são as "cartas" que trocamos com o servidor, os &lt;strong&gt;Métodos (ou Verbos) HTTP&lt;/strong&gt; são a primeira palavra dessa carta, indicando a intenção principal: você quer ler, criar, modificar ou apagar algo? Em uma API RESTful, esses verbos são a base para a manipulação de recursos.&lt;/p&gt;

&lt;p&gt;Antes de detalharmos cada um, precisamos entender dois conceitos técnicos cruciais que os diferenciam:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Segurança (Safe):&lt;/strong&gt; Um método é considerado &lt;strong&gt;seguro&lt;/strong&gt; se ele &lt;strong&gt;não altera o estado&lt;/strong&gt; do recurso no servidor. Pense nisso como uma operação de "apenas leitura". Você pode fazer a requisição quantas vezes quiser sem causar efeitos colaterais.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Idempotência (Idempotent):&lt;/strong&gt; Um método é &lt;strong&gt;idempotente&lt;/strong&gt; se realizar a mesma requisição várias vezes produz &lt;strong&gt;exatamente o mesmo resultado&lt;/strong&gt; que realizá-la uma única vez.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exemplo:&lt;/strong&gt; &lt;code&gt;DELETE /usuarios/123&lt;/code&gt;. A primeira chamada apaga o usuário. A segunda, terceira e quarta chamadas retornarão um erro "Não Encontrado", mas o estado final do servidor é o mesmo: o usuário 123 continua apagado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contraexemplo:&lt;/strong&gt; &lt;code&gt;POST /usuarios&lt;/code&gt;. Chamar isso três vezes criará três novos usuários diferentes. Portanto, &lt;code&gt;POST&lt;/code&gt; não é idempotente.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Verbos Essenciais do CRUD
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;GET&lt;/strong&gt; (Ler)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O que faz:&lt;/strong&gt; Solicita a representação de um recurso específico ou uma coleção de recursos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Características:&lt;/strong&gt; &lt;strong&gt;É seguro&lt;/strong&gt; e &lt;strong&gt;é idempotente&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exemplos:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GET /api/usuarios&lt;/code&gt; (busca a lista de todos os usuários)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /api/usuarios/123&lt;/code&gt; (busca o usuário com ID 123)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Em ASP.NET Core:&lt;/strong&gt; &lt;code&gt;[HttpGet]&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegkl7leimip439reiml9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegkl7leimip439reiml9.png" alt="Exemplo em ASP.NET Core" width="800" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;POST&lt;/strong&gt; (Criar)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O que faz:&lt;/strong&gt; Envia dados (no corpo da requisição) para o servidor para criar um novo recurso.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Características:&lt;/strong&gt; &lt;strong&gt;Não é seguro&lt;/strong&gt; e &lt;strong&gt;não é idempotente&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exemplo:&lt;/strong&gt; &lt;code&gt;POST /api/usuarios&lt;/code&gt; (cria um novo usuário com os dados enviados no corpo)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Em ASP.NET Core:&lt;/strong&gt; &lt;code&gt;[HttpPost]&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftifb6bd40aapxfnnd982.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftifb6bd40aapxfnnd982.png" alt="Exemplo em ASP.NET Core" width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;PUT&lt;/strong&gt; (Atualizar/Substituir)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O que faz:&lt;/strong&gt; Substitui &lt;strong&gt;completamente&lt;/strong&gt; um recurso existente com os dados enviados no corpo. Se o recurso não existir, pode criá-lo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Características:&lt;/strong&gt; &lt;strong&gt;Não é seguro&lt;/strong&gt;, mas &lt;strong&gt;é idempotente&lt;/strong&gt;. (Enviar o mesmo corpo 5 vezes para a mesma URL resultará no mesmo estado final do recurso).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exemplo:&lt;/strong&gt; &lt;code&gt;PUT /api/usuarios/123&lt;/code&gt; (substitui todos os dados do usuário 123)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Em ASP.NET Core:&lt;/strong&gt; &lt;code&gt;[HttpPut]&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft28ziwt621e3g5owdxq3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft28ziwt621e3g5owdxq3.png" alt="Exemplo em ASP.NET Core" width="800" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;DELETE&lt;/strong&gt; (Apagar)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O que faz:&lt;/strong&gt; Remove um recurso específico.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Características:&lt;/strong&gt; &lt;strong&gt;Não é seguro&lt;/strong&gt;, mas &lt;strong&gt;é idempotente&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exemplo:&lt;/strong&gt; &lt;code&gt;DELETE /api/usuarios/123&lt;/code&gt; (apaga o usuário 123)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Em ASP.NET Core:&lt;/strong&gt; &lt;code&gt;[HttpDelete]&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fosl6zri2ujtad0ccjjqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fosl6zri2ujtad0ccjjqy.png" alt="Exemplo em ASP.NET Core" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;PATCH&lt;/strong&gt; (Atualizar/Modificar)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O que faz:&lt;/strong&gt; Aplica uma &lt;strong&gt;modificação parcial&lt;/strong&gt; a um recurso existente. Ao contrário do &lt;code&gt;PUT&lt;/code&gt;, você envia apenas os campos que deseja alterar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Características:&lt;/strong&gt; &lt;strong&gt;Não é seguro&lt;/strong&gt; e, geralmente, &lt;strong&gt;não é idempotente&lt;/strong&gt; (duas requisições &lt;code&gt;PATCH&lt;/code&gt; com "adicione 10 ao valor" teriam resultados diferentes se executadas duas vezes).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exemplo:&lt;/strong&gt; &lt;code&gt;PATCH /api/usuarios/123&lt;/code&gt; (atualiza apenas o e-mail do usuário 123)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Em ASP.NET Core:&lt;/strong&gt; &lt;code&gt;[HttpPatch]&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fie9v7jwfwlf3y8p8xvsr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fie9v7jwfwlf3y8p8xvsr.png" alt="Exemplo em ASP.NET Core" width="800" height="147"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Outros Métodos
&lt;/h3&gt;

&lt;p&gt;Existem outros verbos que você pode encontrar, embora sejam menos comuns no desenvolvimento de APIs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HEAD:&lt;/strong&gt; Idêntico ao &lt;code&gt;GET&lt;/code&gt;, mas o servidor retorna apenas os cabeçalhos, sem o corpo da resposta. Útil para verificar metadados (como o &lt;code&gt;Content-Length&lt;/code&gt; de um arquivo grande) sem baixá-lo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OPTIONS:&lt;/strong&gt; Descreve as opções de comunicação para o recurso alvo. É muito usado nos bastidores pelo mecanismo de &lt;strong&gt;CORS&lt;/strong&gt; do navegador.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Códigos de Status HTTP
&lt;/h2&gt;

&lt;p&gt;Após o servidor processar uma requisição, ele envia de volta um &lt;strong&gt;Código de Status (Status Code)&lt;/strong&gt;. Esse número de três dígitos é a forma mais rápida e clara que uma API tem para dizer ao cliente o resultado da operação: "Deu tudo certo", "Você cometeu um erro" ou "Eu cometi um erro".&lt;/p&gt;

&lt;p&gt;Dominar esses códigos é essencial para construir APIs previsíveis e fáceis de depurar. Eles são agrupados em cinco classes:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Informativa (100 - 199)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Raras no dia a dia do desenvolvimento de APIs REST. Indicam que a requisição foi recebida e o processo continua.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;100 - Continue:&lt;/strong&gt; Indica que o cliente pode continuar a requisição ou ignorar a resposta caso a requisição já tenha terminado;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;101 - Switching Protocols&lt;/strong&gt;: É usado para responder um header de solicitação de atualização do cliente e indica o protocolo para qual o servidor esta alternando.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Sucesso (200 -299)
&lt;/h3&gt;

&lt;p&gt;A classe que todos gostamos de ver. Indica que a requisição foi recebida, entendida e aceita com sucesso.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;200 - Ok:&lt;/strong&gt; Indica um sucesso genérico, o resultado depende do do método HTTP. Por exemplo, quando retornamos este código em uma requisição &lt;code&gt;GET&lt;/code&gt; significa que o recurso foi recuperado e transmitido no corpo da mensagem.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Em ASP.NET Core:&lt;/strong&gt; &lt;code&gt;return Ok(meuRecurso);&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;201 - Created:&lt;/strong&gt; A requisição foi um sucesso e um novo recurso foi criado. Normalmente retornado em uma requisição &lt;code&gt;POST&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Em ASP.NET Core:&lt;/strong&gt; &lt;code&gt;return CreatedAtAction(nameof(GetRecursoPorId), new { id = novoRecurso.Id }, novoRecurso);&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;202 - Accepted:&lt;/strong&gt; A requisição foi recebida mas ainda não foi atendida. Normalmente utilizada quando o servidor esta processando outra solicitação, ou para vários processamentos ao mesmo tempo.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Em ASP.NET Core:&lt;/strong&gt; &lt;code&gt;return Accepted();&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;204 - No Content:&lt;/strong&gt; A requisição foi um sucesso, mas não possui conteúdo a retornar. Muito utilizado em um requisição &lt;code&gt;DELETE&lt;/code&gt; ou &lt;code&gt;PUT/PATCH&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Em ASP.NET Core:&lt;/strong&gt; &lt;code&gt;return NoContent();&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Redirecionamento (300 - 399)
&lt;/h3&gt;

&lt;p&gt;Indica que o cliente precisa tomar uma ação adicional para completar a requisição, geralmente acessando uma nova URL.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;301 - Moved Permanently:&lt;/strong&gt; Utilizado quando a URL do recurso foi alterada permanentemente. A nova URL é passada na resposta.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;302 - Found:&lt;/strong&gt; Utilizado quando a URI foi alterada temporariamente.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Erro do Cliente (400 - 499)
&lt;/h3&gt;

&lt;p&gt;A culpa é do cliente. A requisição tem algo errado: sintaxe inválida, falta de autenticação, etc. Esta é a classe mais importante para validação de dados em APIs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;400 - Bad Request:&lt;/strong&gt; O servidor não conseguiu ou não vai processar a requisição por conta de um erro na requisição. Por exemplo, uma requisição malformada, erro de sintaxe, etc.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Em ASP.NET Core:&lt;/strong&gt; &lt;code&gt;return BadRequest("O campo 'nome' é obrigatório.");&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;401 - Unauthorized:&lt;/strong&gt; Embora o padrão HTTP especifique "não autorizado", semanticamente essa resposta significa "não autenticado". Ou seja, o cliente precisa se autenticar para obter a resposta solicitada.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;403 - Forbidden:&lt;/strong&gt; Agora sim, o cliente está autenticado (logado), mas ele &lt;strong&gt;não tem permissão&lt;/strong&gt; para acessar aquele recurso específico. É uma questão de autorização, não de autenticação.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;404 - Not Found:&lt;/strong&gt; O servidor não conseguiu achar o recurso solicitado. Em um navegador, significa que a URL não foi reconhecida. Em uma API, também pode significar que o endpoint é válido mas o recurso solicitado não existe.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Em ASP.NET Core:&lt;/strong&gt; &lt;code&gt;return NotFound();&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;429 - Too Many Requests:&lt;/strong&gt; O cliente fez muitas requisições em um curto periodo de tempo e foi limitado.&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Erro do Servidor (500 - 599)
&lt;/h3&gt;

&lt;p&gt;A culpa é nossa (do servidor). Algo deu errado do nosso lado e não conseguimos atender a uma requisição aparentemente válida.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;500 - Internal Server Error:&lt;/strong&gt; O erro genérico. Em 99% dos casos em ASP.NET Core, isso significa que &lt;strong&gt;ocorreu uma exceção não tratada&lt;/strong&gt; no seu código.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;503 - Service Unavailable:&lt;/strong&gt; O servidor não esta pronto para atender a requisição. Comumente utilizado quando servidor esta sobrecarregado ou em manutenção.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Consumindo e Criando Endpoints em ASP.NET Core
&lt;/h2&gt;

&lt;p&gt;Até agora, vimos a teoria: a estrutura das mensagens, os verbos e os códigos de status. Agora, vamos ver como tudo isso funciona em .NET.&lt;/p&gt;

&lt;p&gt;Nesta seção, vamos construir duas peças:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Um Servidor:&lt;/strong&gt; Uma API RESTful simples com ASP.NET Core para gerenciar uma lista de produtos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Um Cliente:&lt;/strong&gt; Uma aplicação de Console em C# que consome essa API usando &lt;code&gt;HttpClient&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Para ambos os projetos, usaremos a seguinte classe de modelo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F64nsvllkbqa1qupjs5e2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F64nsvllkbqa1qupjs5e2.png" alt="Classe Produto" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  O Servidor em API ASP.NET Core
&lt;/h3&gt;

&lt;p&gt;Vamos criar um &lt;code&gt;Controller&lt;/code&gt; que expõe endpoints para listar e criar produtos. Em um projeto real, você usaria um banco de dados, mas para manter o foco no HTTP, usaremos uma lista estática em memória&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjfuxml6m728e6ij6kl0a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjfuxml6m728e6ij6kl0a.png" alt="Exemplo em ASP.NET Core" width="800" height="993"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O que este Controller faz?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;[HttpGet]&lt;/code&gt;&lt;/strong&gt;: Responde a requisições &lt;code&gt;GET /api/products&lt;/code&gt; retornando a lista completa de produtos e um status &lt;code&gt;200 OK&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;[HttpGet("{id}")]&lt;/code&gt;&lt;/strong&gt;: Responde a &lt;code&gt;GET /api/products/1&lt;/code&gt;, por exemplo. Ele busca o produto e retorna &lt;code&gt;200 OK&lt;/code&gt; se o encontrar, ou &lt;code&gt;404 Not Found&lt;/code&gt; se não encontrar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;[HttpPost]&lt;/code&gt;&lt;/strong&gt;: Responde a &lt;code&gt;POST /api/products&lt;/code&gt;. Ele recebe os dados de um novo produto do corpo (Body) da requisição, adiciona-o à lista e retorna um &lt;code&gt;201 Created&lt;/code&gt;, usando &lt;code&gt;CreatedAtAction&lt;/code&gt; para gerar a URL correta do novo produto no header &lt;code&gt;Location&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  O Cliente com &lt;code&gt;HttpClient&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Agora, vamos criar uma aplicação de Console que irá chamar nossa API. Para isso, usaremos a classe &lt;code&gt;HttpClient&lt;/code&gt;, a principal ferramenta do .NET para fazer requisições HTTP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Program.cs&lt;/code&gt; de um projeto Console&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ey2ukz1r3qtrl2p2kul.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ey2ukz1r3qtrl2p2kul.png" alt="Exemplo em ASP.NET Core" width="800" height="1286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O que este Cliente faz?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;GetAllProductsAsync&lt;/code&gt;&lt;/strong&gt;: Monta e envia uma requisição &lt;code&gt;GET&lt;/code&gt;. Ele usa &lt;code&gt;EnsureSuccessStatusCode()&lt;/code&gt; para verificar se a resposta foi um sucesso (qualquer código &lt;code&gt;2xx&lt;/code&gt;) e depois usa &lt;code&gt;ReadFromJsonAsync&lt;/code&gt; para converter o JSON da resposta diretamente em uma lista de objetos &lt;code&gt;Product&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;CreateProductAsync&lt;/code&gt;&lt;/strong&gt;: Usa &lt;code&gt;PostAsJsonAsync&lt;/code&gt; para serializar um objeto &lt;code&gt;Product&lt;/code&gt; para JSON e enviá-lo no corpo de uma requisição &lt;code&gt;POST&lt;/code&gt;. Após a chamada, ele verifica se o status foi &lt;code&gt;201 Created&lt;/code&gt; e extrai o header &lt;code&gt;Location&lt;/code&gt; para confirmar que a API retornou a URL do novo recurso, fechando o ciclo que iniciamos com &lt;code&gt;CreatedAtAction&lt;/code&gt; no servidor.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  HTTP/1.1 a HTTP/3
&lt;/h2&gt;

&lt;p&gt;O HTTP não é uma tecnologia estática. À medida que a web evoluiu de simples páginas de texto para aplicações complexas e interativas, o protocolo precisou se adaptar para entregar mais conteúdo, mais rápido e de forma mais eficiente.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTP/1.1
&lt;/h3&gt;

&lt;p&gt;Por quase duas décadas, o HTTP/1.1 foi a espinha dorsal da web. Ele trouxe melhorias cruciais sobre seu antecessor, como o &lt;strong&gt;reaproveitamento de conexões&lt;/strong&gt; (&lt;code&gt;Keep-Alive&lt;/code&gt;), que evitou o custo de abrir uma nova conexão TCP para cada recurso, e o header &lt;code&gt;Host&lt;/code&gt;, que permitiu a hospedagem de múltiplos sites no mesmo IP.&lt;/p&gt;

&lt;p&gt;No entanto, o HTTP/1.1 sofria de um problema fundamental de design: o &lt;strong&gt;Head-of-Line (HOL) Blocking&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analogia para o HOL Blocking:&lt;/strong&gt; Imagine um caixa de supermercado (uma conexão TCP). Você tem vários itens para passar (CSS, JS, imagens). O HTTP/1.1 funciona como uma única fila: você precisa esperar o item da frente ser processado para passar o próximo. Se o primeiro item for grande e demorado (uma imagem pesada), todos os outros itens pequenos (ícones, arquivos de estilo) ficam travados na fila, esperando.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTP/2
&lt;/h3&gt;

&lt;p&gt;O HTTP/2 foi projetado especificamente para resolver o HOL Blocking no nível da aplicação. Sua principal inovação foi a &lt;strong&gt;Multiplexação&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Com a Multiplexação&lt;/strong&gt;, voltando à nossa analogia, é como se o mesmo caixa de supermercado pudesse processar vários itens de clientes diferentes ao mesmo tempo, de forma intercalada, na mesma conexão. Uma imagem grande pode começar a ser processada, e enquanto isso, um arquivo CSS e um JS podem ser processados em paralelo sem esperar.&lt;/p&gt;

&lt;p&gt;Outras melhorias importantes do HTTP/2 incluem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server Push:&lt;/strong&gt; Uma correção importante aqui. Não se trata de enviar atualizações quando dados mudam. Na verdade, é a capacidade do servidor de &lt;strong&gt;antecipar&lt;/strong&gt; as necessidades do cliente. Ao pedir uma página HTML, o servidor já "empurra" o CSS e o JS que ele sabe que serão necessários, sem esperar o navegador pedi-los. É como o caixa te entregar as pilhas junto com o controle remoto, porque ele sabe que você vai precisar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compressão de Cabeçalhos (HPACK):&lt;/strong&gt; Reduz o tamanho dos metadados enviados em cada requisição, economizando banda.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  HTTP/3
&lt;/h3&gt;

&lt;p&gt;O HTTP/2 resolveu o HOL Blocking na aplicação, mas o problema ainda existia na camada de transporte (TCP). Se um único pacote TCP (um pedaço da nossa comunicação) se perdesse na rede, toda a conexão TCP parava para esperar a recuperação daquele pacote, bloqueando todos os fluxos multiplexados do HTTP/2.&lt;/p&gt;

&lt;p&gt;A solução do HTTP/3 foi radical: abandonar o TCP e usar um novo protocolo de transporte chamado &lt;strong&gt;QUIC&lt;/strong&gt;, que roda sobre &lt;strong&gt;UDP&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As principais vantagens são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Eliminação do HOL Blocking do TCP:&lt;/strong&gt; Como o QUIC gerencia seus próprios fluxos de forma independente, a perda de um pacote em um fluxo (ex: o de uma imagem) não bloqueia os outros (ex: o do CSS).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conexão mais rápida:&lt;/strong&gt; O processo de estabelecimento de conexão (handshake) é muito mais rápido que o do TCP com TLS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migração de Conexão (Connection ID):&lt;/strong&gt; O HTTP/3 identifica a conexão por um "Connection ID", e não pelo par IP:Porta. Isso significa que se você sair do Wi-Fi e entrar no 4G, seu celular muda de IP, mas a conexão HTTP/3 continua ativa sem interrupções. É uma virada de jogo para a internet móvel.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Segurança com HTTPS
&lt;/h2&gt;

&lt;p&gt;Até agora, vimos como o HTTP funciona. Mas, por padrão, ele transmite todos os dados em texto puro, o que é um enorme risco de segurança. Qualquer um que intercepte a comunicação pode ler tudo.&lt;/p&gt;

&lt;p&gt;Para resolver isso, temos o &lt;strong&gt;HTTPS (Hypertext Transfer Protocol Secure)&lt;/strong&gt;. Ele não é um protocolo novo; é o mesmo HTTP que já conhecemos, mas com uma camada de segurança adicional fornecida pelo protocolo &lt;strong&gt;TLS (Transport Layer Security)&lt;/strong&gt;, o sucessor do antigo SSL.&lt;/p&gt;

&lt;p&gt;O TLS oferece três garantias fundamentais, os pilares da comunicação segura na web:&lt;/p&gt;

&lt;h3&gt;
  
  
  Pilar 1: Criptografia (Confidencialidade)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;O que é?&lt;/strong&gt; Garante que os dados trocados entre o cliente e o servidor sejam ilegíveis para qualquer um.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Como funciona?&lt;/strong&gt; Através da criptografia. Imagine que você quer enviar os dados do seu cartão de crédito. Sem criptografia, seria como enviar um cartão postal: qualquer um no caminho pode ler. Com a criptografia, é como colocar o cartão postal dentro de um cofre que só o destinatário tem a chave para abrir. Mesmo que alguém intercepte o cofre, verá apenas metal, não o conteúdo. Essa "mágica" é feita com um par de chaves (pública e privada) durante o aperto de mão inicial (handshake) para estabelecer uma conexão segura, e então com chaves simétricas mais rápidas para a troca de dados em si.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pilar 2: Autenticidade
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;O que é?&lt;/strong&gt; Garante que você está realmente se comunicando com o servidor que você espera (ex: &lt;code&gt;google.com&lt;/code&gt;), e não com um impostor se passando por ele.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Como funciona?&lt;/strong&gt; Através dos &lt;strong&gt;Certificados Digitais (SSL/TLS Certificates)&lt;/strong&gt;. O certificado é um "documento de identidade" digital para o servidor, emitido por uma Autoridade Certificadora (AC) confiável (como Let's Encrypt ou GoDaddy). Seu navegador já vem com uma lista de ACs em que ele confia.&lt;/p&gt;

&lt;p&gt;Quando você acessa um site, o servidor apresenta esse certificado. Seu navegador verifica se:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;O certificado foi emitido para o domínio que você está acessando.&lt;/li&gt;
&lt;li&gt;O certificado não expirou.&lt;/li&gt;
&lt;li&gt;Ele foi assinado por uma AC que o seu navegador confia.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Se tudo estiver correto, o navegador exibe o cadeado de segurança. Se não, ele exibe um aviso severo de que a conexão não é privada.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pilar 3: Integridade
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;O que é?&lt;/strong&gt; Assegura que os dados não foram modificados no meio do caminho.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Como funciona?&lt;/strong&gt; Cada mensagem trocada inclui um "código de autenticação de mensagem" (MAC), que funciona como um selo de segurança. Esse código é gerado com base no conteúdo da mensagem e uma chave secreta que só o cliente e o servidor conhecem. Se um invasor alterar um único bit da mensagem, o MAC não corresponderá mais ao conteúdo, e a alteração será detectada imediatamente.&lt;/p&gt;

&lt;h3&gt;
  
  
  SSL vs. TLS
&lt;/h3&gt;

&lt;p&gt;Você ouvirá os termos SSL e TLS usados quase como sinônimos, mas eles não são.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSL (Secure Sockets Layer):&lt;/strong&gt; Foi o protocolo original criado pela Netscape. Todas as suas versões (SSL 1.0, 2.0, 3.0) são hoje consideradas inseguras e obsoletas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TLS (Transport Layer Security):&lt;/strong&gt; É o sucessor oficial e moderno do SSL, mantido pela IETF. Estamos atualmente em versões como TLS 1.2 e 1.3.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;A regra é simples: use sempre TLS.&lt;/strong&gt; Embora as pessoas ainda falem em "certificado SSL", o protocolo que ele usa para garantir a segurança é, na verdade, o TLS.&lt;/p&gt;




&lt;h2&gt;
  
  
  Por que Dominar o HTTP é Crucial?
&lt;/h2&gt;

&lt;p&gt;Ao longo deste artigo, fizemos uma viagem profunda pela espinha dorsal da web e das APIs. Desmontamos o HTTP, peça por peça, não como um acrônimo abstrato, mas como a linguagem viva que permite que nossos sistemas conversem. Vimos a estrutura de suas mensagens, a gramática de seus verbos e códigos de status, sua evolução em busca de performance com o HTTP/2 e HTTP/3, e a armadura indispensável de segurança que o HTTPS fornece.&lt;/p&gt;

&lt;p&gt;E aqui, respondemos à pergunta central: por que um desenvolvedor deve se importar tanto com isso?&lt;/p&gt;

&lt;p&gt;Porque o HTTP transcendeu os navegadores. Hoje, ele é o alicerce para praticamente toda a arquitetura de software moderna: de APIs RESTful que conectam seus microserviços, passando por aplicações mobile que consomem dados da nuvem, até dispositivos de IoT que enviam status para um servidor. Entender HTTP profundamente é a diferença entre apenas usar um framework como o ASP.NET Core e saber de verdade o que acontece sob o capô. É o que permite a você depurar problemas de forma mais inteligente, otimizar a performance de suas requisições e construir APIs que são não apenas funcionais, mas também seguras, eficientes e previsíveis.&lt;/p&gt;

&lt;p&gt;É claro que, embora o HTTP seja o protagonista no palco da web, ele faz parte de um ecossistema mais amplo de protocolos, cada um com um propósito especializado:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FTP (File Transfer Protocol):&lt;/strong&gt; Como o nome sugere, é otimizado para a transferência de arquivos entre cliente e servidor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SMTP (Simple Mail Transfer Protocol):&lt;/strong&gt; É o protocolo padrão para o envio de e-mails pela internet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSH (Secure Shell):&lt;/strong&gt; Usado para administrar e executar comandos em servidores remotos de forma segura.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modelos como o P2P (Peer-to-Peer):&lt;/strong&gt; Oferecem uma arquitetura descentralizada onde os participantes se comunicam diretamente, em contraste com o modelo cliente-servidor centralizado do HTTP.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reconhecer esses outros protocolos nos dá perspectiva. Mostra que, para cada tipo de problema de comunicação, existe uma ferramenta projetada para resolvê-lo da melhor forma.&lt;/p&gt;

&lt;p&gt;No entanto, para você, desenvolvedor que constrói o futuro em serviços e aplicações conectadas, o HTTP continuará sendo seu principal campo de atuação. Dominá-lo não é apenas um diferencial; é a base sólida sobre a qual sistemas resilientes e de alta performance são construídos. Ele é o fluxo invisível, mas vital, que dá vida às aplicações que você cria todos os dias.&lt;/p&gt;




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

&lt;h3&gt;
  
  
  Documentação Essencial
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MDN Web Docs sobre HTTP:&lt;/strong&gt; O melhor e mais completo portal para desenvolvedores web entenderem todos os aspectos do HTTP, de conceitos básicos a listas de headers e códigos de status.

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Overview" rel="noopener noreferrer"&gt;MDN - Uma visão geral do HTTP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Cloudflare Learning Center:&lt;/strong&gt; Explicações claras e acessíveis sobre conceitos de rede e segurança, incluindo a diferença entre SSL e TLS.

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.cloudflare.com/pt-br/learning/ssl/what-is-ssl/" rel="noopener noreferrer"&gt;Cloudflare - O que é SSL?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Para Desenvolvedores .NET
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Microsoft Docs: Criar Web APIs com ASP.NET Core:&lt;/strong&gt; O tutorial oficial da Microsoft para começar a construir APIs RESTful, como a que vimos no nosso exemplo prático.

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/pt-br/aspnet/core/tutorials/first-web-api" rel="noopener noreferrer"&gt;Tutorial: Criar uma API Web com o ASP.NET Core&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Microsoft Docs: Fazer requisições HTTP com &lt;code&gt;HttpClient&lt;/code&gt;:&lt;/strong&gt; A documentação oficial sobre a classe &lt;code&gt;HttpClient&lt;/code&gt;, com exemplos e melhores práticas (como o uso de &lt;code&gt;IHttpClientFactory&lt;/code&gt;).

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/pt-br/dotnet/csharp/tutorials/console-webapiclient" rel="noopener noreferrer"&gt;Fazer solicitações HTTP usando a classe HttpClient&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Artigos e Guias de Aprofundamento
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Curso Alura - HTTP: entendendo a web por baixo dos panos:&lt;/strong&gt; Um curso em português que oferece uma base sólida sobre o protocolo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DevMedia - HTTP Headers:&lt;/strong&gt; Um guia prático sobre os principais cabeçalhos HTTP.

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.devmedia.com.br/http-headers/41219" rel="noopener noreferrer"&gt;Artigo DevMedia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Leitura Avançada
&lt;/h3&gt;

&lt;p&gt;Para os que desejam ir direto à fonte, as &lt;strong&gt;RFCs (Request for Comments)&lt;/strong&gt; são os documentos que padronizam o protocolo na internet. A leitura é densa e técnica, mas é a especificação definitiva.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc7231" rel="noopener noreferrer"&gt;RFC 7231 - HTTP/1.1: Semantics and Content&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://httpwg.org/specs/rfc9113.html" rel="noopener noreferrer"&gt;RFC 9113 - HTTP/2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://httpwg.org/specs/rfc9114.html" rel="noopener noreferrer"&gt;RFC 9114 - HTTP/3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>http</category>
      <category>webdev</category>
      <category>learning</category>
      <category>aspdotnet</category>
    </item>
    <item>
      <title>Um Guia para Gerenciar Segredos no .NET e Azure DevOps</title>
      <dc:creator>Gabriel Amarantes</dc:creator>
      <pubDate>Thu, 19 Jun 2025 15:15:10 +0000</pubDate>
      <link>https://dev.to/amarantess/um-guia-para-gerenciar-segredos-no-net-e-azure-devops-5a5n</link>
      <guid>https://dev.to/amarantess/um-guia-para-gerenciar-segredos-no-net-e-azure-devops-5a5n</guid>
      <description>&lt;p&gt;No mundo do desenvolvimento de software, uma das jornadas mais comuns é levar um projeto da nossa máquina local para o mundo, seja através de um repositório público no GitHub ou por meio de um pipeline de implantação contínua (CI/CD) no Azure DevOps. No entanto, precisamos ter uma atenção especial quando se trata de segurança.&lt;br&gt;
Este artigo nasce de uma experiência real e de um desafio que enfrentei recentemente: &lt;strong&gt;Como gerenciar um projeto .NET que usa chaves de API secretas, mantendo um repositório público limpo e, ao mesmo tempo, garantindo que o build automatizado no Azure DevOps funcione perfeitamente?&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Uma Chave Secreta no Lugar Errado
&lt;/h2&gt;

&lt;p&gt;Minha jornada começou com um projeto de estudos e meu primeiro contato com o Azure. Decidi utilizar o &lt;strong&gt;Service Bus&lt;/strong&gt; para implementar uma funcionalidade de exclusão de usuários de forma assíncrona, via mensageria.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pense no Microsoft Azure Service Bus como um carteiro digital superconfiável. É um mediador de mensagens na nuvem que serve para desacoplar aplicações, permitindo que elas troquem dados de forma segura e assíncrona. Ele utiliza filas (para comunicação um-para-um, seguindo o padrão FIFO - "primeiro a entrar, primeiro a sair") e tópicos (para comunicação um-para-muitos).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Para conectar minha aplicação a uma fila do Service Bus, o Azure me forneceu uma &lt;strong&gt;connection string&lt;/strong&gt; — uma chave de acesso vital para o funcionamento do serviço. A solução mais óbvia? Colocá-la diretamente no arquivo de configuração &lt;code&gt;appsettings.json&lt;/code&gt;.&lt;br&gt;
E foi aí que o dilema surgiu: como manter meu repositório público no GitHub sem expor essa chave?&lt;br&gt;
A primeira ideia que pode vir à mente é a "solução manual": deixar a chave no arquivo &lt;code&gt;appsettings.json&lt;/code&gt; durante o desenvolvimento e removê-la antes de cada &lt;code&gt;commit&lt;/code&gt;. Mas essa abordagem é uma receita para o desastre. Em um trabalho de equipe (ou mesmo sozinho, num dia de pressa), é quase certo que alguém esquecerá de remover o segredo. Uma vez vazado, teríamos que invalidar e regenerar todas as chaves expostas, sem contar que o segredo antigo permaneceria para sempre visível no histórico de commits.&lt;br&gt;
É para evitar essa armadilha que o ecossistema .NET nos oferece uma solução segura: o &lt;strong&gt;User Secrets&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Nunca Comite Segredos
&lt;/h2&gt;

&lt;p&gt;O ponto de partida para qualquer projeto profissional é um princípio inegociável: &lt;strong&gt;nunca, jamais, armazene segredos diretamente no código-fonte.&lt;/strong&gt;&lt;br&gt;
Segredos incluem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chaves de API&lt;/li&gt;
&lt;li&gt;Connection Strings de bancos de dados ou serviços (como o Azure Service Bus)&lt;/li&gt;
&lt;li&gt;Senhas&lt;/li&gt;
&lt;li&gt;Tokens de autenticação&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Quando um segredo é "comitado" no Git, ele fica registrado no histórico do repositório para sempre. Mesmo que você o remova em um commit futuro, qualquer pessoa com acesso ao histórico pode encontrá-lo. Em um repositório público, isso é o mesmo que entregar as chaves do seu sistema para qualquer um.&lt;br&gt;
A solução não é criar lógicas complexas para enviar códigos diferentes para repositórios diferentes, mas sim &lt;strong&gt;externalizar a configuração&lt;/strong&gt;, ou seja, separar o código da configuração sensível.&lt;/p&gt;


&lt;h2&gt;
  
  
  A Segurança Local com User Secrets
&lt;/h2&gt;

&lt;p&gt;Para resolver o problema localmente, precisamos entender como o .NET gerencia as configurações. O sistema é baseado em uma hierarquia de "provedores" que alimentam uma interface central, a &lt;code&gt;IConfiguration&lt;/code&gt;.&lt;br&gt;
Imagine que sua aplicação precisa de uma configuração. Ela pergunta à &lt;code&gt;IConfiguration&lt;/code&gt;: "Qual é o valor para &lt;code&gt;Settings:ServiceBus:DeleteUserAccount&lt;/code&gt;?". A &lt;code&gt;IConfiguration&lt;/code&gt;, por sua vez, consulta seus provedores em uma ordem específica:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Arquivos &lt;code&gt;appsettings.json&lt;/code&gt;&lt;/strong&gt;: Primeiro, ela olha o &lt;code&gt;appsettings.json&lt;/code&gt; e depois o &lt;code&gt;appsettings.Development.json&lt;/code&gt; (que o sobrepõe).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Secrets&lt;/strong&gt;: Em seguida, ela consulta os segredos do usuário.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Variáveis de Ambiente&lt;/strong&gt;: Depois, verifica se existe uma variável de ambiente com esse nome.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linha de Comando&lt;/strong&gt;: Por fim, olha os argumentos de linha de comando.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A regra é simples: &lt;strong&gt;o último provedor a ser lido, vence.&lt;/strong&gt; Se o User Secrets tiver um valor para a chave, ele irá sobrepor o que estiver no &lt;code&gt;appsettings.Development.json&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Setup Inicial
&lt;/h3&gt;

&lt;p&gt;Com base nessa hierarquia, podemos usar o &lt;code&gt;appsettings.Development.json&lt;/code&gt; como um "molde" para as configurações que a aplicação precisa, mas deixando os valores sensíveis em branco.&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Em&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;appsettings.Development.json&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;span class="nl"&gt;"Settings"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="nl"&gt;"ServiceBus"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="nl"&gt;"DeleteUserAccount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Valor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;deixado&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;em&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;branco&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;de&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;propósito&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;span class="p"&gt;}&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;h3&gt;
  
  
  Movendo o Segredo para o User Secrets.
&lt;/h3&gt;

&lt;p&gt;A ferramenta User Secrets não criptografa os segredos, apenas os armazena em um arquivo &lt;code&gt;secrets.json&lt;/code&gt;, localizado fora da pasta do seu projeto (geralmente no diretório de perfil do sistema operacional). Isso torna impossível que ele seja enviado acidentalmente para o Git.&lt;br&gt;
&lt;strong&gt;Passo 1: Habilitar o User Secrets&lt;/strong&gt;&lt;br&gt;
No terminal, na raiz do seu projeto, execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet user-secrets init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse comando adiciona uma tag &lt;code&gt;&amp;lt;UserSecretsId&amp;gt;&lt;/code&gt; ao seu arquivo &lt;code&gt;.csproj&lt;/code&gt;. É esse ID único que conecta seu projeto ao arquivo &lt;code&gt;secrets.json&lt;/code&gt; correspondente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passo 2: Armazenar o Segredo&lt;/strong&gt;&lt;br&gt;
Agora, vamos definir o valor da nossa connection string. Usamos dois-pontos (&lt;code&gt;:&lt;/code&gt;) para navegar na hierarquia do JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet user-secrets &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="s2"&gt;"Settings:ServiceBus:DeleteUserAccount"&lt;/span&gt; &lt;span class="s2"&gt;"SuaConnectionStringSuperSecretaAqui"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E pronto! Quando você rodar sua aplicação em modo de desenvolvimento, o .NET irá ler o valor vazio do &lt;code&gt;appsettings.Development.json&lt;/code&gt; e, em seguida, o sobreporá com o valor real guardado no User Secrets. Problema local resolvido de forma segura e elegante.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Testando a Portabilidade&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;E se outro desenvolvedor baixar o projeto? Ao fazer &lt;code&gt;git pull&lt;/code&gt; em uma nova máquina, todo o código virá, incluindo o &lt;code&gt;.csproj&lt;/code&gt; com o &lt;code&gt;UserSecretsId&lt;/code&gt;. No entanto, o arquivo &lt;code&gt;secrets.json&lt;/code&gt; &lt;strong&gt;não virá&lt;/strong&gt;, pois ele é local ao primeiro computador.&lt;br&gt;
Ao tentar rodar o projeto, ele falhará por não encontrar a chave. Este é um &lt;strong&gt;comportamento esperado e desejado&lt;/strong&gt;, pois prova que o sistema é seguro. A solução é simples: cada desenvolvedor, em cada nova máquina, precisa configurar o segredo localmente apenas uma vez, executando o comando &lt;code&gt;dotnet user-secrets set...&lt;/code&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Automatizando com Segurança no Azure DevOps
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzboni4jqdu94ie77x4if.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzboni4jqdu94ie77x4if.png" alt="Logo do Azure Devops" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
Com o desenvolvimento local resolvido, é hora de automatizar o processo de build e teste com um pipeline de CI/CD.&lt;/p&gt;
&lt;h3&gt;
  
  
  Conceitos Fundamentais de CI/CD
&lt;/h3&gt;

&lt;p&gt;Antes de criar o pipeline, vamos entender os blocos de construção do Azure DevOps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD (Integração/Implantação Contínua):&lt;/strong&gt; É a prática de automatizar as fases do desenvolvimento. A &lt;strong&gt;CI&lt;/strong&gt; garante que o novo código de vários desenvolvedores seja integrado e testado automaticamente. A &lt;strong&gt;CD&lt;/strong&gt; leva essa automação adiante, publicando o projeto em um ambiente (teste ou produção). O objetivo é entregar valor de forma mais rápida e confiável.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pipeline:&lt;/strong&gt; É o fluxo de trabalho que define todas as etapas da sua automação. Ele diz ao Azure DevOps o que fazer e em que ordem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent (Agente):&lt;/strong&gt; É a máquina (geralmente virtual e temporária, fornecida pela Microsoft) que executa os passos do seu pipeline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Job (Trabalho):&lt;/strong&gt; Um conjunto de passos que rodam juntos em um mesmo agente.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task (Tarefa):&lt;/strong&gt; A menor unidade de trabalho. É uma ação individual e pré-empacotada, como &lt;code&gt;dotnet build&lt;/code&gt;, &lt;code&gt;dotnet test&lt;/code&gt; ou a execução de um script.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Criando um Pipeline Simples com o Editor Clássico
&lt;/h3&gt;

&lt;p&gt;No Azure DevOps, você pode criar um pipeline usando um arquivo YAML (código) ou o Editor Clássico (interface gráfica). Para quem está começando, o Editor Clássico é uma ótima porta de entrada. O processo geralmente segue estes passos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Conexão:&lt;/strong&gt; Você aponta o pipeline para o seu repositório de código.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Template:&lt;/strong&gt; Você escolhe um template inicial. Para um projeto .NET, o template "ASP.NET Core" já adiciona as tarefas essenciais:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;dotnet restore&lt;/code&gt; (baixa as dependências)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dotnet build&lt;/code&gt; (compila o código)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dotnet test&lt;/code&gt; (executa os testes)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dotnet publish&lt;/code&gt; (prepara os arquivos para implantação)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execução:&lt;/strong&gt; Você salva e executa o pipeline, que rodará em um agente na nuvem.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;O Desafio e a Solução no Pipeline&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;É aqui que um novo problema surge. Ao executar o pipeline, ele falha com um erro genérico: &lt;code&gt;The process 'C:\Program Files\dotnet\dotnet.exe' failed with exit code 1&lt;/code&gt;.&lt;br&gt;
Após investigar os logs, a causa fica clara: &lt;strong&gt;os testes estão falhando&lt;/strong&gt;. Assim como a "nova máquina" do exemplo anterior, o agente de build do Azure DevOps é um ambiente limpo. Ele não tem acesso aos seus User Secrets. Ao executar os testes que dependem da connection string do Service Bus, o valor está vazio, causando a falha que interrompe todo o pipeline.&lt;br&gt;
A solução é fornecer o segredo de forma segura durante a execução.&lt;/p&gt;
&lt;h3&gt;
  
  
  Variáveis de Pipeline Seguras
&lt;/h3&gt;

&lt;p&gt;Primeiro, armazenamos o segredo de forma centralizada e segura no próprio pipeline.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;No modo de edição do pipeline, vá para a aba &lt;strong&gt;Variables&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Crie uma &lt;strong&gt;Pipeline Variable&lt;/strong&gt; com um nome claro, como &lt;code&gt;ServiceBusConnectionString&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Cole o valor da sua chave e, o mais importante, &lt;strong&gt;clique no ícone de cadeado&lt;/strong&gt; para marcar o valor como secreto. Ele será mascarado e não aparecerá nos logs.&lt;/li&gt;
&lt;li&gt;Salve as variáveis.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Injetando Segredos com PowerShell&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A solução universal e mais robusta é usar uma tarefa de &lt;strong&gt;PowerShell&lt;/strong&gt; para definir a variável de ambiente.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Adicione a Tarefa:&lt;/strong&gt; Na aba &lt;strong&gt;Tasks&lt;/strong&gt;, adicione uma nova tarefa "PowerShell" à sua lista.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Posicione Corretamente:&lt;/strong&gt; Arraste a tarefa PowerShell para que ela seja executada &lt;strong&gt;imediatamente antes&lt;/strong&gt; da sua tarefa de &lt;code&gt;dotnet test&lt;/code&gt;. A ordem é crucial.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Configure o Script:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clique na tarefa PowerShell e defina o &lt;strong&gt;Type&lt;/strong&gt; como &lt;code&gt;Inline&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;No campo &lt;strong&gt;Script&lt;/strong&gt;, insira o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Setting the Service Bus connection string as an environment variable."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"##vso[task.setvariable variable=Settings__ServiceBus__DeleteUserAccount]&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="n"&gt;ServiceBusConnectionString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;Este comando &lt;code&gt;##vso[task.setvariable...]&lt;/code&gt; é uma instrução especial para o agente do Azure DevOps, ordenando que ele crie uma variável de ambiente (&lt;code&gt;Settings__ServiceBus__DeleteUserAccount&lt;/code&gt;) com o valor da nossa variável de pipeline segura (&lt;code&gt;$(ServiceBusConnectionString)&lt;/code&gt;).&lt;br&gt;
A tarefa de teste, ao ser executada logo em seguida, herdará essa variável de ambiente. O sistema de configuração do .NET a detectará, seus testes encontrarão a chave necessária e o pipeline será executado com sucesso!&lt;/p&gt;




&lt;h2&gt;
  
  
  Azure Key Vault
&lt;/h2&gt;

&lt;p&gt;Embora as variáveis de pipeline sejam ótimas para CI/CD, ambientes de produção exigem uma camada extra de segurança e gerenciamento. Para isso, a ferramenta definitiva é o &lt;strong&gt;Azure Key Vault&lt;/strong&gt;.&lt;br&gt;
Pense no Key Vault como um cofre centralizado e ultra-seguro na nuvem. Em vez de armazenar segredos no pipeline, sua aplicação, ao ser executada em produção, se autentica de forma segura no Key Vault para buscar as configurações de que precisa. Isso oferece vantagens imensas, como gerenciamento centralizado de todos os segredos, políticas de acesso granulares, rotação automática de chaves e logs de auditoria detalhados.&lt;/p&gt;




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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Separe Código e Configuração:&lt;/strong&gt; O código deve ser o mesmo em todos os ambientes; a configuração sensível deve ser externa e específica de cada ambiente.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trate Cada Ambiente de Forma Independente:&lt;/strong&gt; O modo como você fornece um segredo para sua máquina local é diferente de como você o faz para um pipeline de CI ou para o ambiente de produção.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use a Ferramenta Certa para o Trabalho:&lt;/strong&gt; O ecossistema .NET e o Azure nos fornecem as ferramentas ideais para cada cenário: &lt;strong&gt;User Secrets&lt;/strong&gt; para desenvolvimento, &lt;strong&gt;Variáveis de Pipeline&lt;/strong&gt; para automação e &lt;strong&gt;Azure Key Vault&lt;/strong&gt; para produção.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ao seguir esses princípios, você garante que seu projeto não apenas funcione, mas que seja seguro. &lt;strong&gt;Para mim, essa jornada que começou com um simples &lt;code&gt;connection string&lt;/code&gt; foi um aprendizado imenso, e espero que compartilhá-la possa ajudar outros desenvolvedores a trilhar um caminho mais seguro.&lt;/strong&gt;&lt;br&gt;
Para referência, o código-fonte do projeto que inspirou este artigo pode ser encontrado &lt;a href="https://github.com/amarantess/ReservaRestaurante" rel="noopener noreferrer"&gt;neste link do GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>azure</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
