<?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: Ravikant Vijayvargiya</title>
    <description>The latest articles on DEV Community by Ravikant Vijayvargiya (@unbalanced-tree).</description>
    <link>https://dev.to/unbalanced-tree</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1834119%2F14766253-72ed-46d3-a494-3e9e6ee29044.jpeg</url>
      <title>DEV Community: Ravikant Vijayvargiya</title>
      <link>https://dev.to/unbalanced-tree</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/unbalanced-tree"/>
    <language>en</language>
    <item>
      <title>Deconstructing our microservices, Part 1: The app crashed in production and what we did next</title>
      <dc:creator>Ravikant Vijayvargiya</dc:creator>
      <pubDate>Thu, 11 Jun 2026 05:36:16 +0000</pubDate>
      <link>https://dev.to/unbalanced-tree/app-crashed-in-production-509i</link>
      <guid>https://dev.to/unbalanced-tree/app-crashed-in-production-509i</guid>
      <description>&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%2Fcdn-images-1.medium.com%2Fmax%2F4200%2F0%2AJpgoo0zhTS3Gb7gk" 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%2Fcdn-images-1.medium.com%2Fmax%2F4200%2F0%2AJpgoo0zhTS3Gb7gk" alt="[Wolf](https://unsplash.com/photos/black-and-brown-wolf-painting-tauPAnOIGvE)" width="760" height="830"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This API had been working fine in production for 2 years. The process was taking the expected time and resources, but boom. One day, one of our pods crashed.&lt;/p&gt;

&lt;p&gt;Self-healing mechanisms were already in place to handle the situation; the system automatically redeployed the pod instance as configured.&lt;/p&gt;

&lt;p&gt;But the question remains, Why?&lt;/p&gt;

&lt;p&gt;The API was tested, working flawlessly with real production data from the last 2 years. So many customers were using it. Resource allocation seemed adequate until now.&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%2Ftwf42281kantdmfsqgml.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%2Ftwf42281kantdmfsqgml.png" width="558" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So we checked the Application Insights on Azure for CPU, memory, and other resource usage. The pod crashed due to high memory usage. A customer had a very large file.&lt;/p&gt;

&lt;p&gt;Now, let’s learn what this API does. We were working on a web application that handles various types of financial calculations. This particular API reads a file and imports its data into the system. The import process includes reading data from a file, processing data for various validations, including checking for a valid file, verifying mathematical constraints, and performing calculations on it before saving. Formatting the data in the required system formats and creating hierarchies that have foreign key references in the database. Some hierarchies go as deep as 12 levels. It sent the real-time status of the process using SignalR. A file can be a single CSV file or a zip file that contains CSV files. Data will be stored across 30+ tables in the SQL Server database. We had 1 GB of memory for a pod. After we got hold of similar data, we tested it on staging, and it was taking 3–4 days in an idle instance. It was also very long. The large file had 1.5 million rows.&lt;/p&gt;

&lt;p&gt;Now we know the reason is high memory usage. What was the cause? Resources, code, database, or its query?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;A large file processing was taking up to 1 GB of memory. If any other process uses a good chunk of memory, it implies less memory for our import process. So this one process was taking the whole pod down with it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We were downloading the files into memory and reading data from them. The memory usage increased exponentially with the large files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We were saving hierarchical data to create one row at a time, so we could have the parent ID to create the hierarchy. It was not a big issue with general files, but that was not the case with this specific file.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With these analyses, we decided to make a few changes.&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%2Fj3hw0ojxjw5t0siv5p2e.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%2Fj3hw0ojxjw5t0siv5p2e.png" width="799" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Extracting the Import Microservice
&lt;/h2&gt;

&lt;p&gt;Let’s move the import process out of the calculation service, so if it goes sideways, the whole calculation pod does not go down with it. To manage n number of pods, used KEDA (Kubernetes Event-driven Autoscaling). A new pod was created for a new import request. After the process was completed, the pod would scale in. The calculation service was publishing events to the Azure Service Bus topic, and KEDA was autoscaling up to the max n( 5 in our case) pods. If there were more than n requests, these requests were held in a message queue. KEDA also gives us the advantage of parallel processing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blob Stream
&lt;/h2&gt;

&lt;p&gt;Instead of reading the data from a file/memory stream, read directly from the Azure Blob Storage using blob stream. This reduced the direct file content in the memory, thus improving performance. The pros of reading blob stream outweighed the cons of keeping a connection open to blob storage. The connection remained open for a very short duration, not for the whole process time, and we did not keep the file in the memory. Previously, we deleted the file after the end of the process. Now we were keeping the file data in data objects in code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Optimization
&lt;/h2&gt;

&lt;p&gt;We were saving the rows one by one because when the code was first written, we had limited exposure to the variety of the data we were going to have in the files. After 2 years of this process working, we had better business metadata to understand the scope better. We had three main hierarchy patterns to handle. In two cases, more than 99% of the data was in the last node of the hierarchy. And in the remaining one case, 99.5% of users never created a hierarchy. They were using only the top-most node. Now we were more comfortable using SQLBulkCopy to bulk save the data. We used a batch size to not overwhelm the database.&lt;/p&gt;

&lt;p&gt;Let me point out one more thing that we were already doing. We were not doing this whole import process in a transaction because a transaction on this long process can lead to a deadlock in the database. We were maintaining a flag to mark the status of the process. Only when the status shows success is the data shown in the UI. User was getting a real-time update of the process via SignalR. If the process failed for any reason, we deleted the dirty data.&lt;/p&gt;

&lt;p&gt;As you may guess, we also made other changes to accommodate our KEDA pattern. The import process logic was idempotent, so the server can safely process the same message twice without corrupting the SQL Server data&lt;/p&gt;

&lt;h2&gt;
  
  
  Post Optimization
&lt;/h2&gt;

&lt;p&gt;Now our process was optimized. What took 3 to 4 days is now done in 3–4 hours. But one new issue arose with it, due to the now faster process, the client was flooded with SignalR. The UI froze. It was receiving more data than it could process and display. We were showing every single row status to the user, so we chose to display updates after every few thousand rows. Real-time to near real-time update.&lt;/p&gt;

