<?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>Forem: Ravikant Vijayvargiya</title>
    <description>The latest articles on Forem by Ravikant Vijayvargiya (@unbalanced-tree).</description>
    <link>https://forem.com/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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1834119%2F14766253-72ed-46d3-a494-3e9e6ee29044.jpeg</url>
      <title>Forem: Ravikant Vijayvargiya</title>
      <link>https://forem.com/unbalanced-tree</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/unbalanced-tree"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Ravikant Vijayvargiya</dc:creator>
      <pubDate>Fri, 31 Oct 2025 07:00:41 +0000</pubDate>
      <link>https://forem.com/unbalanced-tree/-31da</link>
      <guid>https://forem.com/unbalanced-tree/-31da</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/unbalanced-tree" 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%2F1834119%2F14766253-72ed-46d3-a494-3e9e6ee29044.jpeg" alt="unbalanced-tree"&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" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Microservices: Service-to-service invocation with Dapr, docker-compose, and .NET&lt;/h2&gt;
      &lt;h3&gt;Ravikant Vijayvargiya ・ Aug 30 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#csharp&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#docker&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#dapr&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&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://forem.com/unbalanced-tree/dll-dependencies-c5l</link>
      <guid>https://forem.com/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;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://forem.com/unbalanced-tree/cool-website-to-edit-pdf-48d7</link>
      <guid>https://forem.com/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://forem.com/unbalanced-tree/llm-visualization-maj</link>
      <guid>https://forem.com/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://forem.com/unbalanced-tree/remove-windows-software-completely-4k82</link>
      <guid>https://forem.com/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://forem.com/unbalanced-tree/unit-testing-with-xunit-introduction-3npl</link>
      <guid>https://forem.com/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="459"&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="134"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;xUnit Test Project&lt;/center&gt;&lt;/small&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%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;center&gt;Solution XUnitTesting hierarchy&lt;/center&gt;&lt;/small&gt;&lt;/p&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="229"&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="302"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;UnitTests.cs TestDivide()&lt;/center&gt;&lt;/small&gt;&lt;/p&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;center&gt;Test Explorer&lt;/center&gt;&lt;/small&gt;&lt;/p&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="279"&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="800" 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;center&gt;Assert.Equal(expected, actual, precision)&lt;/center&gt;&lt;/small&gt;&lt;/p&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;center&gt;TestDivideMultipleInputs&lt;/center&gt;&lt;/small&gt;&lt;/p&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="174"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;TestDivideByZero()&lt;/center&gt;&lt;/small&gt;&lt;/p&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://forem.com/unbalanced-tree/roadmap-to-becoming-an-aspnet-core-developer-8d</link>
      <guid>https://forem.com/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://forem.com/unbalanced-tree/search-engine-youcom-418n</link>
      <guid>https://forem.com/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://forem.com/unbalanced-tree/brave-browser-43b5</link>
      <guid>https://forem.com/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="800" 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 -&amp;gt; Media " width="800" height="1433"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;Settings -&amp;gt; Media&lt;/center&gt;&lt;/small&gt;&lt;/p&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://forem.com/unbalanced-tree/in-memory-database-with-sqlite-4en5</link>
      <guid>https://forem.com/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;/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="159"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;For Windows&lt;/center&gt;&lt;/small&gt;&lt;/p&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="800" 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;center&gt;A database with the name localDB.db&lt;/center&gt;&lt;/small&gt;&lt;/p&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;center&gt;To add db file&lt;/center&gt;&lt;/small&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%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;center&gt;To access existing DB&lt;/center&gt;&lt;/small&gt;&lt;/p&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="476"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;Create Table TableOne(Id INT, Value Text)&lt;/center&gt;&lt;/small&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%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;center&gt;Table Schema&lt;/center&gt;&lt;/small&gt;&lt;/p&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="800" height="133"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;A simple Web API&lt;/center&gt;&lt;/small&gt;&lt;/p&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;center&gt;Microsoft.Data.Sqlite&lt;/center&gt;&lt;/small&gt;&lt;/p&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;center&gt;File Structure&lt;/center&gt;&lt;/small&gt;&lt;/p&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="379"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;IDbHelpers&lt;/center&gt;&lt;/small&gt;&lt;/p&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="531"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;DbHelpers&lt;/center&gt;&lt;/small&gt;&lt;/p&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="424"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;&lt;/center&gt;&lt;/small&gt;&lt;/p&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="416"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;Swagger&lt;/center&gt;&lt;/small&gt;&lt;/p&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="438"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;TableOne Data&lt;/center&gt;&lt;/small&gt;&lt;/p&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://forem.com/unbalanced-tree/microservices-pubsub-with-dapr-docker-compose-and-net-18nf</link>
      <guid>https://forem.com/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="283"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;Dapr Pub/Sub&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&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;center&gt;ServiceOne Startup.cs ( Publisher)&lt;/center&gt;&lt;/small&gt;&lt;br&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%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;center&gt;ServiceTwo Startup.cs ( Subscriber)&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&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="199"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;ServiceOne IDaprClientHelper&lt;/center&gt;&lt;/small&gt;&lt;br&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%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="800" height="201"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;ServiceOne DaprClientHelper&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&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;center&gt;IServiceTwoHelper&lt;/center&gt;&lt;/small&gt;&lt;br&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%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="800" height="75"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;ServiceTwoHelper&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&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="800" height="289"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;ServiceOne Controller Method PublishMessage&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&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="800" height="165"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;ServiceTwo Controller Method PublishMessage&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&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;center&gt;Docker-compose.yaml&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&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="134"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;Folder structure&lt;/center&gt;&lt;/small&gt;&lt;br&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%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="800" height="83"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;Components Folder&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&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;center&gt;pubsub.yaml&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&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;center&gt;Call to Service One PublishMessage&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&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="313"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;Docker Desktop (Two services, their sidecars, and Redis service is running)&lt;/center&gt;&lt;/small&gt;&lt;br&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%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="800" height="373"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;Docker ServiceTwo Logs&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&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>
    <item>
      <title>Microservices: Service-to-service invocation with Dapr, docker-compose, and .NET</title>
      <dc:creator>Ravikant Vijayvargiya</dc:creator>
      <pubDate>Fri, 30 Aug 2024 10:04:42 +0000</pubDate>
      <link>https://forem.com/unbalanced-tree/microservices-service-to-service-to-invocation-with-dapr-docker-compose-and-net-4a7h</link>
      <guid>https://forem.com/unbalanced-tree/microservices-service-to-service-to-invocation-with-dapr-docker-compose-and-net-4a7h</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%2F3mo11829whjoqyxjdldf.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%2F3mo11829whjoqyxjdldf.jpeg" alt="A lazy wolf" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Wolf Fact: Arctic wolves have white coats all year round. This contrasts with Arctic foxes who are white for most of the year but develop a grey coat in the summer months.
