<?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: Aezan</title>
    <description>The latest articles on DEV Community by Aezan (@aezan).</description>
    <link>https://dev.to/aezan</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%2F3307855%2Fa8288db1-cfa3-4f97-b9d1-be2ea7071495.jpeg</url>
      <title>DEV Community: Aezan</title>
      <link>https://dev.to/aezan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aezan"/>
    <language>en</language>
    <item>
      <title>Design Patterns Explained in C# &amp; nopCommerce</title>
      <dc:creator>Aezan</dc:creator>
      <pubDate>Wed, 21 Jan 2026 06:18:15 +0000</pubDate>
      <link>https://dev.to/aezan/design-patterns-explained-in-c-nopcommerce-5dpa</link>
      <guid>https://dev.to/aezan/design-patterns-explained-in-c-nopcommerce-5dpa</guid>
      <description>&lt;p&gt;When we work on large applications, we often face similar problems again and again. Design patterns help us solve these recurring problems using proven and reusable approaches.&lt;/p&gt;

&lt;p&gt;A design pattern is not a piece of code that you copy and paste. Instead, it is a general solution or idea that you can adapt to your own project based on its needs. You follow the concept of the pattern and implement it in a way that fits your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of Design Patterns
&lt;/h2&gt;

&lt;p&gt;There are mainly three types of design patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creational patterns – focus on object creation&lt;/li&gt;
&lt;li&gt;Structural patterns – focus on class and object composition&lt;/li&gt;
&lt;li&gt;Behavioral patterns – focus on communication between objects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In real-world applications, these patterns are not used in isolation. They are often combined to build scalable and maintainable systems.&lt;/p&gt;

&lt;p&gt;A good real-world example of this is nopCommerce.&lt;br&gt;
nopCommerce uses many design patterns across different layers of its architecture.&lt;/p&gt;

&lt;p&gt;In this article, I will explain common C# design patterns by showing how they are actually used inside nopCommerce.&lt;/p&gt;

&lt;p&gt;nopCommerce is divided into three main layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nop.Core&lt;/li&gt;
&lt;li&gt;Nop.Data&lt;/li&gt;
&lt;li&gt;Nop.Services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll explain two design patterns from each layer.&lt;/p&gt;
&lt;h2&gt;
  
  
  Nop.Core
&lt;/h2&gt;

&lt;p&gt;Nop.Core contains the core abstractions and infrastructure of nopCommerce.&lt;/p&gt;

&lt;p&gt;Design patterns used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Singleton Pattern&lt;/li&gt;
&lt;li&gt;Observer Pattern&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Singleton Pattern
&lt;/h2&gt;

&lt;p&gt;The Singleton pattern is a creational design pattern that ensures a class has only one instance and provides a global access point to that instance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Singleton in nopCommerce&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In nopCommerce, there is a custom Singleton class. This implementation is slightly different from the classic GoF Singleton. It works more like a central registry for shared instances during the application’s lifetime.&lt;/p&gt;