&lt;p&gt;Production crashes are painful, but they are also the best architectural forcing functions. Looking back, our 2-year-old API didn’t fail because it was poorly written; it failed because it hit a scaling wall. By re-architecting the solution, we learned a few invaluable lessons:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Isolate the Blast Radius:&lt;/strong&gt; Never let a heavy background process share a fate with your core user-facing services. Use event-driven scaling (like KEDA) to let heavy lifters crash in peace without taking down the ship.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stream, Don’t Swallow:&lt;/strong&gt; When dealing with unpredictable file sizes, avoid memory buffering. Keep your Large Object Heap (LOH) clean by streaming data directly from cloud storage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manage Backpressure:&lt;/strong&gt; True optimization doesn’t stop at the backend. If you make your data processing 10x faster, ensure your frontend delivery mechanisms (like SignalR) are throttled to handle the flood.&lt;/p&gt;

&lt;p&gt;Have you ever had a seemingly stable API suddenly blow up after years in production? How did your team handle the scaling bottleneck? Let’s talk about it in the comments below!&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>dotnet</category>
      <category>distributedsystems</category>
      <category>microservices</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Ravikant Vijayvargiya</dc:creator>
      <pubDate>Fri, 31 Oct 2025 07:00:41 +0000</pubDate>
      <link>https://dev.to/unbalanced-tree/-31da</link>
      <guid>https://dev.to/unbalanced-tree/-31da</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/unbalanced-tree/microservices-service-to-service-to-invocation-with-dapr-docker-compose-and-net-4a7h" class="crayons-story__hidden-navigation-link"&gt;Microservices: Service-to-service invocation with Dapr, docker-compose, and .NET&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="/unbalanced-tree" 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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1834119%2F14766253-72ed-46d3-a494-3e9e6ee29044.jpeg" alt="unbalanced-tree profile" class="crayons-avatar__image" width="460" height="460"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/unbalanced-tree" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Ravikant Vijayvargiya
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Ravikant Vijayvargiya
                
              
              &lt;div id="story-author-preview-content-1979995" 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="/unbalanced-tree" 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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1834119%2F14766253-72ed-46d3-a494-3e9e6ee29044.jpeg" class="crayons-avatar__image" alt="" width="460" height="460"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Ravikant Vijayvargiya&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/unbalanced-tree/microservices-service-to-service-to-invocation-with-dapr-docker-compose-and-net-4a7h" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 30 '24&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/unbalanced-tree/microservices-service-to-service-to-invocation-with-dapr-docker-compose-and-net-4a7h" id="article-link-1979995"&gt;
          Microservices: Service-to-service invocation with Dapr, docker-compose, and .NET
        &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/docker"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;docker&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/dapr"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;dapr&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/beginners"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;beginners&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/unbalanced-tree/microservices-service-to-service-to-invocation-with-dapr-docker-compose-and-net-4a7h" 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/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/unbalanced-tree/microservices-service-to-service-to-invocation-with-dapr-docker-compose-and-net-4a7h#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&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;
            7 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&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>docker</category>
      <category>dapr</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Discovering the Hidden Dependencies in Your DLLs</title>
      <dc:creator>Ravikant Vijayvargiya</dc:creator>
      <pubDate>Wed, 26 Feb 2025 10:14:21 +0000</pubDate>
      <link>https://dev.to/unbalanced-tree/dll-dependencies-c5l</link>
      <guid>https://dev.to/unbalanced-tree/dll-dependencies-c5l</guid>
      <description>&lt;p&gt;This cool application finds all the dependent DLLs of the provided DLL. &lt;/p&gt;

&lt;p&gt;GitHub Repo:- &lt;a href="https://github.com/lucasg/Dependencies" rel="noopener noreferrer"&gt;https://github.com/lucasg/Dependencies&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/lucasg/Dependencies/releases/download/v1.11.1/Dependencies_x64_Release.zip" rel="noopener noreferrer"&gt;Download from here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just unzip the folder, run &lt;strong&gt;DependenciesGui&lt;/strong&gt;, and upload the DLL file to see the results. &lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dll</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Cool website to edit PDF</title>
      <dc:creator>Ravikant Vijayvargiya</dc:creator>
      <pubDate>Sat, 25 Jan 2025 09:22:39 +0000</pubDate>
      <link>https://dev.to/unbalanced-tree/cool-website-to-edit-pdf-48d7</link>
      <guid>https://dev.to/unbalanced-tree/cool-website-to-edit-pdf-48d7</guid>
      <description>&lt;p&gt;&lt;a href="https://www.sejda.com/pdf-editor" rel="noopener noreferrer"&gt;https://www.sejda.com/pdf-editor&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Simple to use. You can easily add and remove content. &lt;/p&gt;

</description>
      <category>pdf</category>
    </item>
    <item>
      <title>LLM Visualization</title>
      <dc:creator>Ravikant Vijayvargiya</dc:creator>
      <pubDate>Thu, 16 Jan 2025 09:06:30 +0000</pubDate>
      <link>https://dev.to/unbalanced-tree/llm-visualization-maj</link>
      <guid>https://dev.to/unbalanced-tree/llm-visualization-maj</guid>
      <description>&lt;p&gt;LLM Visualization: A 3D animated visualization of an LLM with a walkthrough. &lt;/p&gt;

&lt;p&gt;This website demonstrates various LLM models, such as GPT-2(small), nano-GPT, and GPT -3.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bbycroft.net/llm" rel="noopener noreferrer"&gt;https://bbycroft.net/llm&lt;/a&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>chatgpt</category>
      <category>ai</category>
      <category>animation</category>
    </item>
    <item>
      <title>Remove Windows software completely</title>
      <dc:creator>Ravikant Vijayvargiya</dc:creator>
      <pubDate>Thu, 05 Dec 2024 06:25:19 +0000</pubDate>
      <link>https://dev.to/unbalanced-tree/remove-windows-software-completely-4k82</link>
      <guid>https://dev.to/unbalanced-tree/remove-windows-software-completely-4k82</guid>
      <description>&lt;p&gt;Windows uninstall/remove software feature is good but does not completely remove the software. For example, if you uninstall Chrome browser and install it again, you may find previous data.&lt;/p&gt;