&lt;/h4&gt;




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

&lt;p&gt;Have you heard of microservices or Dapr and want to learn more? Perhaps you’d like to know some code to get started. I can assist you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Microservices&lt;/strong&gt;:- It is an architectural style that structures an application as a collection of services that are&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Highly maintainable and testable&lt;/li&gt;
&lt;li&gt;Loosely coupled&lt;/li&gt;
&lt;li&gt;Independently deployable&lt;/li&gt;
&lt;li&gt;Organized around business capabilities&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Microservice is a way to implement a distributed system. All microservices are distributed systems but all distributed systems are not microservices.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Hey, but why do I need this?&lt;/em&gt; The more people work on a deployable unit, the less efficient it becomes. Microservice helps in this case, where smaller teams can work on a single deployable unit. These units may or may not be affected by other units. They communicate with one another through various means. That’s where Dapr comes into the picture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dapr.io/" rel="noopener noreferrer"&gt;**Dapr&lt;/a&gt;**:- Dapr codifies the best practices for building microservice applications into open, independent APIs called building blocks that enable you to create portable applications with the language and framework of your choice. One microservice, for example, is written in Python, while another is written in .NET. They can also easily communicate using Dapr.&lt;/p&gt;

&lt;p&gt;Dapr provides so many necessary functionalities for microservice architecture.&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%2Fgg5ebgmnjihecax6e750.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%2Fgg5ebgmnjihecax6e750.png" alt="Dapr" width="800" height="384"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;Dapr&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;br&gt;
In this article, I’ll primarily discuss service-to-service invocation.&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%2Fcdn-images-1.medium.com%2Fmax%2F2988%2F1%2A-DXHlEOF5S1J_Nkzt_9nUg.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%2Fcdn-images-1.medium.com%2Fmax%2F2988%2F1%2A-DXHlEOF5S1J_Nkzt_9nUg.png" alt="[Dapr’s service invocation process](https://docs.dapr.io/developing-applications/building-blocks/service-invocation/service-invocation-overview/#service-invocation)" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;a href="https://docs.dapr.io/developing-applications/building-blocks/service-invocation/service-invocation-overview/#service-invocation" rel="noopener noreferrer"&gt;Dapr’s service invocation process&lt;/a&gt;&lt;/center&gt;
&lt;br&gt;Dapr’s service invocation process

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Service A makes an HTTP or gRPC call targeting Service B. The call goes to the local Dapr sidecar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dapr discovers Service B’s location using the name resolution component which is running on the given hosting platform.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dapr forwards the message to Service B’s Dapr sidecar (always gRPC calls)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Service B’s Dapr sidecar forwards the request to the specified endpoint (or method) on Service B. Service B then runs its business logic code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Service B sends a response to Service A. The response goes to Service B’s sidecar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dapr forwards the response to Service A’s Dapr sidecar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Service A receives the response.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are a few new words like a sidecar. Let’s understand them one by one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sidecar&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%2Flqx0hnqxgrqn23rvfxat.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%2Flqx0hnqxgrqn23rvfxat.jpeg" alt="Bike with sidecar" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;Bike with sidecar&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;In the above image, a sidecar is attached to the bike. Logically, the Dapr distributed application capabilities provider is attached to our Service. That’s why the name sidecar. The Dapr APIs are run and exposed on a separate process ( i.e. the Dapr sidecar) running alongside your application. The Dapr sidecar process is named &lt;strong&gt;&lt;em&gt;daprd&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Name Resolution Component&lt;/strong&gt;:- This component helps in finding the sidecar of the desired service. Dapr provides users with the ability to call other applications that have unique IDs. This functionality allows apps to interact with one another via named identifiers and puts the burden of service discovery on the Dapr runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mTLS Encryption&lt;/strong&gt;:- Mutual Transport Layer Security (mTLS) is a process that establishes an encrypted TLS connection in which both parties use digital certificates( X.509) to authenticate each other. I won’t go in deep on why we need this. If interested, you may have a look at this &lt;a href="https://en.m.wikipedia.org/wiki/Fallacies_of_distributed_computing" rel="noopener noreferrer"&gt;Wikipedia article.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a distributed system, Dapr sidecar architecture helps locate other services, call other services securely, and handle retries in case of temporary service interruptions.&lt;/p&gt;

&lt;p&gt;After a basic introductory theory, now let’s do a practical example. &lt;br&gt;
The complete code can be found &lt;a href="https://github.com/Unbalanced-Tree/CSharp/tree/main/Microservices" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I would create two microservices(Web APIs) with the names ServiceOne and ServiceTwo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Basic Configuration&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%2Fllqvnnjcxuhfkxv6ks0a.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%2Fllqvnnjcxuhfkxv6ks0a.png" alt="ASP.NET Core Web API" width="800" height="394"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;ASP.NET Core Web API&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;Two NuGet packages Dapr.Client and Dapr.AspNetCore is required.&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%2Fy0p2zme8u8ea1ozn5ocp.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%2Fy0p2zme8u8ea1ozn5ocp.png" alt="Dapr NuGets for ASP.NET Core" width="800" height="268"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;Dapr NuGets for ASP.NET Core&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;Let’s now create the project ServiceOne with Dapr.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Folder Structure:-&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;(You may keep the folder structure the way you prefer.)&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%2Fxo5vqxcem1qwfgpcjcaf.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%2Fxo5vqxcem1qwfgpcjcaf.png" alt="Folder Hierarchy" width="530" height="615"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;Folder Hierarchy&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Startup.cs&lt;/strong&gt;:-
&lt;/h3&gt;

&lt;p&gt;Add Dapr integration. Appending the &lt;em&gt;AddDapr&lt;/em&gt; extension method to the &lt;em&gt;AddControllers()&lt;/em&gt; extension method registers the necessary services to integrate Dapr into the MVC pipeline.&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%2Ffbivxpgvgcimpbgnihq7.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%2Ffbivxpgvgcimpbgnihq7.png" alt="ServiceOne Startup.cs" width="800" height="393"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;ServiceOne Startup.cs&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. IDaprClientHelper&lt;/strong&gt;:-
&lt;/h3&gt;

&lt;p&gt;In this interface, I declared a method definition with the name ResponseByDaprClient. This method’s implementation contains steps to invoke other microservices using 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%2F4ketq8rkf22hihylldhw.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%2F4ketq8rkf22hihylldhw.png" alt="IDaprClientHelper" width="800" height="219"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;IDaprClientHelper&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4.&lt;/strong&gt; &lt;strong&gt;DaprClientHelper&lt;/strong&gt;:-
&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%2Fvm5c8h74m064fe1p0xz6.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%2Fvm5c8h74m064fe1p0xz6.png" alt="DaprClientHelper" width="800" height="301"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;DaprClientHelper&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;ResponseByDaprClient method has so many concepts. Let’s understand them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.1 httpMethod&lt;/strong&gt;:- Every API has a unique HTTP request method like PATCH/POST/GET/PUT/DELETE. httpMethod contains this HTTP request method details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.2 appId&lt;/strong&gt;:- Name Resolution Component uses this appId to find and perform service invocation for that particular service. AppId would be mentioned in docker-compose.yaml. I will discuss it later in this article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.3 endPoint&lt;/strong&gt;:- Relative API controller path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.4 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;4.5 daprRequest&lt;/strong&gt;:- A HttpRequestMessage that can be used to perform service invocation for the application identified by appId and invokes the method specified by methodName(endPoint) with the HTTP method specified by httpMethod.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.6 InvokeMethodAsync&lt;/strong&gt;:- Perform service invocation using the request provided by &lt;em&gt;request.&lt;/em&gt; If the response has a success status code the body will de-serialize using JSON to a value of type T. Other wise an exception will be thrown.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;5. IServiceTwoHelper&lt;/strong&gt;:-
&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%2F51bnj6ve98lheoz01co9.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%2F51bnj6ve98lheoz01co9.png" alt="IServiceTwoHelper" width="610" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this interface, I declared a method definition with the name GetMessage. This method’s implementation contains steps to call ServiceTwo’s API named GetMessage.&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%2Fwqyrcumynfiikjl1dgid.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%2Fwqyrcumynfiikjl1dgid.png" alt="ServiceTwo GetMessage API Controller" width="800" height="318"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;ServiceTwo GetMessage API Controller&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;6. ServiceTwoHelper&lt;/strong&gt;:-
&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%2Fz78tu32aqvchle6xuosj.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%2Fz78tu32aqvchle6xuosj.png" alt="ServiceTwoHelper" width="800" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have injected IDaprClientHelper in this class, so I can use ResponseByDaprClient method for ServiceOne to ServiceTwo communication. ResponseByDaprClient takes three parameters as input.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;httpMethod&lt;/em&gt;&lt;/strong&gt;- HttpMethod.Get in this case because ServiceTwo API is a Get method.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;appId&lt;/em&gt;&lt;/strong&gt;- “servicetwoapp”, this name will be mentioned in the docker-compose file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;endPoint&lt;/em&gt;&lt;/strong&gt;- “/Home/GetMessage”, it is the address of ServiceTwo API.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. 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%2Fzv3lj7db0wkopkkboys4.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%2Fzv3lj7db0wkopkkboys4.png" alt="HomeController" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now the &lt;em&gt;docker-compose.yaml&lt;/em&gt; file.&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%2Fj6cs5odth9pvhkilv6ks.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%2Fj6cs5odth9pvhkilv6ks.png" alt="docker-compose.yaml" width="800" height="864"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;docker-compose.yaml&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;I explained a basic docker-compose file in the first part of this series.  So here, I am going to focus on the sidecar part i.e. serviceoneapp-dapr and servicetwoapp-dapr.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;image&lt;/em&gt;&lt;/strong&gt;: daprd is just the name of the Dapr sidecar process. There are many &lt;a href="https://docs.dapr.io/operations/hosting/self-hosted/self-hosted-with-docker/#images" rel="noopener noreferrer"&gt;published Docker images &lt;/a&gt;for each of the Dapr components available on Docker Hub. You may use daprd:latest for the latest release. You should always use fix and stable version for the production environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;command&lt;/em&gt;&lt;/strong&gt;: It contains a collection of instructions to run a Dapr sidecar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;app-id&lt;/em&gt;&lt;/strong&gt;: ResponseByDaprClient uses this name. The name resolution component uses this name to find the required Dapr sidecar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;app-port&lt;/em&gt;&lt;/strong&gt;: This port number will be the same as an exposed port of service’s Dockerfile.&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%2Ft029qt56bor1vuyx4h9n.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%2Ft029qt56bor1vuyx4h9n.png" alt="ServiceOne Dockerfile Expose Port" width="800" height="340"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;ServiceOne Dockerfile Expose Port&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.dapr.io/concepts/components-concept/" rel="noopener noreferrer"&gt;***components&lt;/a&gt;***: It is a configuration that defines which state store to use or which pub-sub to use or which binding to use etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;network_mode&lt;/em&gt;&lt;/strong&gt;: Using network_mode, I placed two containers serviceoneapp-dapr and serviceoneapp in the same namespace. It means both have the same IP and the same open TCP ports.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Hey, that’s a lot of explanation but does it even works?&lt;/em&gt;&lt;br&gt;
Now Let’s test it.&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 up

deploying....( wink)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Any application can invoke a Dapr sidecar by using the native invoke API built into Dapr. The API can be called with either HTTP or gRPC. Use the following URL to call the HTTP API:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[http://localhost](http://localhost):&amp;lt;dapr-port&amp;gt;/v1.0/invoke/&amp;lt;application-id&amp;gt;/method/&amp;lt;method-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt; the HTTP port that Dapr is listening on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt; application ID of the service to call.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt; name of the method to invoke the remote service.&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%2Fd3gc16xy34nsajo9g4lh.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%2Fd3gc16xy34nsajo9g4lh.png" alt="Call to ServiceOne sidecar which invokes ServiceTwo" width="800" height="288"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;Call to ServiceOne sidecar which invokes ServiceTwo&lt;/center&gt;&lt;/small&gt;&lt;br&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%2Fnkg3bw8ulirohevkpuv3.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%2Fnkg3bw8ulirohevkpuv3.png" alt="Call to ServiceTwo sidecar" width="800" height="276"&gt;&lt;/a&gt;&lt;small&gt;&lt;center&gt;Call to ServiceTwo sidecar&lt;/center&gt;&lt;/small&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;That’s how I accomplished service-to-service invocation using docker-compose, Dapr, and a web API.&lt;/p&gt;

&lt;p&gt;Friendly Suggestion: Keep the code for every microservice in a separate repository.&lt;/p&gt;

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

</description>
      <category>csharp</category>
      <category>docker</category>
      <category>dapr</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