&lt;p&gt;Core Singleton Implementation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace Nop.Core.Infrastructure
{
    /// &amp;lt;summary&amp;gt;
    /// A statically compiled "singleton" used to store objects
    /// throughout the lifetime of the app domain.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;typeparam name="T"&amp;gt;The type of object to store.&amp;lt;/typeparam&amp;gt;
    public partial class Singleton&amp;lt;T&amp;gt; : BaseSingleton
    {
        private static T instance;

        /// &amp;lt;summary&amp;gt;
        /// The singleton instance for the specified type T.
        /// &amp;lt;/summary&amp;gt;
        public static T Instance
        {
            get =&amp;gt; instance;
            set
            {
                instance = value;
                AllSingletons[typeof(T)] = value;
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How this works&lt;/p&gt;

&lt;p&gt;Singleton stores a single instance of type T&lt;/p&gt;

&lt;p&gt;The instance is stored in a static field&lt;/p&gt;

&lt;p&gt;All singleton instances are tracked using a shared dictionary&lt;/p&gt;

&lt;p&gt;This ensures one shared instance per type for the entire app domain&lt;/p&gt;

&lt;p&gt;This approach gives nopCommerce a consistent and controlled way to manage shared objects across the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Observer Pattern
&lt;/h2&gt;

&lt;p&gt;The Observer pattern is a behavioral design pattern that allows objects to subscribe to events and get notified automatically when something changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observer in nopCommerce&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;nopCommerce uses the Observer pattern heavily through its event system. This is especially useful when entities are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inserted&lt;/li&gt;
&lt;li&gt;Updated&lt;/li&gt;
&lt;li&gt;Deleted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of tightly coupling logic everywhere, nopCommerce publishes events and lets consumers react to them.&lt;/p&gt;

&lt;p&gt;This keeps the code modular, decoupled, and maintainable.&lt;/p&gt;

&lt;p&gt;Core Components of the Observer Pattern in nopCommerce&lt;/p&gt;

&lt;p&gt;Events – represent something that happened&lt;/p&gt;

&lt;p&gt;Event Publisher – publishes events&lt;/p&gt;

&lt;p&gt;Event Consumers – handle the events&lt;/p&gt;

&lt;p&gt;Example: Entity Deleted Event&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace Nop.Core.Events
{
    public partial class EntityDeletedEvent&amp;lt;T&amp;gt; where T : BaseEntity
    {
        public EntityDeletedEvent(T entity)
        {
            Entity = entity;
        }

        public T Entity { get; }
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This event carries the deleted entity so consumers know exactly what was deleted.&lt;/p&gt;

&lt;p&gt;nopCommerce also provides:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EntityInsertedEvent&amp;lt;T&amp;gt;

EntityUpdatedEvent&amp;lt;T&amp;gt;

Event Publisher Interface
namespace Nop.Core.Events
{
    public partial interface IEventPublisher
    {
        Task PublishAsync&amp;lt;TEvent&amp;gt;(TEvent @event);
        void Publish&amp;lt;TEvent&amp;gt;(TEvent @event);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The publisher sends events to all subscribed consumers, either synchronously or asynchronously.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nop.Data
&lt;/h2&gt;

&lt;p&gt;Nop.Data is responsible for data access in nopCommerce.&lt;/p&gt;

&lt;p&gt;Design patterns used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Builder Pattern&lt;/li&gt;
&lt;li&gt;Repository Pattern&lt;/li&gt;
&lt;li&gt;Builder Pattern&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Builder pattern is a creational pattern that helps construct complex objects step by step. It allows different representations of an object using the same construction process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Builder in nopCommerce&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In nopCommerce, the Builder pattern is commonly used with FluentMigrator to define database schemas in a readable and structured way.&lt;/p&gt;

&lt;p&gt;Example: BlogPostBuilder&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using FluentMigrator.Builders.Create.Table;
using Nop.Core.Domain.Blogs;
using Nop.Core.Domain.Localization;
using Nop.Data.Extensions;

namespace Nop.Data.Mapping.Builders.Blogs
{
    /// &amp;lt;summary&amp;gt;
    /// Represents a blog post entity builder
    /// &amp;lt;/summary&amp;gt;
    public partial class BlogPostBuilder : NopEntityBuilder&amp;lt;BlogPost&amp;gt;
    {
        public override void MapEntity(CreateTableExpressionBuilder table)
        {
            table
                .WithColumn(nameof(BlogPost.Title)).AsString(int.MaxValue).NotNullable()
                .WithColumn(nameof(BlogPost.Body)).AsString(int.MaxValue).NotNullable()
                .WithColumn(nameof(BlogPost.MetaKeywords)).AsString(400).Nullable()
                .WithColumn(nameof(BlogPost.MetaTitle)).AsString(400).Nullable()
                .WithColumn(nameof(BlogPost.LanguageId)).AsInt32().ForeignKey&amp;lt;Language&amp;gt;();
        }
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why this is Builder Pattern&lt;/p&gt;

&lt;p&gt;The object (table schema) is built step by step&lt;/p&gt;

&lt;p&gt;Fluent syntax improves readability&lt;/p&gt;

&lt;p&gt;The construction logic is separated from usage&lt;/p&gt;

&lt;p&gt;This is a good example of Builder + Fluent Interface working together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repository Pattern
&lt;/h2&gt;

&lt;p&gt;The Repository pattern abstracts data access logic and provides a clean API for the business layer.&lt;/p&gt;

&lt;p&gt;In nopCommerce, repositories:&lt;/p&gt;

&lt;p&gt;Hide database details&lt;/p&gt;

&lt;p&gt;Improve testability&lt;/p&gt;

&lt;p&gt;Promote separation of concerns&lt;/p&gt;

&lt;p&gt;Repositories are commonly used with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dependency Injection&lt;/li&gt;
&lt;li&gt;Unit of Work&lt;/li&gt;
&lt;li&gt;Service Layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example: Repository Used Inside a Service&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public partial class BlogService : IBlogService
{
    private readonly IRepository&amp;lt;BlogComment&amp;gt; _blogCommentRepository;
    private readonly IRepository&amp;lt;BlogPost&amp;gt; _blogPostRepository;

    public BlogService(
        IRepository&amp;lt;BlogComment&amp;gt; blogCommentRepository,
        IRepository&amp;lt;BlogPost&amp;gt; blogPostRepository)
    {
        _blogCommentRepository = blogCommentRepository;
        _blogPostRepository = blogPostRepository;
    }

    public virtual async Task DeleteBlogPostAsync(BlogPost blogPost)
    {
        await _blogPostRepository.DeleteAsync(blogPost);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here:&lt;/p&gt;

&lt;p&gt;Repository handles data access&lt;/p&gt;

&lt;p&gt;Service handles business logic&lt;/p&gt;

&lt;h2&gt;
  
  
  Nop.Services
&lt;/h2&gt;

&lt;p&gt;Nop.Services contains the business logic layer.&lt;/p&gt;

&lt;p&gt;Design patterns used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Service Pattern&lt;/li&gt;
&lt;li&gt;Dependency Injection Pattern&lt;/li&gt;
&lt;li&gt;Service Pattern&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Service pattern organizes business logic and acts as a bridge between:&lt;/p&gt;

&lt;p&gt;Presentation layer&lt;/p&gt;

&lt;p&gt;Data access layer&lt;/p&gt;

&lt;p&gt;This makes the application:&lt;/p&gt;

&lt;p&gt;Easier to maintain&lt;/p&gt;

&lt;p&gt;Easier to test&lt;/p&gt;

&lt;p&gt;Easier to understand&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service Interface and Implementation&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public partial interface IBlogService
{
    Task DeleteBlogPostAsync(BlogPost blogPost);
    Task&amp;lt;BlogPost&amp;gt; GetBlogPostByIdAsync(int blogPostId);
}

public partial class BlogService : IBlogService
{
    private readonly IRepository&amp;lt;BlogPost&amp;gt; _blogPostRepository;

    public BlogService(IRepository&amp;lt;BlogPost&amp;gt; blogPostRepository)
    {
        _blogPostRepository = blogPostRepository;
    }

    public async Task DeleteBlogPostAsync(BlogPost blogPost)
    {
        await _blogPostRepository.DeleteAsync(blogPost);
    }

    public async Task&amp;lt;BlogPost&amp;gt; GetBlogPostByIdAsync(int blogPostId)
    {
        return await _blogPostRepository.GetByIdAsync(blogPostId, cache =&amp;gt; default);
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The service defines what the system can do, while repositories handle how data is accessed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependency Injection Pattern
&lt;/h2&gt;

&lt;p&gt;Dependency Injection (DI) is used everywhere in nopCommerce.&lt;/p&gt;

&lt;p&gt;Instead of creating dependencies manually, they are injected through constructors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public partial class BlogService : IBlogService
{
    private readonly IRepository&amp;lt;BlogPost&amp;gt; _blogPostRepository;

    public BlogService(IRepository&amp;lt;BlogPost&amp;gt; blogPostRepository)
    {
        _blogPostRepository = blogPostRepository;
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Benefits of DI&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loose coupling&lt;/li&gt;
&lt;li&gt;Easier unit testing&lt;/li&gt;
&lt;li&gt;Better maintainability&lt;/li&gt;
&lt;li&gt;Cleaner architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;nopCommerce uses DI in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Services&lt;/li&gt;
&lt;li&gt;Factories&lt;/li&gt;
&lt;li&gt;Controllers&lt;/li&gt;
&lt;li&gt;Repositories&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disadvantages of Design Patterns&lt;/p&gt;

&lt;p&gt;While design patterns are powerful, they are not always the best solution.&lt;/p&gt;

&lt;p&gt;Common disadvantages&lt;/p&gt;

&lt;p&gt;Complexity – can make code harder to understand&lt;/p&gt;

&lt;p&gt;Learning curve – requires solid understanding&lt;/p&gt;

&lt;p&gt;Overengineering – patterns used where simple code is enough&lt;/p&gt;

&lt;p&gt;Rigidity – may reduce flexibility&lt;/p&gt;

&lt;p&gt;Increased development time – more planning and structure&lt;/p&gt;

&lt;p&gt;Misapplication – wrong pattern causes bad architecture&lt;/p&gt;

&lt;p&gt;Dependency complexity – harder to refactor&lt;/p&gt;

&lt;p&gt;Documentation overhead – patterns must be well documented&lt;/p&gt;

&lt;p&gt;Design patterns should be used as tools, not rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;nopCommerce is a great real-world example of how C# design patterns are used in production systems.&lt;/p&gt;

&lt;p&gt;Patterns like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Singleton&lt;/li&gt;
&lt;li&gt;Observer&lt;/li&gt;
&lt;li&gt;Builder&lt;/li&gt;
&lt;li&gt;Repository&lt;/li&gt;
&lt;li&gt;Service&lt;/li&gt;
&lt;li&gt;Dependency Injection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;help keep the codebase scalable, testable, and maintainable.&lt;/p&gt;

&lt;p&gt;The key lesson is not to use patterns everywhere, but to use them when they actually solve a problem.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;br&gt;
You can find me on &lt;a href="https://github.com/AezanPathan" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;br&gt;
 and &lt;a href="https://www.linkedin.com/in/aezanpathan/" rel="noopener noreferrer"&gt;LinkedIn &lt;/a&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>nopcommerce</category>
      <category>designpatterns</category>
      <category>ecommerce</category>
    </item>
    <item>
      <title>I Created an MCP Server and Why I Think MCP is Overrated</title>
      <dc:creator>Aezan</dc:creator>
      <pubDate>Fri, 07 Nov 2025 07:42:45 +0000</pubDate>
      <link>https://dev.to/aezan/i-created-an-mcp-server-and-why-i-think-mcp-is-overrated-lmh</link>
      <guid>https://dev.to/aezan/i-created-an-mcp-server-and-why-i-think-mcp-is-overrated-lmh</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%2F5wi6me7dgd6swn8yc8e5.gif" 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%2F5wi6me7dgd6swn8yc8e5.gif" alt=" " width="500" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sometime ago, I created an MCP server with C#. It was just a basic project I was trying to learn how MCP works, and I followed this &lt;a href="https://devblogs.microsoft.com/dotnet/build-a-model-context-protocol-mcp-server-in-csharp/?wt.mc_id=studentamb_475453" rel="noopener noreferrer"&gt;Microsoft blog&lt;/a&gt;&lt;br&gt;
 to get started. At that time, MCP was booming, and I wanted to explore AI development using my favorite language, C#. So, I decided to create a simple Google Sheets MCP integration just to see how it works.&lt;/p&gt;

&lt;p&gt;This blog is not a step-by-step tutorial on how to create an MCP server, but more about what I think of MCP after building one.&lt;br&gt;
So, MCP or Model Context Protocol is an open-source protocol that allows you to expose your methods and functions to AI agents. Basically, it lets the AI directly access your code or functions. That’s why developers get excited about it: it feels like connecting your codebase directly to an intelligent assistant.&lt;/p&gt;

&lt;p&gt;Now, about why I don’t really love MCP. I don’t hate it — it’s just “okay” for me. AI is powerful, but it’s still not fully accurate or secure. If you’ve worked with AI before, you know how easily it gets confused or stuck repeating the same thing. MCP depends heavily on natural language, which makes it even more unreliable in real use cases.&lt;/p&gt;

&lt;p&gt;For example, let’s say you build a simple MCP tool that just adds two numbers. When you connect your AI agent and ask, “Can you add 1 + 1?”, there’s a high chance the AI will just respond with “2” directly instead of calling your MCP tool — unless you explicitly tell it to use the tool. That’s the issue: MCP sounds great in theory but doesn’t always behave as expected in real workflows. It’s more suited for AI coding experiments or vibe coding sessions rather than serious projects where you’re writing the logic yourself.&lt;/p&gt;

&lt;p&gt;Another thing I noticed while experimenting is that MCP feels more like a bridge technology something that fills the gap between AI tools and real-world codebases, but not something most developers actually need daily. It looks impressive in demos, but when you implement it, you realize it doesn’t really solve a new problem; it just repackages an old one with a different label.&lt;/p&gt;

&lt;p&gt;I also think the hype around MCP mostly comes from how Big Tech markets it rather than how developers use it. Everyone loves to say “AI agents can now run your code,” but in practice, 90% of the time it’s faster and safer to just expose an API or run a script yourself. MCP adds another layer that looks fancy but doesn’t necessarily improve your workflow. There are also more developers building MCP tools than actual users. It’s mostly used by vibe coders or enthusiasts rather than everyday developers writing real-world code. People love the idea of AI and anything with “AI” in it gets instant hype but that doesn’t mean it’s always practical.&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%2Fpolpaf023lm3q7eut40q.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%2Fpolpaf023lm3q7eut40q.jpeg" alt=" " width="800" height="766"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That said, I still respect the idea behind MCP. It’s a good step toward standardizing how AI tools interact with software, and I can see it becoming useful once AI models get more consistent and reliable. Maybe in the future, MCP will make more sense but for now, it feels more like a presentation feature than a production feature.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;br&gt;
You can find me on &lt;a href="https://github.com/AezanPathan" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;br&gt;
 and &lt;a href="https://www.linkedin.com/in/aezanpathan/" rel="noopener noreferrer"&gt;LinkedIn &lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>architecture</category>
      <category>security</category>
    </item>
    <item>
      <title>I Created a BitTorrent Client with Blazor and c#</title>
      <dc:creator>Aezan</dc:creator>
      <pubDate>Sun, 03 Aug 2025 07:27:43 +0000</pubDate>
      <link>https://dev.to/aezan/i-created-a-bittorrent-client-with-blazor-and-c-47i6</link>
      <guid>https://dev.to/aezan/i-created-a-bittorrent-client-with-blazor-and-c-47i6</guid>
      <description>&lt;p&gt;Some time ago I completed the CodeCrafters BitTorrent challenge, and after that I rewrote the torrent client in Blazor to understand it more deeply and also as a portfolio project. So I chose Blazor rather than going with .NET MVC.  &lt;/p&gt;

&lt;p&gt;I took on this project to enhance my C# skills and logic, and I learned more about how cryptography works, networking, TCP handshake, and obviously how BitTorrent files work.  &lt;/p&gt;

&lt;p&gt;This article isn’t a deep dive, but rather a quick overview of how I built the BitTorrent client and how it works under the hood.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. BitTorrent Encoding
&lt;/h2&gt;

&lt;p&gt;BitTorrent files are decoded using &lt;strong&gt;bencoding&lt;/strong&gt;, and you have to decode this format to get the file contents. Bencoding supports 4 types, and they are encoded like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Integers are encoded as i&amp;lt;base10 integer&amp;gt;e.
Zero is encoded as i0e.

Byte Strings are encoded as &amp;lt;length&amp;gt;:&amp;lt;contents&amp;gt;.
The length is the number of bytes in the string, encoded in base 10.
A colon (:) separates the length and the contents.
The string "bencode" is encoded as 7:bencode.

Lists are encoded as l&amp;lt;elements&amp;gt;e.
A list containing the string "bencode" and the integer -20 is encoded as l7:bencodei-20ee.

Dictionaries are encoded as d&amp;lt;pairs&amp;gt;e.
A dictionary with keys "wiki" ? "bencode" and "meaning" ? 42 is encoded as d7:meaningi42e4:wiki7:bencodee.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. BitTorrent File Content
&lt;/h2&gt;

&lt;p&gt;A BitTorrent file contains a dictionary with keys like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;announce&lt;/li&gt;
&lt;li&gt;announce-list&lt;/li&gt;
&lt;li&gt;comment&lt;/li&gt;
&lt;li&gt;created by&lt;/li&gt;
&lt;li&gt;creation date&lt;/li&gt;
&lt;li&gt;encoding&lt;/li&gt;
&lt;li&gt;info&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What we mainly need is the &lt;strong&gt;info&lt;/strong&gt; dictionary, because inside that the pieces we will download are stored.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Peers
&lt;/h2&gt;

&lt;p&gt;We use peers to download the file. To find peers, we use the tracker available in the &lt;code&gt;announce&lt;/code&gt; dictionary field. We read the tracker URL from &lt;code&gt;announce&lt;/code&gt; and send a GET request there, and in the response we get the list of available peers, including their IP and port. Then we use those peers to download the pieces.&lt;/p&gt;

&lt;p&gt;We can also use just one peer to download, but it is recommended to use multiple peers in parallel to improve speed. There are many dead peers as well as slow peers, so we should make sure the peer is working properly and that we are using the right peers.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. TCP Handshake
&lt;/h2&gt;

&lt;p&gt;BitTorrent uses TCP to make the communication between client and peer. We make the connection with the peer, and after a successful handshake the peer will return messages like &lt;code&gt;bitfield&lt;/code&gt;, &lt;code&gt;unchoke&lt;/code&gt;, etc. Then we have to send messages like &lt;code&gt;interested&lt;/code&gt; or request any specific piece to download.  &lt;/p&gt;

&lt;p&gt;If somehow a piece is not downloaded, you can make a download piece later queue with the piece index, and then request all the pieces again with a new peer or try again with the same peer (I have to implement this too 💀).&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Download File
&lt;/h2&gt;

&lt;p&gt;Now you have successfully established the connection with the peer. What you have to do next is download the file in BitTorrent, but it is not that simple. There are many things you have to take care of, like making sure you got the piece data correctly by comparing it with the expected piece data from the info dictionary.  &lt;/p&gt;

&lt;p&gt;You have to match that, and as I wrote before you have to make sure you are using multi-peer downloading and properly assign each peer to each piece.  &lt;/p&gt;

&lt;p&gt;If you got this far, pray that your file was not corrupt or a pending piece, otherwise all your hard work is useless.  &lt;/p&gt;




&lt;p&gt;Anyway, this is just my learning project to increase my skills, and I think it helped me a lot no doubt, but it was not too easy. This post is not about the full details or how the code works, but just about the under-the-hood process of how it works.&lt;/p&gt;

&lt;p&gt;✨ &lt;a href="https://github.com/AezanPathan/BlazeTorrent" rel="noopener noreferrer"&gt;Here’s&lt;/a&gt; the full source code on GitHub if you want to take a look.&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%2Fbssldwzfgl2f63pyrf9p.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%2Fbssldwzfgl2f63pyrf9p.png" alt=" " width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>csharp</category>
      <category>dotnet</category>
      <category>networking</category>
    </item>
  </channel>
</rss>