&lt;p&gt;Sometimes we want to wipe out a software and its data completely. &lt;br&gt;
I find Revo Uninstaller very useful in this case. Its free version is sufficient for personal use. &lt;/p&gt;

&lt;p&gt;The best part is that it creates a Windows restore point, so there is no fear of losing any other data. &lt;/p&gt;

&lt;p&gt;Download link:- &lt;a href="https://www.revouninstaller.com/revo-uninstaller-free-download/" rel="noopener noreferrer"&gt;https://www.revouninstaller.com/revo-uninstaller-free-download/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tooling</category>
      <category>os</category>
    </item>
    <item>
      <title>Unit testing with xUnit: Introduction</title>
      <dc:creator>Ravikant Vijayvargiya</dc:creator>
      <pubDate>Sun, 08 Sep 2024 11:59:30 +0000</pubDate>
      <link>https://dev.to/unbalanced-tree/unit-testing-with-xunit-introduction-3npl</link>
      <guid>https://dev.to/unbalanced-tree/unit-testing-with-xunit-introduction-3npl</guid>
      <description>&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%2Fcdn-images-1.medium.com%2Fmax%2F3914%2F0%2AXMOcmCHUhRMQWTWo.jpg" 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%2Fcdn-images-1.medium.com%2Fmax%2F3914%2F0%2AXMOcmCHUhRMQWTWo.jpg" alt="[Source](https://www.reddit.com/r/wolves/comments/yitg4a/wolves_can_loaf_too/)" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Wolf Fact: &lt;a href="https://x.com/saveourwolves23/status/1830957787943444862" rel="noopener noreferrer"&gt;That's how a pack of wolves sound&lt;/a&gt;
&lt;/h4&gt;




&lt;p&gt;&lt;a href="https://xunit.net/" rel="noopener noreferrer"&gt;Xunit.net&lt;/a&gt; is a free, open-source, community-focused unit testing tool for the .NET Framework.&lt;/p&gt;

&lt;p&gt;Let’s go. &lt;a href="https://github.com/Unbalanced-Tree/CSharp/tree/main/XUnitTesting" rel="noopener noreferrer"&gt;Please visit this link for the code.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a .NET console app ( for simplicity) and add an xUnit test project to the solution. Now, we have two projects in the solution — one for application logic and another for unit testing.&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%2Fef4616aqwawnq34cv5v1.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%2Fef4616aqwawnq34cv5v1.png" alt="xUnit Test Project" width="800" height="135"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;xUnit Test Project&lt;/small&gt;&lt;/center&gt;
&lt;br&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%2Fcyew4dpru07wnojc6ub7.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%2Fcyew4dpru07wnojc6ub7.png" alt="Solution XUnitTesting hierarchy" width="541" height="335"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Solution XUnitTesting hierarchy&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;blockquote&gt;
&lt;p&gt;We should always keep the application code and its tests in separate projects.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Application- This project has our application logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Application.Test- As the name indicates, this project has test cases for the application code.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wrote a simple method to divide two numbers in Logics class.&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%2Foyt0k970o61qr6t4uqgl.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%2Foyt0k970o61qr6t4uqgl.png" alt="Logics.Divide" width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The access modifier for the method must be public. The xUnit checks all methods in all public exported classes in the assembly.&lt;/p&gt;

&lt;p&gt;Now we will test this method. We will write unit tests for this method in the UnitTests class.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Don’t forget to add the Application project reference to the Application.Test project.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Fact-
&lt;/h4&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%2F5vssgnyljq0eqmc6hb4k.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%2F5vssgnyljq0eqmc6hb4k.png" alt="UnitTests.cs TestDivide()" width="800" height="303"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;UnitTests.cs TestDivide()&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;[Fact]&lt;/strong&gt;: Marks a test method&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Assert&lt;/strong&gt;: The assert class contains various static methods. These methods are utilized to evaluate the testing conditions. Example:- Assert.Equal(expected value, actual value), Assert.True(boolean condition)and many more. You can check all assert statements here.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We pass parameter values for the method and then compare the actual and expected values. In the TestDivide() method, we pass parameters as 4 and 2 for the numerator and denominator respectively.&lt;/p&gt;

&lt;p&gt;We can run tests using Test Explorer.&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%2Ffvgxnrb2b9jcxnnw1lwl.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%2Ffvgxnrb2b9jcxnnw1lwl.png" alt="Test Explorer" width="654" height="358"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Test Explorer&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;or&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%2F1hdnvhvzgb8sf08w5jnf.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%2F1hdnvhvzgb8sf08w5jnf.png" alt="Green Dot" width="800" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our test case passed for the numerator 4 and denominator 2. It would fail for numerator 1 and denominator 3.&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%2Fwlxh7bn1mzehjjzfciby.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%2Fwlxh7bn1mzehjjzfciby.png" alt="TestDivide2" width="799" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need to improve this test’s coverage. We should specify the precision in the assert statement.&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%2Fes7wc7i2n3v2osqo4ehr.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%2Fes7wc7i2n3v2osqo4ehr.png" alt="Assert.Equal(expected, actual, precision)" width="642" height="180"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Assert.Equal(expected, actual, precision)&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;&lt;strong&gt;Precision&lt;/strong&gt;: Verify up to digits after the decimal&lt;/p&gt;

&lt;p&gt;There is a drawback to writing test cases like this. We have to create different test methods for various inputs.&lt;/p&gt;

&lt;h4&gt;
  
  
  Theory-
&lt;/h4&gt;

&lt;p&gt;xUnit theory overcomes the above drawback.&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%2Fvoexluah0j4o9im25ns5.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%2Fvoexluah0j4o9im25ns5.png" alt="TestDivideMultipleInputs" width="800" height="211"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;TestDivideMultipleInputs&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;[Theory]&lt;/strong&gt;: Marks a test method as being a data theory. A theory is a test case with multiple intakes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;[InlineData]&lt;/strong&gt;: To provide data for theory.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For an InlineData row, the test method executes one time. So the method TestDivideMultipleInputs will be executed three times. We can provide input parameters and desired output for the divide method using InlineData.&lt;/p&gt;

&lt;h4&gt;
  
  
  Exception-
&lt;/h4&gt;

&lt;p&gt;This testing tool does not address exceptions with the general assert statements. It uses &lt;em&gt;Assert.Throws&lt;/em&gt;. It validates that the exact exception is thrown and not a derived exception type.&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%2Fw0lrwd31518rgj6xltrt.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%2Fw0lrwd31518rgj6xltrt.png" alt="TestDivideByZero()" width="800" height="175"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;TestDivideByZero()&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;For a zero denominator, the code will throw a DivideByZeroException. The TestDivideByZero() test method validates it. You may try different types of exceptions to verify.&lt;/p&gt;

&lt;p&gt;Any feedback would be greatly appreciated. Thank you.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>unittest</category>
      <category>xunit</category>
    </item>
    <item>
      <title>Roadmap to becoming an ASP.NET Core developer</title>
      <dc:creator>Ravikant Vijayvargiya</dc:creator>
      <pubDate>Fri, 06 Sep 2024 13:57:00 +0000</pubDate>
      <link>https://dev.to/unbalanced-tree/roadmap-to-becoming-an-aspnet-core-developer-8d</link>
      <guid>https://dev.to/unbalanced-tree/roadmap-to-becoming-an-aspnet-core-developer-8d</guid>
      <description>&lt;p&gt;I found this cool roadmap to becoming an ASP.NET Core developer by Moien Tajik.&lt;/p&gt;

&lt;p&gt;You can find the road map &lt;a href="https://github.com/MoienTajik/AspNetCore-Developer-Roadmap/blob/master/aspnetcore-developer-roadmap.png" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Hopefully, He will maintain this repo but I am still adding my fork in case... &lt;a href="https://github.com/Unbalanced-Tree/AspNetCore-Developer-Roadmap/blob/master/aspnetcore-developer-roadmap.png" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Moien Tajik &lt;a href="https://www.linkedin.com/in/moientajik/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What do you think about this roadmap? &lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>backend</category>
    </item>
    <item>
      <title>All AI engines in one place</title>
      <dc:creator>Ravikant Vijayvargiya</dc:creator>
      <pubDate>Thu, 05 Sep 2024 12:05:00 +0000</pubDate>
      <link>https://dev.to/unbalanced-tree/search-engine-youcom-418n</link>
      <guid>https://dev.to/unbalanced-tree/search-engine-youcom-418n</guid>
      <description>&lt;p&gt;&lt;a href="https://you.com/" rel="noopener noreferrer"&gt;https://you.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You.com is an innovative search engine.&lt;/p&gt;

&lt;p&gt;You.com supports a variety of advanced AI models, allowing users to choose from different options for their conversational and task-oriented needs. Here are some of the key models available:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;OpenAI's GPT Models: You.com includes access to OpenAI's GPT-4 and GPT-4 Turbo models, which are known for their high performance in natural language understanding and generation tasks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anthropic's Claude Models: This includes Claude Instant, Claude 2, Claude 3 Opus, Claude 3 Sonnet, and Claude 3 Haiku. These models are designed to provide conversational capabilities and are tailored for various applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Google's Gemini Pro: This model is part of Google's AI offerings and is designed to enhance conversational AI experiences.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Zephyr: An uncensored model that provides a different approach to AI interactions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You.com allows users to toggle between these models using a Custom Model Selector, enabling a flexible and tailored experience based on user preferences and specific tasks.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: The content of this post has been generated using You.com&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>chatgpt</category>
      <category>llm</category>
      <category>google</category>
    </item>
    <item>
      <title>Brave Browser: with built-in Ad-blocker</title>
      <dc:creator>Ravikant Vijayvargiya</dc:creator>
      <pubDate>Wed, 04 Sep 2024 13:31:00 +0000</pubDate>
      <link>https://dev.to/unbalanced-tree/brave-browser-43b5</link>
      <guid>https://dev.to/unbalanced-tree/brave-browser-43b5</guid>
      <description>&lt;p&gt;&lt;a href="https://brave.com/download/" rel="noopener noreferrer"&gt;Brave Browser&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Privacy and Ad-Blocker
&lt;/h4&gt;

&lt;p&gt;Brave browser has an inbuilt Ad-Blocker so we don't need any extension. It's like YouTube Premium without YouTube Premium, for music and videos. &lt;/p&gt;

&lt;p&gt;It also has a Brave shield that can be used for advanced controls like blocking fingerprints and blocking third-party cookies. &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%2Feuw80rswz9vogpgji72s.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%2Feuw80rswz9vogpgji72s.png" alt="Brave shield" width="526" height="740"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Brave shows trackers and ads blocked on a site, like 10 in the above image. &lt;/p&gt;

&lt;p&gt;It also displays the total number of trackers blocked till now. &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%2Fwf15d4j0forltih2gvqr.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%2Fwf15d4j0forltih2gvqr.png" alt="Total trackers" width="798" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Background Image
&lt;/h4&gt;

&lt;p&gt;Brave has beautiful background images created/captured by various contributors. It makes the browser less boring. &lt;/p&gt;




&lt;p&gt;Brave has some awesome features in its mobile version. &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%2Fscbnpqb1ryefdmmnwbgc.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%2Fscbnpqb1ryefdmmnwbgc.png" alt="Settings -&gt; Media " width="800" height="1433"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Settings -&amp;gt; Media&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;h4&gt;
  
  
  Background Play
&lt;/h4&gt;

&lt;p&gt;We can play videos on a Mobile device even when we are not using the Brave browser or our phone screen is off. &lt;/p&gt;

&lt;h4&gt;
  
  
  Block YouTube shorts
&lt;/h4&gt;

&lt;p&gt;It disables the Shorts feature on YouTube. &lt;/p&gt;

</description>
      <category>browser</category>
      <category>privacy</category>
      <category>music</category>
      <category>youtube</category>
    </item>
    <item>
      <title>In-Memory Database with SQLite</title>
      <dc:creator>Ravikant Vijayvargiya</dc:creator>
      <pubDate>Sun, 01 Sep 2024 07:19:08 +0000</pubDate>
      <link>https://dev.to/unbalanced-tree/in-memory-database-with-sqlite-4en5</link>
      <guid>https://dev.to/unbalanced-tree/in-memory-database-with-sqlite-4en5</guid>
      <description>&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%2Fb06awkuaqq75p0mmi7zm.jpeg" 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%2Fb06awkuaqq75p0mmi7zm.jpeg" alt="sleeping wolf" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Wolf Fact: With 200M+ olfactory cells housed in the nose, a wolf’s sense of smell is their most acute. By smell alone, wolves can locate prey, family members, or enemies. They can also tell if other wolves are nearby if they're male/female, etc.
&lt;/h4&gt;




&lt;p&gt;&lt;strong&gt;&lt;em&gt;Prerequisites: C#, Visual Studio, basic concepts of database, Web API&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What is SQLite? How to install SQLite? How to create a database with it? Why do we need an in-memory DB? And how create it with SQLite?&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://www.sqlite.org/index.html" rel="noopener noreferrer"&gt;&lt;strong&gt;SQLite:&lt;/strong&gt;&lt;/a&gt; SQLite is a C-language library that provides a SQL database engine that is small, fast, self-contained, high-reliability, and full-featured. SQLite database files are commonly used as containers to transfer rich content between systems and as a long-term archival format for data. SQLite uses dynamic types for tables. It means you can store any value in any column, regardless of the data type.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install:&lt;/strong&gt; You can install SQLite from &lt;a href="https://www.sqlite.org/download.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;. I am using Windows, so I used SQLite-tools-win32-x86–3380300.&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%2Fqdqtnfncaz34wnwiz622.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%2Fqdqtnfncaz34wnwiz622.png" alt="For Windows" width="800" height="160"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;For Windows&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;You should choose one based on your OS. You should see the following three files after extracting this zip.&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%2F2va8tsjs4sj2tvtfunom.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%2F2va8tsjs4sj2tvtfunom.png" alt="SQLite Files" width="797" height="105"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create a database:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open command prompt(cmd)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;To create a new database&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sqlite3 DBName.db&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To see a list of the existing databases&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.databases&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&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%2Ffwfkfy4xvtuifmouvb3a.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%2Ffwfkfy4xvtuifmouvb3a.png" alt="A database with the name localDB.db" width="800" height="294"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;A database with the name localDB.db&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;&lt;a href="https://www.intel.com/content/www/us/en/analytics/in-memory-database.html" rel="noopener noreferrer"&gt;&lt;strong&gt;What is an In-Memory Database:&lt;/strong&gt;&lt;/a&gt; The data in a traditional database is stored on disk. When the data is needed, it’s called into the local system memory — or RAM — and then is processed by the CPU. Because it takes time to search for data that resides on disks, bottlenecks frequently occur.&lt;/p&gt;

&lt;p&gt;In contrast, &lt;em&gt;an in-memory database stores data directly in system memory&lt;/em&gt;, plugging directly into the high-speed, low-latency memory bus. It decreases data latency by reducing the time needed to analyze data. With an in-memory database, data is accessed much quicker, allowing you to analyze large volumes of complex data in real time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When should you use it?&lt;/strong&gt; An In-memory database uses RAM for storage, resulting in faster read-write operations. You should consider an in-memory database if&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The target system has data to manage, but no persistent media.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The performance requirement simply cannot be met with a persistent database&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are a few common examples in which an in-memory database can be useful.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Caching:&lt;/em&gt; You can increase performance by using a small in-memory database( can lose data) with a large disk-based database( reliable).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Batch Write:&lt;/em&gt; You can perform a batch of read-write operations on the in-memory database. You can back up this database to a physical database after a predetermined period( like 10 mins) or a predeﬁned number of operations( like 5000 queries), as needed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let’s write some code.&lt;/p&gt;

&lt;p&gt;We have created a physical database “localDB.db”. Now we need to add a table to this. We can do this using a query or manually using the UI. I am using DB Browser for SQLite to perform operations on the database. &lt;em&gt;DB Browser for SQLite&lt;/em&gt; (DB4S) is a high-quality, visual, &lt;strong&gt;&lt;em&gt;open-source&lt;/em&gt;&lt;/strong&gt; tool to create, design, and edit database files compatible with SQLite. You can download it from &lt;a href="https://sqlitebrowser.org/dl/" rel="noopener noreferrer"&gt;here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After installing DB Browser, We should add the “localDB.db” file to this.&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%2Felvuwjgo8byo8ib7u29p.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%2Felvuwjgo8byo8ib7u29p.png" alt="To add db file" width="512" height="197"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;To add db file&lt;/small&gt;&lt;/center&gt;
&lt;br&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%2Fs2qwfftpik0uavggi96r.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%2Fs2qwfftpik0uavggi96r.png" alt="To access existing DB" width="500" height="179"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;To access existing DB&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;Now let’s create a new table in the localDB.&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%2Fhgfu3gh8j26d74idowdd.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%2Fhgfu3gh8j26d74idowdd.png" alt="Create Table TableOne(Id INT, Value Text)" width="800" height="477"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Create Table TableOne(Id INT, Value Text)&lt;/small&gt;&lt;/center&gt;
&lt;br&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%2Fji6a2tk0bxdo6z24ce2j.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%2Fji6a2tk0bxdo6z24ce2j.png" alt="Table Schema" width="800" height="353"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Table Schema&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;&lt;strong&gt;In-memory database with SQLite:&lt;/strong&gt; We will create an in-memory database in three main steps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Duplicate physical database to in-memory: Copy physical DB schema( like tables ) to in-memory.&lt;/li&gt;
&lt;li&gt;Operations on the in-memory database: Read-write operation on the in-memory database.&lt;/li&gt;
&lt;li&gt;Back up the in-memory DB to the physical DB: Update the real database with the current state of the in-memory database. It is quite quick.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;The complete source code can be found&lt;/em&gt; &lt;a href="https://github.com/Unbalanced-Tree/CSharp/tree/main/InMemoryDb" rel="noopener noreferrer"&gt;&lt;em&gt;here.&lt;/em&gt;&lt;/a&gt; Let’s get started now.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a Web API.&lt;/li&gt;
&lt;/ul&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%2Fyaqx09n5mfb6o5zjtayv.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%2Fyaqx09n5mfb6o5zjtayv.png" alt="A simple Web API" width="798" height="133"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;A simple Web API&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;ul&gt;
&lt;li&gt;Add Nuget package to it.&lt;/li&gt;
&lt;/ul&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%2F64csr3musja8p3jar2oc.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%2F64csr3musja8p3jar2oc.png" alt="Microsoft.Data.Sqlite" width="800" height="125"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Microsoft.Data.Sqlite&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;ul&gt;
&lt;li&gt;Solution File Structure( I tried to keep things as simple as possible.)&lt;/li&gt;
&lt;/ul&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%2F6l1ihuzk9fqhxwagpfhn.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%2F6l1ihuzk9fqhxwagpfhn.png" alt="File Structure" width="442" height="545"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;File Structure&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;I mainly created three files. Let’s go over them one by one.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;IDbHelpers:&lt;/em&gt; This interface contains method declarations for acquiring physical and in-memory DB connections.&lt;/li&gt;
&lt;/ul&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%2Fypoqxiyan3vjrmm4wgko.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%2Fypoqxiyan3vjrmm4wgko.png" alt="IDbHelpers" width="800" height="380"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;IDbHelpers&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;DbHelpers:&lt;/em&gt; This class contains implementations for GetPhysicalDbConnection and GetInMemoryDbConnection methods.&lt;/li&gt;
&lt;/ul&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%2Fcvfk7r08s9mtkb2zc3ie.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%2Fcvfk7r08s9mtkb2zc3ie.png" alt="DbHelpers" width="800" height="532"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;DbHelpers&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;-&amp;gt; &lt;em&gt;dbFilePath:&lt;/em&gt; Path to “localDB.db” file&lt;/p&gt;

&lt;p&gt;-&amp;gt; &lt;em&gt;GetPhysicalDbConnection():&lt;/em&gt; I set the Data Source to dbfilePath with read-write permissions.&lt;/p&gt;

&lt;p&gt;-&amp;gt; &lt;em&gt;GetInMemoryDbConnection():&lt;/em&gt; I set the Data Source to &lt;strong&gt;&lt;em&gt;:memory:&lt;/em&gt;&lt;/strong&gt; for in-memory database.&lt;/p&gt;

&lt;p&gt;Don’t forget to open the DB connection.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;HomeController:&lt;/em&gt; The addRow API endpoint is available in HomeController. I’ll insert a row into TableOne using an in-memory database connection.&lt;/li&gt;
&lt;/ul&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%2F744oyh2otzmgaucda1b8.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%2F744oyh2otzmgaucda1b8.png" alt="Add Row method" width="800" height="425"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;I am using SqlCommand in this example. You may use other methods like dapper. If necessary, you can additionally add a transaction to this connection.&lt;/p&gt;

&lt;p&gt;Now let’s test it.&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%2Fq9b3sll7vne6lqc1hskq.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%2Fq9b3sll7vne6lqc1hskq.png" alt="Swagger" width="800" height="417"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Swagger&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;and DB status&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%2Fmmu67vd2kwjesunkiw94.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%2Fmmu67vd2kwjesunkiw94.png" alt="TableOne Data" width="800" height="439"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;TableOne Data&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;We can see data has been successfully inserted and backed up into the physical database.&lt;/p&gt;

&lt;p&gt;Friendly Suggestion: If you face an error during code execution that the Database is locked. Try closing the DB Browser.&lt;/p&gt;

&lt;p&gt;Any comments or suggestions would be greatly appreciated.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>sqlite</category>
      <category>dotnet</category>
      <category>database</category>
    </item>
    <item>
      <title>Microservices: Pub/Sub with Dapr, docker-compose, and .NET</title>
      <dc:creator>Ravikant Vijayvargiya</dc:creator>
      <pubDate>Fri, 30 Aug 2024 16:19:09 +0000</pubDate>
      <link>https://dev.to/unbalanced-tree/microservices-pubsub-with-dapr-docker-compose-and-net-18nf</link>
      <guid>https://dev.to/unbalanced-tree/microservices-pubsub-with-dapr-docker-compose-and-net-18nf</guid>
      <description>&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%2Fxi0pghxbeb6b0lzncobz.jpeg" 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%2Fxi0pghxbeb6b0lzncobz.jpeg" alt="One more wolf" width="800" height="614"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Wolf Fact: Wolves and domestic dogs share about 99.8% of their DNA, making them closely related.
&lt;/h4&gt;




&lt;p&gt;&lt;strong&gt;Prerequisites: C#, basic of Web API, Visual Studio, Docker Desktop&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Publish and Subscribe Pattern:-&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;It defines brokers, publishers, and subscribers, and how they should interact to create a loosely coupled scalable system. The publisher forwards the content/messages to the broker. And the subscribers get these messages from the broker.&lt;/p&gt;

&lt;p&gt;The Pub/Sub pattern can be implemented in a variety of ways. Ex.- The broker may push messages to subscribers or subscribers may have to read messages from the broker. Like this, every step’s process depends on implementation.&lt;/p&gt;

&lt;p&gt;The broker determines the type of content that a subscriber will receive. The broker uses message filtering techniques for this. There are two mainstream methods.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Topic-based&lt;/em&gt;:&lt;/strong&gt; It is a name for logical channels. A subscriber will receive all the messages published to a topic based on their subscription. The &lt;em&gt;publisher is responsible&lt;/em&gt; for defining the topics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Content-based:&lt;/em&gt;&lt;/strong&gt;  In this case, the subscriber classifies what type of content it will receive. So Subscriber is responsible for defining the constraints.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Pub/Sub pattern makes the application more scalable because publishers are not directly bound to subscribers and the broker deals with message delivery. So publishers don’t have to make any changes for a large number of subscribers. That’s the job of the broker.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://docs.dapr.io/developing-applications/building-blocks/pubsub/pubsub-overview/" rel="noopener noreferrer"&gt;Pub/Sub with Dapr&lt;/a&gt;:-
&lt;/h3&gt;

&lt;p&gt;Dapr supports pub/sub pattern. In Dapr implementation:-&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Publisher:&lt;/em&gt;&lt;/strong&gt; It writes messages to an input channel and sends them to a topic, unaware of which application will receive them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Subscriber:&lt;/em&gt;&lt;/strong&gt; It subscribes to the topic and receives messages from an output channel, unaware of which service produced these messages.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An intermediary message broker copies each message from a publisher’s input channel to an output channel for all subscribers interested in that message. Dapr provides *a content-based routing *pattern( filtering technique).&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%2Fprhf2lducyjbevon03rx.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%2Fprhf2lducyjbevon03rx.png" alt="Dapr Pub/Sub" width="800" height="284"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Dapr Pub/Sub&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;h3&gt;
  
  
  The pub/sub API in Dapr:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Provides a platform-agnostic API to send and receive messages. Ex. Windows, Linux …&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Offers at-least-once message delivery guarantee. Dapr considers a message successfully delivered once the subscriber processes the message and responds with a non-error response.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integrates with various message brokers and queuing systems. Ex. Apache Kafka, AWS, Azure Service Bus, Redis streams, and many more. You can check the complete list &lt;a href="https://docs.dapr.io/reference/components-reference/supported-pubsub/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Default Values:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Message Routing:&lt;/em&gt;&lt;/strong&gt; For message routing, Dapr uses the header value Content-Type as &lt;code&gt;datacontenttype&lt;/code&gt;. Any message sent by an application to a topic using Dapr is automatically wrapped in a Cloud Events envelope.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Message Content:&lt;/em&gt;&lt;/strong&gt; For message content, Dapr uses the header value Content-Type as &lt;code&gt;text/plain&lt;/code&gt;.The developer can change the content type for the message based on requirements.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dapr applications can subscribe to published topics via two methods that support the same features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Declarative: Subscription is defined in an &lt;strong&gt;external file&lt;/strong&gt;( YAML file).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;programmatic. Subscription is defined in the &lt;strong&gt;user code&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  So how does dapr pub/sub work?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The Dapr sidecar of the subscriber service calls the &lt;code&gt;/dapr/subscribe&lt;/code&gt; endpoint.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Dapr sidecar of the subscriber creates the requested subscriptions on the message broker.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The publisher sends a message at the &lt;code&gt;/v1.0/publish/&amp;lt;pub-sub-name&amp;gt;/&amp;lt;topic&amp;gt;&lt;/code&gt; endpoint on the Dapr publisher’s sidecar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The publisher sidecar publishes the message to the message broker.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The message broker sends a copy of the message to the subscriber’s sidecar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The subscriber’s sidecar calls the corresponding endpoint on the subscriber service then the subscriber returns an HTTP response.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;HTTP Response Code&lt;/strong&gt;&lt;br&gt;
 &lt;strong&gt;204&lt;/strong&gt; Message delivered&lt;br&gt;
 &lt;strong&gt;403&lt;/strong&gt; Message forbidden by access controls&lt;br&gt;
 &lt;strong&gt;404&lt;/strong&gt; No pubsub name or topic given&lt;br&gt;
 &lt;strong&gt;500&lt;/strong&gt; Delivery failed&lt;br&gt;
 &lt;strong&gt;200&lt;/strong&gt; Success&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now Let’s write some code. I will continue with the code that I wrote in the previous article. &lt;a href="https://github.com/Unbalanced-Tree/CSharp/tree/main/Microservices" rel="noopener noreferrer"&gt;The complete source code can be found here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am using the programmatic subscription approach, the subscription will be defined in the code. My Project ServiceOne will behave as a Publisher and ServiceTwo as a subscriber. I will use the Redis Stream component for the broker.&lt;/p&gt;

&lt;p&gt;In both services, NuGet packages Dapr.Client and Dapr.AspNetCore is required.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Startup.cs:-&lt;/strong&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%2Fnrz19nk981dz0b259d1h.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%2Fnrz19nk981dz0b259d1h.png" alt="ServiceOne Startup.cs ( Publisher)" width="708" height="211"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;ServiceOne Startup.cs ( Publisher)&lt;/small&gt;&lt;/center&gt;
&lt;br&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%2Ftp39eq9cu9gdcwvpwn7l.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%2Ftp39eq9cu9gdcwvpwn7l.png" alt="ServiceTwo Startup.cs ( Subscriber)" width="700" height="210"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;ServiceTwo Startup.cs ( Subscriber)&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;Add these methods to respective services.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;UseCloudEvents(): Dapr uses Cloud event 1.0 for message routing( sending messages to topics and receiving responses from subscribers). So we need this method in both startups.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MapSubscribeHandler(): Map the endpoint that will respond to requests /dapr/subscribe from the Dapr runtime. So needs only in subscription service.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: If your service is behaving as both subscriber and publisher then you need to add both these methods to the startup.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. ServiceOne IDaprClientHelper and DaprClientHelper:-
&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%2Fag8zqy0kl0j2pioo6r4p.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%2Fag8zqy0kl0j2pioo6r4p.png" alt="ServiceOne IDaprClientHelper" width="800" height="200"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;ServiceOne IDaprClientHelper&lt;/small&gt;&lt;/center&gt;
&lt;br&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%2Fjltftf7uszx4nzkmfb08.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%2Fjltftf7uszx4nzkmfb08.png" alt="ServiceOne DaprClientHelper" width="799" height="201"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;ServiceOne DaprClientHelper&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;This method is only required in ServiceOne (Publisher). PublishToTopicWithDaprClient method has so many concepts. Let’s understand them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.1. topicName:&lt;/strong&gt; The name of the topic. It is a user-defined name.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.2.&lt;/strong&gt; &lt;strong&gt;data:&lt;/strong&gt; Data that needs to be published on the topic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.3.&lt;/strong&gt; &lt;strong&gt;daprClient:&lt;/strong&gt; The Dapr client package allows interaction with other Dapr applications from a .NET application. The daprClient is an instance of DaprClientBuilder that would be used to call other dapr services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.4. PublishEventAsync:&lt;/strong&gt; Publish an event to the specified topic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.5 pubsubname:&lt;/strong&gt; It is the name of the pubsub component. This will be used by subscribers to subscribe to a topic. We will see it in the ServiceTwo controller.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. ServiceOne IServiceTwoHelper and ServiceTwoHelper:-
&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%2Fgkl9x5j3y29j8irqas0n.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%2Fgkl9x5j3y29j8irqas0n.png" alt="IServiceTwoHelper" width="795" height="296"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;IServiceTwoHelper&lt;/small&gt;&lt;/center&gt;
&lt;br&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%2Fxoot4jps1csd4agx22h4.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%2Fxoot4jps1csd4agx22h4.png" alt="ServiceTwoHelper" width="799" height="75"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;ServiceTwoHelper&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;PublishMessageTopic calls PublishToTopicWithDaprClient method. In this step, serviceOne( + sidecar) will write a message on the specified topic.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;pubsubname:&lt;/strong&gt; pubsub&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;topicName:&lt;/strong&gt; publishmessage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;data:&lt;/strong&gt; Notice that data is passed as an object but not as a primitive data type.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. HomeController:-
&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%2Fncldei36q9upho9gxpmk.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%2Fncldei36q9upho9gxpmk.png" alt="ServiceOne Controller Method PublishMessage" width="799" height="289"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;ServiceOne Controller Method PublishMessage&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;This controller method is used to publish the message to the topic.&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%2Fim2wov61wxec8kxp2zre.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%2Fim2wov61wxec8kxp2zre.png" alt="ServiceTwo Controller Method PublishedMessage" width="798" height="165"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;ServiceTwo Controller Method PublishMessage&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;This controller method will receive the message from the broker/topic. Notice the header. The topic has two parameters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First:- pubsubname. Which is pubsub.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Second:- topicName. Which is &lt;code&gt;publishmessage&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both are the same as &lt;code&gt;PublishToTopicWithDaprClient&lt;/code&gt; parameters.&lt;/p&gt;

&lt;p&gt;Now let’s update the docker-compose file. I am using Redis streams. So I have added the below-mentioned lines to docker-compose.&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%2F6doh9xo2wv9ud1jxij8s.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%2F6doh9xo2wv9ud1jxij8s.png" alt="Docker-compose.yaml" width="444" height="139"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Docker-compose.yaml&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;It defines that we need a service Redis on host port 6379 with any available hostname( I chose redisstate, you may choose based on your preference).&lt;/p&gt;

&lt;p&gt;Hey, we have written a programmatic subscription for pubsub. Okk.&lt;/p&gt;

&lt;p&gt;Also added Redis service to docker-compose file. Okk.&lt;/p&gt;

&lt;p&gt;But how will our services know they need to use this Redis stream? hmmm.&lt;/p&gt;

&lt;p&gt;Now let’s do this…&lt;/p&gt;

&lt;p&gt;Do you remember the declaration of the component in the docker-compose sidecar?&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%2Fxpwdxms9q205w2rve6qv.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%2Fxpwdxms9q205w2rve6qv.png" alt="DC SS" width="717" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This folder is used to define the components that can be used. We are going to use redis stream component.&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%2Fobjp3xcg60ig0qv566vm.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%2Fobjp3xcg60ig0qv566vm.png" alt="Folder structure" width="800" height="135"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Folder structure&lt;/small&gt;&lt;/center&gt;
&lt;br&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%2Fds34rmjwnb8x2lcgtx46.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%2Fds34rmjwnb8x2lcgtx46.png" alt="Components Folder" width="799" height="83"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Components Folder&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;blockquote&gt;
&lt;p&gt;Dapr keeps a YAML file in the components folder to identify the components that need to be used.&lt;/p&gt;
&lt;/blockquote&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%2Fsqdo5gp95yqboebsshbl.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%2Fsqdo5gp95yqboebsshbl.png" alt="pubsub.yaml" width="528" height="249"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;pubsub.yaml&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;This file defines that we are using a Redis component at port 6379. I am using dapr.io apiVersion V1 alpha1. The hostname and port number are the same as the docker-compose file.&lt;/p&gt;

&lt;p&gt;Now the coding part is done. So let’s run the code.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; docker compose build

&amp;gt;&amp;gt;&amp;gt; docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With these two commands, our services will be up and running.&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%2F93ghtn2z9r8l2f209vqg.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%2F93ghtn2z9r8l2f209vqg.png" alt="Call to Service One PublishMessage" width="800" height="342"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Call to Service One PublishMessage&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;It shows status code 200, Success. You can check the console of ServiceTwo to confirm that the message is published correctly( Because I have written it on the console in the ServiceTwo controller).&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%2F9ra8x8jbrm9ocopp4x14.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%2F9ra8x8jbrm9ocopp4x14.png" alt="Docker Desktop (Two services, their sidecars, and Redis service is running)" width="800" height="314"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Docker Desktop (Two services, their sidecars, and Redis service is running)&lt;/small&gt;&lt;/center&gt;
&lt;br&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%2F4lgn3voaygt0r6ryzvoq.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%2F4lgn3voaygt0r6ryzvoq.png" alt="Docker ServiceTwo Logs" width="799" height="373"&gt;&lt;/a&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Docker ServiceTwo Logs&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;Correctly Published.&lt;/p&gt;

&lt;p&gt;So that’s how we can perform Pub/Sub operation with Dapr, docker-compose, and .NET.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: &lt;a href="https://github.com/hungrywoolf/CSharp/tree/main/Microservices" rel="noopener noreferrer"&gt;You can check out the complete code here&lt;/a&gt;. The first commit has docker-compose configurations, and the service-to-service invocation code. The second commit has an extra pub-sub configuration and the pub/sub code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Any comments or suggestions would be greatly appreciated.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>pubsub</category>
      <category>microservices</category>
      <category>dapr</category>
    </item>
  </channel>
</rss>
