<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Sudip Bhandari]]></title><description><![CDATA[Software Developer]]></description><link>https://sudipbhandari.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Tue, 13 Oct 2026 13:14:46 GMT</lastBuildDate><atom:link href="https://sudipbhandari.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[ASP.NET Core for Beginners: HttpContext, IHttpContextAccessor, IConfiguration & IOptions<T>]]></title><description><![CDATA[A hands-on guide using a real ProductAPI project — with every concept explained line by line.


What You'll Learn



Concept
What It Does



HttpContext
Access request, response, headers, user & IP in]]></description><link>https://sudipbhandari.hashnode.dev/asp-net-core-for-beginners-httpcontext-ihttpcontextaccessor-iconfiguration-ioptions-t</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/asp-net-core-for-beginners-httpcontext-ihttpcontextaccessor-iconfiguration-ioptions-t</guid><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Sun, 15 Mar 2026 03:06:57 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p>A hands-on guide using a real <strong>ProductAPI</strong> project — with every concept explained line by line.</p>
</blockquote>
<hr />
<h2>What You'll Learn</h2>
<table>
<thead>
<tr>
<th>Concept</th>
<th>What It Does</th>
</tr>
</thead>
<tbody><tr>
<td><code>HttpContext</code></td>
<td>Access request, response, headers, user &amp; IP inside a controller</td>
</tr>
<tr>
<td><code>IHttpContextAccessor</code></td>
<td>Access <code>HttpContext</code> from services <strong>outside</strong> a controller</td>
</tr>
<tr>
<td><code>IConfiguration</code></td>
<td>Read raw values from <code>appsettings.json</code> by key path</td>
</tr>
<tr>
<td><code>IOptions&lt;T&gt;</code></td>
<td>Bind a config section to a strongly-typed C# class</td>
</tr>
</tbody></table>
<p>All examples come from a single working project — a <code>ProductController</code> with a <code>GetNetworkService</code> helper. By the end you'll understand every line of both files.</p>
<hr />
<h2>📁 Project Structure We're Working With</h2>
<pre><code class="language-plaintext">ProductAPI/
├── Controllers/
│   └── ProductController.cs
├── Services/
│   └── GetNetworkService.cs
├── Options/
│   └── OpenApiOptions.cs
├── appsettings.json
└── Program.cs
</code></pre>
<hr />
<h2>Chapter 1 — HttpContext</h2>
<h3>What Is HttpContext?</h3>
<p>Every HTTP request that arrives at your API is wrapped in an object called <code>HttpContext</code>. Think of it as a box that holds <strong>everything</strong> about the current web request and response — headers, cookies, the user's identity, the IP address, and more.</p>
<blockquote>
<p>💡 <strong>Simple Analogy:</strong> Imagine you run a post office. Every parcel arrives with a label (headers), a sender address (IP), recipient info (URL), the parcel contents (request body), and a reply envelope (response). <code>HttpContext</code> is that entire parcel + reply envelope combined.</p>
</blockquote>
<h3>Where Does HttpContext Come From?</h3>
<p>In ASP.NET Core, the framework creates a new <code>HttpContext</code> for every incoming request. Because your controller inherits from <code>ControllerBase</code>, it already has a property called <code>HttpContext</code> — <strong>no injection needed</strong>.</p>
<pre><code class="language-csharp">// ProductController.cs
[ApiController]
[Route("api/[controller]")]
public class ProductController : ControllerBase   // &lt;-- inherits ControllerBase
{
    // ControllerBase gives you 'HttpContext' for free.
    // No constructor injection needed for HttpContext itself.
}
</code></pre>
<h3>Reading Request Headers</h3>
<p>Headers are key-value pairs sent by the client (browser, Postman, mobile app, etc.). Common ones include <code>Content-Type</code>, <code>Authorization</code>, and custom ones like <code>X-Custom-Header</code>.</p>
<pre><code class="language-csharp">// Inside Get() in ProductController.cs

var headers = HttpContext.Request.Headers;

foreach (var header in headers)
{
    Console.WriteLine($"{header.Key}: {header.Value}");

    // Check for a specific header
    if (header.Key == "X-Custom-Header")
    {
        Console.WriteLine($"Custom Header Value: {header.Value}");
    }
}
</code></pre>
<blockquote>
<p>📝 <strong>Key Points:</strong></p>
<ul>
<li><p><code>HttpContext.Request.Headers</code> is a dictionary of all incoming headers.</p>
</li>
<li><p>Keys are <strong>case-insensitive</strong> (<code>X-Custom-Header</code> = <code>x-custom-header</code>).</p>
</li>
<li><p>Always check if a header exists before reading its value.</p>
</li>
</ul>
</blockquote>
<h3>Writing Response Headers</h3>
<p>You can add headers to your response — for example, a timestamp showing when the response was generated.</p>
<pre><code class="language-csharp">// Add a custom header to the HTTP response
HttpContext.Response.Headers.Add("X-Response-Time", DateTime.UtcNow.ToString("o"));

// 'o' = ISO 8601 format, e.g. 2025-06-01T12:00:00.000Z

// Log all response headers
foreach (var header in HttpContext.Response.Headers)
{
    Console.WriteLine($"{header.Key}: {header.Value}");
}
</code></pre>
<h3>Getting the Logged-In User</h3>
<p><code>HttpContext.User</code> holds the identity of the currently authenticated user. If no authentication is configured, the user will be <code>"Anonymous"</code>.</p>
<pre><code class="language-csharp">// Get the username of the logged-in user (or 'Anonymous' if not logged in)
var user = HttpContext.User.Identity?.Name ?? "Anonymous";

// The ?? operator means: "if null, use this fallback value"
// Identity?.Name uses ?. to safely handle the case where Identity is null

Console.WriteLine($"Session User: {user}");
</code></pre>
<h3>Quick Reference — HttpContext Properties</h3>
<table>
<thead>
<tr>
<th>Property</th>
<th>Type</th>
<th>What You Get</th>
</tr>
</thead>
<tbody><tr>
<td><code>HttpContext.Request.Headers</code></td>
<td><code>IHeaderDictionary</code></td>
<td>All incoming request headers</td>
</tr>
<tr>
<td><code>HttpContext.Response.Headers</code></td>
<td><code>IHeaderDictionary</code></td>
<td>Response headers you can add to</td>
</tr>
<tr>
<td><code>HttpContext.User.Identity?.Name</code></td>
<td><code>string?</code></td>
<td>Logged-in username (or null)</td>
</tr>
<tr>
<td><code>HttpContext.Connection.RemoteIpAddress</code></td>
<td><code>IPAddress?</code></td>
<td>Client's IP address</td>
</tr>
<tr>
<td><code>HttpContext.Request.Path</code></td>
<td><code>PathString</code></td>
<td>URL path, e.g. <code>/api/product</code></td>
</tr>
<tr>
<td><code>HttpContext.Request.Method</code></td>
<td><code>string</code></td>
<td>HTTP verb: GET, POST, etc.</td>
</tr>
</tbody></table>
<hr />
<h2>Chapter 2 — IHttpContextAccessor</h2>
<h3>The Problem: Services Don't Have HttpContext</h3>
<p>Controllers inherit <code>ControllerBase</code> and get <code>HttpContext</code> automatically. But what about a helper service class like <code>GetNetworkService</code>? <strong>Service classes do NOT inherit</strong> <code>ControllerBase</code>, so they have no direct access to <code>HttpContext</code>.</p>
<pre><code class="language-csharp">// ❌ This will NOT compile
public class GetNetworkService
{
    public string GetUserIP()
    {
        // ERROR: 'HttpContext' does not exist in this context
        return HttpContext.Connection.RemoteIpAddress?.ToString();
    }
}
</code></pre>
<p>The solution is to inject <code>IHttpContextAccessor</code> — an interface provided by ASP.NET Core that lets <strong>any class</strong> access the current <code>HttpContext</code>.</p>
<h3>The GetNetworkService — Full Walkthrough</h3>
<pre><code class="language-csharp">public class GetNetworkService
{
    // Step 1: Declare a field to store the accessor
    public readonly IHttpContextAccessor _httpContextAccessor;

    // Step 2: Receive IHttpContextAccessor via constructor injection
    public GetNetworkService(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    // Step 3: Use it — access HttpContext through the accessor
    public string GetUserIP()
    {
        return _httpContextAccessor.HttpContext
                   ?.Connection.RemoteIpAddress
                   ?.ToString() ?? "Unknown";
    }
}
</code></pre>
<h3>Breaking Down the IP Address Line</h3>
<table>
<thead>
<tr>
<th>Code Part</th>
<th>Meaning</th>
</tr>
</thead>
<tbody><tr>
<td><code>_httpContextAccessor.HttpContext</code></td>
<td>Get the current HTTP context (may be null outside a request)</td>
</tr>
<tr>
<td><code>?.Connection</code></td>
<td>Safe navigation: only proceed if <code>HttpContext</code> is not null</td>
</tr>
<tr>
<td><code>?.RemoteIpAddress</code></td>
<td>Safe navigation: get IP (null if not available)</td>
</tr>
<tr>
<td><code>.ToString()</code></td>
<td>Convert <code>IPAddress</code> object to a readable string like <code>127.0.0.1</code></td>
</tr>
<tr>
<td><code>?? "Unknown"</code></td>
<td>Fallback value if anything above returned null</td>
</tr>
</tbody></table>
<h3>Registering the Service — Program.cs</h3>
<p>For dependency injection to work, you must register both <code>IHttpContextAccessor</code> <strong>and</strong> your service in <code>Program.cs</code>:</p>
<pre><code class="language-csharp">// Program.cs

var builder = WebApplication.CreateBuilder(args);

// REQUIRED: Register IHttpContextAccessor with the DI container
builder.Services.AddHttpContextAccessor();

// Register your custom service
builder.Services.AddScoped&lt;GetNetworkService&gt;();

builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();
</code></pre>
<blockquote>
<p>⚠️ <strong>Common Mistake — Forgetting to Register</strong></p>
<p>If you forget <code>builder.Services.AddHttpContextAccessor()</code>, you will get:</p>
<pre><code class="language-plaintext">InvalidOperationException: Unable to resolve service for type
'Microsoft.AspNetCore.Http.IHttpContextAccessor'
</code></pre>
<p>Always register it before building the app.</p>
</blockquote>
<h3>Using the Service in the Controller</h3>
<pre><code class="language-csharp">// ProductController.cs — constructor receives GetNetworkService
public class ProductController : ControllerBase
{
    private readonly GetNetworkService _myService;

    public ProductController(GetNetworkService myService)
    {
        _myService = myService;
    }

    [HttpGet("getall")]
    public ActionResult&lt;List&lt;Product&gt;&gt; Get()
    {
        // Call the service — it internally uses IHttpContextAccessor
        Console.WriteLine($"Client IP: {_myService.GetUserIP()}");
        return Ok(products);
    }
}
</code></pre>
<h3>HttpContext vs IHttpContextAccessor — Side by Side</h3>
<table>
<thead>
<tr>
<th>HttpContext (in Controller)</th>
<th>IHttpContextAccessor (in Service)</th>
</tr>
</thead>
<tbody><tr>
<td>Available via <code>ControllerBase</code></td>
<td>Injected via constructor</td>
</tr>
<tr>
<td>Use directly: <code>HttpContext.X</code></td>
<td>Use via: <code>_accessor.HttpContext?.X</code></td>
</tr>
<tr>
<td>Always available in controller</td>
<td>May be null outside a request</td>
</tr>
<tr>
<td>No registration needed</td>
<td>Requires <code>AddHttpContextAccessor()</code></td>
</tr>
</tbody></table>
<hr />
<h2>Chapter 3 — IConfiguration</h2>
<h3>What Is IConfiguration?</h3>
<p><code>IConfiguration</code> is ASP.NET Core's built-in way to read settings from <code>appsettings.json</code> (and environment variables, command-line args, etc.). You inject it into your controller or service and then read values using <strong>key paths separated by colons</strong>.</p>
<h3>The appsettings.json File</h3>
<pre><code class="language-json">{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "AppSettings": {
    "AppName": "Products API"
  },
  "OpenApi": {
    "Title": "OpenApi",
    "Version": "v1",
    "BaseUrl": "https://api.openai.com/v1",
    "Advanced": {
      "IncludeRequestingHost": true,
      "IncludeRequestingUser": true,
      "IncludeRequestingUserAgent": true
    }
  }
}
</code></pre>
<h3>Injecting IConfiguration</h3>
<pre><code class="language-csharp">// ProductController.cs
public class ProductController : ControllerBase
{
    private readonly IConfiguration _configuration;   // declare field

    public ProductController(IConfiguration configuration)  // inject
    {
        _configuration = configuration;
    }
}
</code></pre>
<blockquote>
<p>✅ <strong>No Registration Needed</strong></p>
<p>Unlike <code>GetNetworkService</code>, <code>IConfiguration</code> is registered automatically by <code>WebApplication.CreateBuilder(args)</code> — you do NOT need to add anything to <code>Program.cs</code>. Just inject it and use it.</p>
</blockquote>
<h3>Reading Values — Key Paths with Colons</h3>
<p>To navigate nested JSON, separate levels with a colon (<code>:</code>). Think of it like a file path, but with colons instead of slashes.</p>
<pre><code class="language-csharp">// Reading individual values from IConfiguration

// Reads "Products API" from AppSettings &gt; AppName
var appName = _configuration["AppSettings:AppName"];

// Reads "OpenApi" from OpenApi &gt; Title
var title = _configuration["OpenApi:Title"];

// Reads "v1" from OpenApi &gt; Version
var version = _configuration["OpenApi:Version"];

// Reads "true" (as a string!) from OpenApi &gt; Advanced &gt; IncludeRequestingHost
var includeHost = _configuration["OpenApi:Advanced:IncludeRequestingHost"];
</code></pre>
<h3>Iterating Over a Section</h3>
<p>You can read an entire section at once using <code>GetSection()</code>. The code in our <code>ProductController</code> loops over all keys in the <code>OpenApi</code>section:</p>
<pre><code class="language-csharp">// Get all key-value pairs under the "OpenApi" section
foreach (var setting in _configuration.GetSection("OpenApi").AsEnumerable())
{
    if (!string.IsNullOrWhiteSpace(setting.Value))
    {
        Console.WriteLine($"{setting.Key}: {setting.Value}");
    }
}

// Console output:
// OpenApi:Title: OpenApi
// OpenApi:Version: v1
// OpenApi:BaseUrl: https://api.openai.com/v1
// OpenApi:Advanced:IncludeRequestingHost: True
// OpenApi:Advanced:IncludeRequestingUser: True
// OpenApi:Advanced:IncludeRequestingUserAgent: True
</code></pre>
<h3>IConfiguration Key Path Cheatsheet</h3>
<table>
<thead>
<tr>
<th>JSON Path</th>
<th>IConfiguration Key</th>
<th>Returns</th>
</tr>
</thead>
<tbody><tr>
<td><code>AppSettings &gt; AppName</code></td>
<td><code>"AppSettings:AppName"</code></td>
<td><code>"Products API"</code></td>
</tr>
<tr>
<td><code>OpenApi &gt; Title</code></td>
<td><code>"OpenApi:Title"</code></td>
<td><code>"OpenApi"</code></td>
</tr>
<tr>
<td><code>OpenApi &gt; Version</code></td>
<td><code>"OpenApi:Version"</code></td>
<td><code>"v1"</code></td>
</tr>
<tr>
<td><code>OpenApi &gt; Advanced &gt; IncludeRequestingHost</code></td>
<td><code>"OpenApi:Advanced:IncludeRequestingHost"</code></td>
<td><code>"True"</code></td>
</tr>
</tbody></table>
<blockquote>
<p>⚠️ <strong>IConfiguration Always Returns Strings</strong></p>
<p>Even if your JSON value is <code>true</code> (boolean) or <code>42</code> (number), <code>IConfiguration</code> returns it as a string. To get a boolean, use:</p>
<pre><code class="language-csharp">bool flag = _configuration.GetValue&lt;bool&gt;("OpenApi:Advanced:IncludeRequestingHost");
</code></pre>
<p>This is one of the reasons <code>IOptions&lt;T&gt;</code> (Chapter 4) is often preferred.</p>
</blockquote>
<hr />
<h2>Chapter 4 — IOptions</h2>
<h3>The Problem With Raw IConfiguration</h3>
<p>Using <code>IConfiguration</code> works, but has drawbacks: string keys can have typos, values are always strings so you must manually convert types, and there is no IntelliSense. <code>IOptions&lt;T&gt;</code> solves all of these.</p>
<table>
<thead>
<tr>
<th>IConfiguration (raw)</th>
<th>IOptions (strongly typed)</th>
</tr>
</thead>
<tbody><tr>
<td><code>_config["OpenApi:Title"]</code></td>
<td><code>_options.Value.Title</code></td>
</tr>
<tr>
<td>Returns <code>string</code> — must convert</td>
<td>Returns correct type (<code>bool</code>, <code>int</code>…)</td>
</tr>
<tr>
<td>Typos only fail at <strong>runtime</strong></td>
<td>Typos caught at <strong>compile time</strong></td>
</tr>
<tr>
<td>No IntelliSense for keys</td>
<td>Full IntelliSense in IDE</td>
</tr>
<tr>
<td>No registration needed</td>
<td>Requires 2 lines in <code>Program.cs</code></td>
</tr>
</tbody></table>
<h3>Step 1 — Create the Options Classes</h3>
<p>Create a plain C# class that mirrors the shape of your JSON section. Each property name must match the JSON key exactly (case-insensitive).</p>
<pre><code class="language-csharp">// OpenApiOptions.cs
namespace ProductAPI;

public class OpenApiOptions
{
    // SectionName is a constant holding the JSON section key.
    // This avoids 'magic strings' scattered around your code.
    public const string SectionName = "OpenApi";

    // These properties map to OpenApi &gt; Title, Version, BaseUrl in JSON
    public string Title { get; set; } = string.Empty;
    public string Version { get; set; } = string.Empty;
    public string BaseUrl { get; set; } = string.Empty;

    // Nested class maps to the 'Advanced' sub-object
    public OpenApiAdvancedOptions Advanced { get; set; } = new();
}

public class OpenApiAdvancedOptions
{
    // These are booleans — IOptions handles the conversion automatically!
    public bool IncludeRequestingHost { get; set; }
    public bool IncludeRequestingUser { get; set; }
    public bool IncludeRequestingUserAgent { get; set; }
}
</code></pre>
<h3>Step 2 — Register in Program.cs</h3>
<p>Tell ASP.NET Core to bind the <code>"OpenApi"</code> section of <code>appsettings.json</code> to your <code>OpenApiOptions</code> class:</p>
<pre><code class="language-csharp">// Program.cs
var builder = WebApplication.CreateBuilder(args);

// Bind the 'OpenApi' JSON section to OpenApiOptions class
builder.Services.Configure&lt;OpenApiOptions&gt;(
    builder.Configuration.GetSection(OpenApiOptions.SectionName)
);

// Note: OpenApiOptions.SectionName is just the string "OpenApi"
// Using the constant prevents typos.

builder.Services.AddControllers();
var app = builder.Build();
app.Run();
</code></pre>
<h3>Step 3 — Inject IOptions into the Controller</h3>
<pre><code class="language-csharp">// ProductController.cs
using Microsoft.Extensions.Options;     // &lt;-- required using statement

public class ProductController : ControllerBase
{
    private readonly OpenApiOptions _openApiOptions;

    public ProductController(
        IOptions&lt;OpenApiOptions&gt; openApiOptions)  // &lt;-- inject
    {
        _openApiOptions = openApiOptions.Value;   // .Value unwraps the options
    }
}
</code></pre>
<blockquote>
<p>💡 <strong>Why</strong> <code>.Value</code><strong>?</strong></p>
<p><code>IOptions&lt;T&gt;</code> is a wrapper. The actual <code>OpenApiOptions</code> object lives inside <code>.Value</code>. You can either call <code>.Value</code> each time, or store it once in the constructor (as shown above). <strong>Storing it is the recommended pattern.</strong></p>
</blockquote>
<h3>Step 4 — Read the Values</h3>
<pre><code class="language-csharp">// Inside Get(int id) in ProductController.cs

Console.WriteLine($"Title: {_openApiOptions.Title}");
Console.WriteLine($"Version: {_openApiOptions.Version}");
Console.WriteLine($"BaseUrl: {_openApiOptions.BaseUrl}");

// Nested advanced options — full dot-notation access
Console.WriteLine($"IncludeRequestingHost: {_openApiOptions.Advanced.IncludeRequestingHost}");
Console.WriteLine($"IncludeRequestingUser: {_openApiOptions.Advanced.IncludeRequestingUser}");
Console.WriteLine($"IncludeRequestingUserAgent: {_openApiOptions.Advanced.IncludeRequestingUserAgent}");

// Console output:
// Title: OpenApi
// Version: v1
// BaseUrl: https://api.openai.com/v1
// IncludeRequestingHost: True    &lt;-- already a bool, no conversion!
// IncludeRequestingUser: True
// IncludeRequestingUserAgent: True
</code></pre>
<h3>How JSON Maps to C# Class</h3>
<table>
<thead>
<tr>
<th>appsettings.json</th>
<th>C# Property</th>
<th>Type</th>
</tr>
</thead>
<tbody><tr>
<td><code>OpenApi &gt; Title</code></td>
<td><code>OpenApiOptions.Title</code></td>
<td><code>string</code></td>
</tr>
<tr>
<td><code>OpenApi &gt; Version</code></td>
<td><code>OpenApiOptions.Version</code></td>
<td><code>string</code></td>
</tr>
<tr>
<td><code>OpenApi &gt; BaseUrl</code></td>
<td><code>OpenApiOptions.BaseUrl</code></td>
<td><code>string</code></td>
</tr>
<tr>
<td><code>OpenApi &gt; Advanced &gt; IncludeRequestingHost</code></td>
<td><code>OpenApiAdvancedOptions.IncludeRequestingHost</code></td>
<td><code>bool</code></td>
</tr>
<tr>
<td><code>OpenApi &gt; Advanced &gt; IncludeRequestingUser</code></td>
<td><code>OpenApiAdvancedOptions.IncludeRequestingUser</code></td>
<td><code>bool</code></td>
</tr>
<tr>
<td><code>OpenApi &gt; Advanced &gt; IncludeRequestingUserAgent</code></td>
<td><code>OpenApiAdvancedOptions.IncludeRequestingUserAgent</code></td>
<td><code>bool</code></td>
</tr>
</tbody></table>
<hr />
<h2>Chapter 5 — Putting It All Together</h2>
<h3>Complete Program.cs</h3>
<pre><code class="language-csharp">// Program.cs — Complete setup
using ProductAPI;

var builder = WebApplication.CreateBuilder(args);

// ── 1. IHttpContextAccessor ──────────────────────────────────────────
//    Required so GetNetworkService can access HttpContext outside a controller
builder.Services.AddHttpContextAccessor();

// ── 2. Custom Services ───────────────────────────────────────────────
//    Register GetNetworkService with Scoped lifetime
//    (new instance per HTTP request)
builder.Services.AddScoped&lt;GetNetworkService&gt;();

// ── 3. IOptions&lt;T&gt; ───────────────────────────────────────────────────
//    Bind the 'OpenApi' section of appsettings.json to OpenApiOptions
builder.Services.Configure&lt;OpenApiOptions&gt;(
    builder.Configuration.GetSection(OpenApiOptions.SectionName)
);

// ── 4. Standard MVC ──────────────────────────────────────────────────
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();

var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
</code></pre>
<h3>Complete Controller Constructor</h3>
<pre><code class="language-csharp">// ProductController.cs — constructor receives all four dependencies
public class ProductController : ControllerBase
{
    private readonly GetNetworkService _myService;       // uses IHttpContextAccessor internally
    private readonly IConfiguration _configuration;      // raw config access
    private readonly OpenApiOptions _openApiOptions;     // strongly-typed config

    public ProductController(
        GetNetworkService myService,
        IConfiguration configuration,
        IOptions&lt;OpenApiOptions&gt; openApiOptions)
    {
        _myService = myService;
        _configuration = configuration;
        _openApiOptions = openApiOptions.Value;
    }

    // HttpContext is available directly — no constructor injection needed.
}
</code></pre>
<h3>How Everything Connects</h3>
<pre><code class="language-plaintext">HTTP Request arrives
        │
        ▼
ASP.NET Core creates HttpContext
        │
        ▼
DI Container injects:
  ├── IConfiguration          (reads appsettings.json)
  ├── IOptions&lt;OpenApiOptions&gt; (strongly-typed config)
  └── GetNetworkService        (uses IHttpContextAccessor internally)
        │
        ▼
ProductController runs
  ├── Uses HttpContext directly (headers, user, response)
  └── Calls _myService.GetUserIP()
              │
              ▼
        IHttpContextAccessor → HttpContext.Connection.RemoteIpAddress
</code></pre>
<h3>Final Checklist</h3>
<ul>
<li><p>[ ] <strong>Create</strong> <code>OpenApiOptions</code> <strong>class</strong> — match property names to JSON keys exactly</p>
</li>
<li><p>[ ] <strong>Register</strong> <code>IHttpContextAccessor</code> — <code>builder.Services.AddHttpContextAccessor()</code></p>
</li>
<li><p>[ ] <strong>Register</strong> <code>GetNetworkService</code> — <code>builder.Services.AddScoped&lt;GetNetworkService&gt;()</code></p>
</li>
<li><p>[ ] <strong>Register</strong> <code>IOptions&lt;T&gt;</code> — <code>builder.Services.Configure&lt;OpenApiOptions&gt;(...)</code></p>
</li>
<li><p>[ ] <strong>Inject in constructor</strong> — receive <code>IConfiguration</code>, <code>IOptions&lt;T&gt;</code>, <code>GetNetworkService</code></p>
</li>
<li><p>[ ] <strong>Use</strong> <code>HttpContext</code> <strong>directly</strong> — in controller: <code>.Request.Headers</code>, <code>.User.Identity</code>, etc.</p>
</li>
<li><p>[ ] <strong>Call</strong> <code>.Value</code> <strong>on</strong> <code>IOptions&lt;T&gt;</code> — store <code>openApiOptions.Value</code> in a field</p>
</li>
</ul>
<hr />
<h2>Appendix — Quick Reference Cards</h2>
<h3>All Four Concepts at a Glance</h3>
<table>
<thead>
<tr>
<th>Concept</th>
<th>Inject Via</th>
<th>Registration in Program.cs</th>
<th>Use Case</th>
</tr>
</thead>
<tbody><tr>
<td><code>HttpContext</code></td>
<td>Inherited (<code>ControllerBase</code>)</td>
<td>None needed</td>
<td>Headers, user, IP inside controller</td>
</tr>
<tr>
<td><code>IHttpContextAccessor</code></td>
<td>Constructor injection</td>
<td><code>AddHttpContextAccessor()</code></td>
<td><code>HttpContext</code> access in services</td>
</tr>
<tr>
<td><code>IConfiguration</code></td>
<td>Constructor injection</td>
<td>None (auto)</td>
<td>Read raw string values from JSON</td>
</tr>
<tr>
<td><code>IOptions&lt;T&gt;</code></td>
<td><code>IOptions&lt;MyClass&gt;</code></td>
<td><code>Configure&lt;T&gt;(section)</code></td>
<td>Strongly-typed config binding</td>
</tr>
</tbody></table>
<h3>Service Lifetime Cheatsheet</h3>
<table>
<thead>
<tr>
<th>Lifetime</th>
<th>Method</th>
<th>When to Use</th>
</tr>
</thead>
<tbody><tr>
<td>Transient</td>
<td><code>AddTransient&lt;T&gt;()</code></td>
<td>New instance every time the service is requested</td>
</tr>
<tr>
<td>Scoped</td>
<td><code>AddScoped&lt;T&gt;()</code></td>
<td>One instance per HTTP request <em>(most common for web APIs)</em></td>
</tr>
<tr>
<td>Singleton</td>
<td><code>AddSingleton&lt;T&gt;()</code></td>
<td>One instance for the entire application lifetime</td>
</tr>
</tbody></table>
<blockquote>
<p>📌 <strong>Rule of Thumb:</strong> Use <code>AddScoped</code> for most web API services (like <code>GetNetworkService</code>). Use <code>AddSingleton</code> only for stateless, thread-safe services (e.g. caches). Use <code>AddTransient</code> for lightweight, stateless utilities.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[How to Deploy a Django App with PostgreSQL on cPanel: A Beginner's Guide]]></title><description><![CDATA[Deploying a Django application on cPanel shared hosting may look confusing at first, especially when PostgreSQL and Python virtual environments are involved.This guide walks you through each step slowly and clearly, assuming you are a beginner.
We’ll...]]></description><link>https://sudipbhandari.hashnode.dev/how-to-deploy-a-django-app-with-postgresql-on-cpanel-a-beginners-guide</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/how-to-deploy-a-django-app-with-postgresql-on-cpanel-a-beginners-guide</guid><category><![CDATA[cpanel django]]></category><category><![CDATA[Django]]></category><category><![CDATA[cpanel]]></category><category><![CDATA[cPanel hosting]]></category><category><![CDATA[postgres]]></category><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Thu, 22 Jan 2026 15:42:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769096490748/3c19ca4a-2c29-476a-9897-726378435fed.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Deploying a Django application on <strong>cPanel shared hosting</strong> may look confusing at first, especially when PostgreSQL and Python virtual environments are involved.<br />This guide walks you through <strong>each step slowly and clearly</strong>, assuming you are a beginner.</p>
<p>We’ll deploy a Django project named <code>mysite</code> on the domain:</p>
<p><code>bhandarisudip.com.np</code></p>
<h2 id="heading-what-you-need-before-starting">What You Need Before Starting</h2>
<p>Make sure your Django project includes:</p>
<ul>
<li><p><code>manage.py</code></p>
</li>
<li><p><code>requirements.txt</code></p>
</li>
<li><p>A project folder (<code>mysite/</code>) containing:</p>
<ul>
<li><p><code>settings.py</code></p>
</li>
<li><p><code>wsgi.py</code></p>
</li>
</ul>
</li>
<li><p>PostgreSQL support (<code>psycopg2-binary</code> in requirements)</p>
</li>
</ul>
<p>You also need:</p>
<ul>
<li><p>cPanel hosting with <strong>Python App (Passenger)</strong> enabled</p>
</li>
<li><p>A domain already pointing to your hosting server</p>
</li>
</ul>
<hr />
<h2 id="heading-step-1-ssh-setup-amp-project-cloning">Step 1: SSH Setup &amp; Project Cloning</h2>
<p>First, enable <strong>SSH access</strong> in cPanel and connect to your server.</p>
<p>Once SSH is ready, clone your project:</p>
<pre><code class="lang-plaintext">cd /home/USERNAME
git clone YOUR_REPOSITORY_URL mysite
</code></pre>
<blockquote>
<p>If you don’t use Git, you can upload your project as a ZIP file using <strong>cPanel → File Manager</strong> and extract it.</p>
</blockquote>
<hr />
<h2 id="heading-step-2-add-domain-in-cpanel">Step 2: Add Domain in cPanel</h2>
<p>Go to <strong>cPanel → Domains</strong></p>
<ul>
<li><p>Add domain:<br />  <code>bhandarisudip.com.np</code></p>
</li>
<li><p>Set document root (recommended):</p>
</li>
</ul>
<pre><code class="lang-plaintext">/home/USERNAME/bhandarisudip
</code></pre>
<p>✅ Your Django project (<code>mysite</code>) does <strong>not</strong> need to be inside <code>public_html</code>.</p>
<hr />
<h2 id="heading-step-3-upload-project-to-file-manager-if-not-cloned">Step 3: Upload Project to File Manager (if not cloned)</h2>
<p>Open <strong>cPanel → File Manager</strong><br />Upload your Django project to:</p>
<pre><code class="lang-plaintext">/home/USERNAME/mysite
</code></pre>
<p>Confirm these files exist:</p>
<ul>
<li><p><code>manage.py</code></p>
</li>
<li><p><code>mysite/settings.py</code></p>
</li>
<li><p><code>mysite/wsgi.py</code></p>
</li>
</ul>
<hr />
<h2 id="heading-step-4-create-postgresql-database">Step 4: Create PostgreSQL Database</h2>
<p>Go to <strong>cPanel → PostgreSQL Databases</strong></p>
<ol>
<li>Create database:</li>
</ol>
<pre><code class="lang-plaintext">USERNAME_mysite_db
</code></pre>
<ol start="2">
<li>Create user:</li>
</ol>
<pre><code class="lang-plaintext">USERNAME_mysite_user
</code></pre>
<ol start="3">
<li>Assign user to database with <strong>ALL PRIVILEGES</strong></li>
</ol>
<p>Save these details carefully:</p>
<ul>
<li><p>Database name</p>
</li>
<li><p>Username</p>
</li>
<li><p>Password</p>
</li>
<li><p>Host: <code>localhost</code></p>
</li>
<li><p>Port: <code>5432</code></p>
</li>
</ul>
<hr />
<h2 id="heading-step-5-create-python-app-cpanel">Step 5: Create Python App (cPanel)</h2>
<p>Go to <strong>cPanel → Setup Python App → Create Application</strong></p>
<p>Fill in:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Setting</td><td>Value</td></tr>
</thead>
<tbody>
<tr>
<td>Python version</td><td>3.10 or 3.11</td></tr>
<tr>
<td>Application root</td><td><code>/home/USERNAME/mysite</code></td></tr>
<tr>
<td>Application URL</td><td><code>bhandarisudip.com.np</code></td></tr>
<tr>
<td>Startup file</td><td><code>passenger_wsgi.py</code></td></tr>
<tr>
<td>Entry point</td><td><code>application</code></td></tr>
</tbody>
</table>
</div><p>Click <strong>Create</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769096198969/f099bfb3-bb7f-49d1-add6-3e9e4df0e2e2.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-step-6-install-project-dependencies">Step 6: Install Project Dependencies</h2>
<p>Open <strong>Terminal / SSH</strong>:</p>
<pre><code class="lang-plaintext">cd /home/USERNAME/mysite
source /home/USERNAME/virtualenv/mysite/3.11/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
</code></pre>
<p>If PostgreSQL driver is missing:</p>
<pre><code class="lang-plaintext">pip install psycopg2-binary
</code></pre>
<hr />
<h2 id="heading-step-7-update-django-settings-for-production">Step 7: Update Django Settings for Production</h2>
<h3 id="heading-a-allowedhosts">A) ALLOWED_HOSTS</h3>
<p>In <code>settings.py</code>:</p>
<pre><code class="lang-plaintext">ALLOWED_HOSTS = [
    "bhandarisudip.com.np",
    "www.bhandarisudip.com.np"
]
</code></pre>
<hr />
<h3 id="heading-b-postgresql-database-configuration">B) PostgreSQL Database Configuration</h3>
<pre><code class="lang-plaintext">DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": "USERNAME_mysite_db",
        "USER": "USERNAME_mysite_user",
        "PASSWORD": "DB_PASSWORD",
        "HOST": "localhost",
        "PORT": "5432",
    }
}
</code></pre>
<hr />
<h3 id="heading-c-static-amp-media-settings">C) Static &amp; Media Settings</h3>
<pre><code class="lang-plaintext">STATIC_URL = "/static/"
STATIC_ROOT = BASE_DIR / "staticfiles"

MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR / "media"
</code></pre>
<hr />
<h2 id="heading-step-8-create-passengerwsgipy">Step 8: Create <code>passenger_wsgi.py</code></h2>
<p>Inside <code>/home/USERNAME/mysite/</code>, create:</p>
<pre><code class="lang-plaintext">import os
import sys

PROJECT_PATH = "/home/USERNAME/mysite"
if PROJECT_PATH not in sys.path:
    sys.path.insert(0, PROJECT_PATH)

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
</code></pre>
<hr />
<h2 id="heading-step-9-run-migrations-amp-collect-static-files">Step 9: Run Migrations &amp; Collect Static Files</h2>
<pre><code class="lang-plaintext">cd /home/USERNAME/mysite
source /home/USERNAME/virtualenv/mysite/3.11/bin/activate

python manage.py migrate
python manage.py collectstatic
</code></pre>
<hr />
<h2 id="heading-step-10-set-permissions-for-static-amp-media-files">Step 10: Set Permissions for Static &amp; Media Files</h2>
<pre><code class="lang-plaintext">chmod -R 755 /home/USERNAME/mysite/staticfiles
chmod -R 755 /home/USERNAME/mysite/media
</code></pre>
<p>If folders don’t exist:</p>
<pre><code class="lang-plaintext">mkdir -p /home/USERNAME/mysite/staticfiles
mkdir -p /home/USERNAME/mysite/media
</code></pre>
<hr />
<h2 id="heading-step-11-link-static-amp-media-to-domain-root">Step 11: Link Static &amp; Media to Domain Root</h2>
<p>Assuming domain root:</p>
<pre><code class="lang-plaintext">/home/USERNAME/bhandarisudip
</code></pre>
<p>Create symlinks:</p>
<pre><code class="lang-plaintext">ln -s /home/USERNAME/mysite/staticfiles /home/USERNAME/bhandarisudip/static
ln -s /home/USERNAME/mysite/media /home/USERNAME/bhandarisudip/media
</code></pre>
<hr />
<h2 id="heading-step-12-restart-the-python-app">Step 12: Restart the Python App</h2>
<p>In <strong>Setup Python App</strong>, click <strong>Restart</strong></p>
<p>OR via SSH:</p>
<pre><code class="lang-plaintext">mkdir -p /home/USERNAME/mysite/tmp
touch /home/USERNAME/mysite/tmp/restart.txt
</code></pre>
<hr />
<h2 id="heading-common-errors-amp-fixes">Common Errors &amp; Fixes</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Problem</td><td>Solution</td></tr>
</thead>
<tbody>
<tr>
<td>500 Internal Server Error</td><td>Check <code>passenger_wsgi.py</code> and ALLOWED_HOSTS</td></tr>
<tr>
<td>Database connection error</td><td>Verify DB prefix &amp; password</td></tr>
<tr>
<td>Static files not loading</td><td>Run <code>collectstatic</code> and check symlinks</td></tr>
<tr>
<td>Changes not showing</td><td>Restart Python app</td></tr>
</tbody>
</table>
</div><hr />
<h3 id="heading-deployment-complete">✅ Deployment Complete</h3>
<p>Your Django application is now live on:</p>
<p>👉 <a target="_blank" href="https://bhandarisudip.com.np/"><strong>https://bhandarisudip.com.np</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Easy Steps to Create a Maui Blazor Hybrid App Using VS Code]]></title><description><![CDATA[This guide explains how to set up and run .NET MAUI apps on Windows and macOS using Visual Studio Code.

Windows Setup

Install Visual Studio Code

Install .NET SDK 9+

Install the .NET MAUI extension in VS Code

Install the MAUI workload:
 dotnet wo...]]></description><link>https://sudipbhandari.hashnode.dev/easy-steps-to-create-a-maui-blazor-hybrid-app-using-vs-code</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/easy-steps-to-create-a-maui-blazor-hybrid-app-using-vs-code</guid><category><![CDATA[#maui]]></category><category><![CDATA[C#]]></category><category><![CDATA[Blazor]]></category><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Sat, 06 Dec 2025 16:12:25 GMT</pubDate><content:encoded><![CDATA[<p>This guide explains how to set up and run .NET MAUI apps on <strong>Windows</strong> and <strong>macOS</strong> using <strong>Visual Studio Code</strong>.</p>
<hr />
<h2 id="heading-windows-setup">Windows Setup</h2>
<ol>
<li><p>Install <strong>Visual Studio Code</strong></p>
</li>
<li><p>Install <strong>.NET SDK 9+</strong></p>
</li>
<li><p>Install the <strong>.NET MAUI extension</strong> in VS Code</p>
</li>
<li><p>Install the MAUI workload:</p>
<pre><code class="lang-sh"> dotnet workload install maui
</code></pre>
</li>
<li><p>Create a new MAUI Blazor project:</p>
<pre><code class="lang-plaintext"> dotnet new maui-blazor -n YourAppName
</code></pre>
</li>
<li><p>List available workloads:</p>
<pre><code class="lang-plaintext"> dotnet workload search
</code></pre>
</li>
<li><p>Run the app on Windows:</p>
<pre><code class="lang-plaintext"> dotnet run -f net9.0-windows10.0.19041.0
</code></pre>
<h2 id="heading-macos-setup">macOS Setup</h2>
<ol>
<li><p>Install <strong>Visual Studio Code</strong></p>
</li>
<li><p>Install <strong>.NET SDK 9+</strong></p>
</li>
<li><p>Install the <strong>.NET MAUI extension</strong> in VS Code</p>
</li>
<li><p>Install <strong>Xcode</strong> from the App Store</p>
</li>
<li><p>Install the MAUI workload:</p>
<pre><code class="lang-plaintext"> dotnet workload install maui
</code></pre>
</li>
<li><p>Create a new MAUI Blazor project:</p>
<pre><code class="lang-plaintext"> dotnet new maui-blazor -n YourAppName
</code></pre>
</li>
<li><p>List available workloads:</p>
<pre><code class="lang-plaintext"> dotnet workload search
</code></pre>
</li>
<li><p>Run the app on MacCatalyst:</p>
<pre><code class="lang-plaintext"> dotnet build -t:Run -f net9.0-maccatalyst
</code></pre>
</li>
</ol>
</li>
</ol>
<hr />
<h2 id="heading-notes">Notes</h2>
<ul>
<li><p>VS Code supports <strong>building and running</strong>, but not full drag-and-drop MAUI UI design.</p>
</li>
<li><p>Xcode is required on macOS for <strong>MacCatalyst</strong> and <strong>iOS</strong> builds.</p>
</li>
<li><p>Use <code>.NET 9</code> or later for MAUI <code>.net9.0-*</code> targets.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Discover Digital Patro: Your Ultimate Nepali Calendar App]]></title><description><![CDATA[Digital Patro is an innovative, ad-free नेपाली पात्रो﻿(nepali calendar/ nepali patro) app designed for everyone who wants to stay connected with नेपाली मिति﻿(nepali dates), festivals, cultural events, and more. Whether you're planning daily activitie...]]></description><link>https://sudipbhandari.hashnode.dev/discover-digital-patro-your-ultimate-nepali-calendar-app</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/discover-digital-patro-your-ultimate-nepali-calendar-app</guid><category><![CDATA[calendar]]></category><category><![CDATA[#nepalicalendarwidget ]]></category><category><![CDATA[#nepalicalendar ]]></category><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Fri, 31 Oct 2025 06:30:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1761893853537/6272ccaf-3032-4ca4-af7b-91718125469b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://digitalpatroapp.com">Digital Patro</a> is an innovative, ad-free नेपाली पात्रो﻿(nepali calendar/ nepali patro) app designed for everyone who wants to stay connected with नेपाली मिति﻿(nepali dates), festivals, cultural events, and more. Whether you're planning daily activities or special ceremonies, Digital Patro offers an easy-to-use interface with comprehensive calendar tools to meet all your needs.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761892107556/f921f37b-1550-47f2-9066-71d930dd87d3.jpeg" alt class="image--center mx-auto" /></p>
<h2 id="heading-key-features-of-digital-patro">Key Features of Digital Patro</h2>
<ul>
<li><p><strong>Ad-Free Experience</strong><br />  Enjoy a smooth, clean interface without annoying ads for uninterrupted use. Learn more about the ad-free experience on the digital patro’s home page.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761894061052/9889b0c9-e60e-4855-b377-6378a6059abe.jpeg" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Bikram Sambat (BS) &amp; English (AD) Date Formats</strong><br />  Seamlessly switch between बिक्रम सङ्वत (बी एस)﻿ and Gregorian calendars and use the reliable <a target="_blank" href="https://digitalpatroapp.com/date-converter"><strong>date converter</strong></a> tool for accurate conversions.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761894047717/b0e2ff2a-bf2e-4432-ab5b-9b9f3e547813.jpeg" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Daily Weather &amp; Horoscope (Rashifal)</strong><br />  Stay updated with the latest weather and get your daily, monthly, and yearly राशिफल﻿ on the dedicated <a target="_blank" href="https://digitalpatroapp.com/horoscope/daily-horoscope"><strong>horoscope page</strong></a>.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761894022425/5f0a5859-326c-4be8-878b-b46be75aa511.jpeg" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>National and International Events</strong><br />  Access detailed information about major national and international public holidays and cultural events on the <a target="_blank" href="https://digitalpatroapp.com/events"><strong>events page</strong></a>.</p>
</li>
<li><p><strong>Offline Access &amp; Clean UI</strong><br />  Use Digital Patro anytime without internet, thanks to its offline feature on the web, all within a neat and modern design available on both iOS and Android platforms. Download from <a target="_blank" href="https://apps.apple.com/app/digital-patro-nepali-calendar/6747698614"><strong>App Store</strong></a> or <a target="_blank" href="https://play.google.com/store/apps/details?id=com.rudrakx.calendar&amp;pcampaignid=web_share"><strong>Google Play</strong></a>.</p>
</li>
<li><p><strong>Forex Rates</strong><br />  Keep track of the latest foreign exchange rates conveniently via the <a target="_blank" href="https://digitalpatroapp.com/forex"><strong>forex page</strong></a>.</p>
</li>
<li><p><strong>Social Post Generator</strong><br />  Easily create festival-wise and special occasion social media posts using the <a target="_blank" href="https://digitalpatroapp.com/posts-generator"><strong>posts generator</strong></a>, including birthday greetings and congratulations.</p>
</li>
</ul>
<h2 id="heading-why-choose-digital-patro">Why Choose Digital Patro?</h2>
<p>Digital Patro offers a distraction-free, reliable, and culturally rich नेपाली पात्रो﻿ experience with features tailored for both modern and traditional users. It helps you plan important ceremonies with detailed Panchang and auspicious dates and never miss a festival or event with customizable reminders and notifications.</p>
]]></content:encoded></item><item><title><![CDATA[How to Create a WebSocket in ASP.NET Using .NET 8]]></title><description><![CDATA[Add WebSocket Middleware
In .NET 8, middleware configuration can stay outside Program.cs if you organize it into dedicated classes or handlers.
Let’s write a WebSocketHandler class.
📄 WebSocketHandler.cs
using System.Net.WebSockets;
using System.Tex...]]></description><link>https://sudipbhandari.hashnode.dev/how-to-create-a-websocket-in-aspnet-using-net-8</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/how-to-create-a-websocket-in-aspnet-using-net-8</guid><category><![CDATA[web sockets]]></category><category><![CDATA[socket]]></category><category><![CDATA[ASP.NET]]></category><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Fri, 09 May 2025 02:07:09 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-add-websocket-middleware">Add WebSocket Middleware</h2>
<p>In <code>.NET 8</code>, middleware configuration can stay outside <code>Program.cs</code> if you organize it into dedicated classes or handlers.</p>
<p>Let’s write a <strong>WebSocketHandler</strong> class.</p>
<h3 id="heading-websockethandlercs">📄 <code>WebSocketHandler.cs</code></h3>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System.Net.WebSockets;
<span class="hljs-keyword">using</span> System.Text;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">WebSocketDemo</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">WebSocketHandler</span>
    {
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">HandleAsync</span>(<span class="hljs-params">WebSocket webSocket, CancellationToken cancellationToken</span>)</span>
        {
            Console.WriteLine(<span class="hljs-string">"WebSocket connection established"</span>);

            <span class="hljs-keyword">var</span> sendTask = SendPeriodicMessagesAsync(webSocket, cancellationToken);
            <span class="hljs-keyword">var</span> receiveTask = ReceiveMessagesAsync(webSocket, cancellationToken);

            <span class="hljs-keyword">await</span> Task.WhenAny(sendTask, receiveTask);
        }

        <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">SendPeriodicMessagesAsync</span>(<span class="hljs-params">WebSocket webSocket, CancellationToken cancellationToken</span>)</span>
        {
            <span class="hljs-keyword">while</span> (!cancellationToken.IsCancellationRequested &amp;&amp; webSocket.State == WebSocketState.Open)
            {
                <span class="hljs-keyword">var</span> message = <span class="hljs-string">"Hello"</span>;
                <span class="hljs-keyword">var</span> buffer = Encoding.UTF8.GetBytes(message);

                <span class="hljs-keyword">await</span> webSocket.SendAsync(
                    <span class="hljs-keyword">new</span> ArraySegment&lt;<span class="hljs-keyword">byte</span>&gt;(buffer),
                    WebSocketMessageType.Text,
                    <span class="hljs-literal">true</span>,
                    cancellationToken
                );

                Console.WriteLine(<span class="hljs-string">$"Sent: <span class="hljs-subst">{message}</span>"</span>);

                <span class="hljs-keyword">try</span>
                {
                    <span class="hljs-keyword">await</span> Task.Delay(TimeSpan.FromMinutes(<span class="hljs-number">1</span>), cancellationToken);
                }
                <span class="hljs-keyword">catch</span> (TaskCanceledException)
                {
                    <span class="hljs-keyword">break</span>;
                }
            }
        }

        <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">ReceiveMessagesAsync</span>(<span class="hljs-params">WebSocket webSocket, CancellationToken cancellationToken</span>)</span>
        {
            <span class="hljs-keyword">var</span> buffer = <span class="hljs-keyword">new</span> <span class="hljs-keyword">byte</span>[<span class="hljs-number">1024</span> * <span class="hljs-number">4</span>];

            <span class="hljs-keyword">while</span> (!cancellationToken.IsCancellationRequested &amp;&amp; webSocket.State == WebSocketState.Open)
            {
                <span class="hljs-keyword">var</span> result = <span class="hljs-keyword">await</span> webSocket.ReceiveAsync(<span class="hljs-keyword">new</span> ArraySegment&lt;<span class="hljs-keyword">byte</span>&gt;(buffer), cancellationToken);

                <span class="hljs-keyword">if</span> (result.MessageType == WebSocketMessageType.Close)
                {
                    Console.WriteLine(<span class="hljs-string">"Client requested close"</span>);
                    <span class="hljs-keyword">await</span> webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, <span class="hljs-string">"Closing"</span>, cancellationToken);
                    <span class="hljs-keyword">break</span>;
                }
            }
        }
    }
}
</code></pre>
<p>Configure WebSockets in Program.cs</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> builder = WebApplication.CreateBuilder(args);
<span class="hljs-keyword">var</span> app = builder.Build();

app.UseWebSockets();

<span class="hljs-keyword">var</span> webSocketHandler = <span class="hljs-keyword">new</span> WebSocketHandler();

app.Map(<span class="hljs-string">"/ws"</span>, <span class="hljs-keyword">async</span> context =&gt;
{
    <span class="hljs-keyword">if</span> (context.WebSockets.IsWebSocketRequest)
    {
        <span class="hljs-keyword">var</span> webSocket = <span class="hljs-keyword">await</span> context.WebSockets.AcceptWebSocketAsync();
        <span class="hljs-keyword">await</span> webSocketHandler.HandleAsync(webSocket, context.RequestAborted);
    }
    <span class="hljs-keyword">else</span>
    {
        context.Response.StatusCode = <span class="hljs-number">400</span>;
    }
});

app.Run();
</code></pre>
<p>Create a Frontend to Connect<br />Let’s create a simple HTML file</p>
<pre><code class="lang-csharp">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;WebSocket Client&lt;/title&gt;
    &lt;style&gt;
        <span class="hljs-meta">#socket_box {</span>
            width: <span class="hljs-number">400</span>px;
            height: <span class="hljs-number">300</span>px;
            border: <span class="hljs-number">1</span>px solid <span class="hljs-meta">#ccc;</span>
            padding: <span class="hljs-number">10</span>px;
            overflow-y: auto;
            font-family: sans-serif;
        }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;WebSocket Messages&lt;/h1&gt;
    &lt;div id=<span class="hljs-string">"socket_box"</span>&gt;&lt;/div&gt;

    &lt;script&gt;
        <span class="hljs-keyword">const</span> ws = <span class="hljs-keyword">new</span> WebSocket(<span class="hljs-string">'wss://localhost:5001/ws'</span>);

        ws.onopen = () =&gt; {
            console.log(<span class="hljs-string">'WebSocket connected'</span>);
        };

        ws.onmessage = (<span class="hljs-keyword">event</span>) =&gt; {
            <span class="hljs-keyword">const</span> box = document.getElementById(<span class="hljs-string">'socket_box'</span>);
            <span class="hljs-keyword">const</span> msg = document.createElement(<span class="hljs-string">'div'</span>);
            msg.textContent = <span class="hljs-keyword">event</span>.data + <span class="hljs-string">' at '</span> + <span class="hljs-keyword">new</span> Date().toLocaleTimeString();
            box.appendChild(msg);
            box.scrollTop = box.scrollHeight;
        };

        ws.onclose = () =&gt; {
            console.log(<span class="hljs-string">'WebSocket closed'</span>);
        };
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
]]></content:encoded></item><item><title><![CDATA[How to Upload Images Using ASP.NET Web API]]></title><description><![CDATA[Step 1: Create a CreateProductDto
First, create a DTO (Data Transfer Object) that represents the product data along with the images:
public class CreateProductDto
{
    public string Name { get; set; }
    public decimal Price { get; set; }
    publi...]]></description><link>https://sudipbhandari.hashnode.dev/how-to-upload-images-using-aspnet-web-api</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/how-to-upload-images-using-aspnet-web-api</guid><category><![CDATA[ IFormFile]]></category><category><![CDATA[wwwroot]]></category><category><![CDATA[Aspnetcore]]></category><category><![CDATA[Web API]]></category><category><![CDATA[image upload]]></category><category><![CDATA[File Upload]]></category><category><![CDATA[multipart/form-data]]></category><category><![CDATA[dotnet, ASP.NET Core, Minimal APIs, Route Parameters, RESTful API, Web Development]]></category><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Sun, 27 Apr 2025 02:46:17 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-step-1-create-a-createproductdto">Step 1: Create a <code>CreateProductDto</code></h2>
<p>First, create a <strong>DTO (Data Transfer Object)</strong> that represents the product data along with the images:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">CreateProductDto</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Name { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">decimal</span> Price { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span>? Description { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> CategoryId { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> List&lt;IFormFile&gt; Images { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}
</code></pre>
<p>Here, <code>IFormFile</code> is used to receive uploaded files via <strong>HTTP multipart form-data</strong>.</p>
<h2 id="heading-ia"> </h2>
<p>Step 2: Create the <code>CreateProduct</code> API Endpoint</p>
<p>Now, create a <code>POST</code> API method to handle incoming product data and image uploads:</p>
<pre><code class="lang-csharp">[<span class="hljs-meta">HttpPost</span>]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;ActionResult&lt;ProductDto&gt;&gt; CreateProduct([FromForm] CreateProductDto createDto)
{
    <span class="hljs-keyword">var</span> uploadedImageUrls = <span class="hljs-keyword">new</span> List&lt;<span class="hljs-keyword">string</span>&gt;();

    <span class="hljs-keyword">if</span> (createDto.Images != <span class="hljs-literal">null</span> &amp;&amp; createDto.Images.Any())
    {
        <span class="hljs-keyword">var</span> uploadsFolder = Path.Combine(Directory.GetCurrentDirectory(), <span class="hljs-string">"wwwroot/uploads/products"</span>);

        <span class="hljs-keyword">if</span> (!Directory.Exists(uploadsFolder))
        {
            Directory.CreateDirectory(uploadsFolder);
        }

        <span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> image <span class="hljs-keyword">in</span> createDto.Images)
        {
            <span class="hljs-keyword">var</span> extension = Path.GetExtension(image.FileName);
            <span class="hljs-keyword">var</span> newFileName = <span class="hljs-string">$"<span class="hljs-subst">{Guid.NewGuid()}</span><span class="hljs-subst">{extension}</span>"</span>;
            <span class="hljs-keyword">var</span> filePath = Path.Combine(uploadsFolder, newFileName);

            <span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> stream = <span class="hljs-keyword">new</span> FileStream(filePath, FileMode.Create))
            {
                <span class="hljs-keyword">await</span> image.CopyToAsync(stream);
            }

            <span class="hljs-comment">// Store relative URL for frontend usage</span>
            uploadedImageUrls.Add(<span class="hljs-string">$"/uploads/products/<span class="hljs-subst">{newFileName}</span>"</span>);
        }
    }

    <span class="hljs-keyword">var</span> product = <span class="hljs-keyword">new</span> Product
    {
        Name = createDto.Name,
        Price = createDto.Price,
        Description = createDto.Description,
        CategoryId = createDto.CategoryId,
        Images = uploadedImageUrls.Select(url =&gt; <span class="hljs-keyword">new</span> ProductImage
        {
            ImageUrl = url
        }).ToList()
    };

    _context.Products.Add(product);
    <span class="hljs-keyword">await</span> _context.SaveChangesAsync();

    <span class="hljs-keyword">return</span> CreatedAtAction(<span class="hljs-keyword">nameof</span>(GetProduct), <span class="hljs-keyword">new</span> { id = product.Id }, product);
}
</code></pre>
<h2 id="heading-how-it-works">How It Works:</h2>
<ul>
<li><p><code>[FromForm]</code> binding is used because <strong>files must be posted as form-data</strong>, not JSON.</p>
</li>
<li><p>The API saves each uploaded image to <code>wwwroot/uploads/products</code>.</p>
</li>
<li><p>A <strong>new filename</strong> is generated using <code>Guid.NewGuid()</code> to avoid name collisions.</p>
</li>
<li><p>The server <strong>stores the relative URL</strong> (like <code>/uploads/products/xyz.jpg</code>) for each image.</p>
</li>
<li><p>All product details (including images) are finally saved into the database.</p>
</li>
</ul>
<h2 id="heading-important-tips">Important Tips</h2>
<ul>
<li><p>✅ <strong>Create wwwroot/uploads/products</strong> folder manually or ensure it's auto-created in code (we handle it above).</p>
</li>
<li><p>✅ <strong>Configure</strong> <code>Startup.cs</code> / <code>Program.cs</code> (depending on your .NET version) to serve static files:</p>
<pre><code class="lang-csharp">  app.UseStaticFiles();
</code></pre>
</li>
<li><p>✅ <strong>Limit the allowed file types</strong> (e.g., only <code>.jpg</code>, <code>.png</code>) and <strong>size</strong> if needed for security.</p>
</li>
<li><p>✅ <strong>Handle errors</strong> gracefully (e.g., invalid files, large uploads).</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Implementing Google OAuth in ASP.NET Web API]]></title><description><![CDATA[1. Setting Up Google OAuth Credentials
Before writing any code, you need to set up a project in the Google Cloud Console:

Go to the Google Cloud Console

Create a new project or select an existing one

Navigate to "APIs & Services" > "Credentials"

...]]></description><link>https://sudipbhandari.hashnode.dev/implementing-google-oauth-in-aspnet-web-api</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/implementing-google-oauth-in-aspnet-web-api</guid><category><![CDATA[oauth using asp.net]]></category><category><![CDATA[google auth]]></category><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Sat, 19 Apr 2025 16:52:50 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-1-setting-up-google-oauth-credentials">1. Setting Up Google OAuth Credentials</h2>
<p>Before writing any code, you need to set up a project in the Google Cloud Console:</p>
<ol>
<li><p>Go to the <a target="_blank" href="https://console.cloud.google.com/">Google Cloud Console</a></p>
</li>
<li><p>Create a new project or select an existing one</p>
</li>
<li><p>Navigate to "APIs &amp; Services" &gt; "Credentials"</p>
</li>
<li><p>Click "Create Credentials" and select "OAuth client ID"</p>
</li>
<li><p>Configure the OAuth consent screen with your application details</p>
</li>
<li><p>For application type, select "Web application"</p>
</li>
<li><p>Add authorized JavaScript origins (e.g., <code>http://localhost:7276</code> for development)</p>
</li>
<li><p>Add authorized redirect URIs</p>
</li>
<li><p>Create the client ID and note your Client ID and Client Secret</p>
</li>
</ol>
<h2 id="heading-2-configuring-your-aspnethttpaspnet-core-application">2. Configuring Your <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core Application</h2>
<p>Add the necessary NuGet packages to your project:</p>
<pre><code class="lang-csharp">dotnet <span class="hljs-keyword">add</span> package Google.Apis.Auth
dotnet <span class="hljs-keyword">add</span> package Microsoft.AspNetCore.Identity
dotnet <span class="hljs-keyword">add</span> package Microsoft.AspNetCore.Authentication.JwtBearer
</code></pre>
<p>Update your <code>appsettings.json</code> file with the Google OAuth configuration:</p>
<pre><code class="lang-csharp">{
  <span class="hljs-string">"Google"</span>: {
    <span class="hljs-string">"ClientId"</span>: <span class="hljs-string">"YOUR_GOOGLE_CLIENT_ID"</span>,
    <span class="hljs-string">"ClientSecret"</span>: <span class="hljs-string">"YOUR_GOOGLE_CLIENT_SECRET"</span>
  },
  <span class="hljs-string">"JwtConfig"</span>: {
    <span class="hljs-string">"Secret"</span>: <span class="hljs-string">"YOUR_SECURE_JWT_SECRET_KEY"</span>,
    <span class="hljs-string">"Issuer"</span>: <span class="hljs-string">"YourAppName"</span>,
    <span class="hljs-string">"Audience"</span>: <span class="hljs-string">"YourAppUsers"</span>,
    <span class="hljs-string">"ExpiryInMinutes"</span>: <span class="hljs-number">60</span>
  }
}
</code></pre>
<h2 id="heading-3-the-token-service-implementation">3. The Token Service Implementation</h2>
<p>The token service is responsible for generating JWT tokens for authenticated users:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TokenService</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> IConfiguration _configuration;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> UserManager&lt;ApplicationUser&gt; _userManager;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">TokenService</span>(<span class="hljs-params">IConfiguration configuration, UserManager&lt;ApplicationUser&gt; userManager</span>)</span>
    {
        _configuration = configuration;
        _userManager = userManager;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;<span class="hljs-keyword">string</span>&gt; <span class="hljs-title">GenerateToken</span>(<span class="hljs-params">ApplicationUser user</span>)</span>
    {
        <span class="hljs-keyword">var</span> jwtTokenHandler = <span class="hljs-keyword">new</span> JwtSecurityTokenHandler();
        <span class="hljs-keyword">var</span> key = Encoding.ASCII.GetBytes(_configuration[<span class="hljs-string">"JwtConfig:Secret"</span>]);
        <span class="hljs-keyword">var</span> roles = <span class="hljs-keyword">await</span> _userManager.GetRolesAsync(user);

        <span class="hljs-comment">// Create claims for the token</span>
        <span class="hljs-keyword">var</span> claims = <span class="hljs-keyword">new</span> List&lt;Claim&gt;
        {
            <span class="hljs-keyword">new</span> Claim(ClaimTypes.NameIdentifier, user.Id),
            <span class="hljs-keyword">new</span> Claim(JwtRegisteredClaimNames.Sub, user.UserName),
            <span class="hljs-keyword">new</span> Claim(JwtRegisteredClaimNames.Email, user.Email),
            <span class="hljs-keyword">new</span> Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
        };

        <span class="hljs-comment">// Add role claims</span>
        <span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> role <span class="hljs-keyword">in</span> roles)
        {
            claims.Add(<span class="hljs-keyword">new</span> Claim(ClaimTypes.Role, role));
        }

        <span class="hljs-comment">// Create token descriptor</span>
        <span class="hljs-keyword">var</span> now = DateTime.UtcNow;
        <span class="hljs-keyword">var</span> expires = now.AddMinutes(Convert.ToDouble(_configuration[<span class="hljs-string">"JwtConfig:ExpiryInMinutes"</span>] ?? <span class="hljs-string">"60"</span>));

        <span class="hljs-keyword">var</span> tokenDescriptor = <span class="hljs-keyword">new</span> SecurityTokenDescriptor
        {
            Subject = <span class="hljs-keyword">new</span> ClaimsIdentity(claims),
            NotBefore = now,
            Expires = expires,
            SigningCredentials = <span class="hljs-keyword">new</span> SigningCredentials(
                <span class="hljs-keyword">new</span> SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
            Issuer = _configuration[<span class="hljs-string">"JwtConfig:Issuer"</span>] ?? <span class="hljs-string">"DefaultIssuer"</span>,
            Audience = _configuration[<span class="hljs-string">"JwtConfig:Audience"</span>] ?? <span class="hljs-string">"DefaultAudience"</span>
        };

        <span class="hljs-keyword">var</span> token = jwtTokenHandler.CreateToken(tokenDescriptor);
        <span class="hljs-keyword">return</span> jwtTokenHandler.WriteToken(token);
    }
}
</code></pre>
<h2 id="heading-4-the-authentication-controller">4. The Authentication Controller</h2>
<p>Next, implement the controller that handles Google authentication:</p>
<pre><code class="lang-csharp">[<span class="hljs-meta">Route(<span class="hljs-meta-string">"api/[controller]"</span>)</span>]
[<span class="hljs-meta">ApiController</span>]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">AuthController</span> : <span class="hljs-title">ControllerBase</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> UserManager&lt;ApplicationUser&gt; _userManager;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> RoleManager&lt;IdentityRole&gt; _roleManager;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> IConfiguration _configuration;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> TokenService _tokenService;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">AuthController</span>(<span class="hljs-params">
        UserManager&lt;ApplicationUser&gt; userManager,
        RoleManager&lt;IdentityRole&gt; roleManager,
        IConfiguration configuration,
        TokenService tokenService</span>)</span>
    {
        _userManager = userManager;
        _roleManager = roleManager;
        _configuration = configuration;
        _tokenService = tokenService;
    }

    [<span class="hljs-meta">HttpPost(<span class="hljs-meta-string">"google-login"</span>)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;IActionResult&gt; <span class="hljs-title">GoogleLogin</span>(<span class="hljs-params">[FromBody] GoogleLoginDTO model</span>)</span>
    {
        <span class="hljs-comment">// Validate request</span>
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">string</span>.IsNullOrEmpty(model.IdToken))
        {
            <span class="hljs-keyword">return</span> BadRequest(<span class="hljs-keyword">new</span> AuthResponseDto
            {
                IsSuccess = <span class="hljs-literal">false</span>,
                Message = <span class="hljs-string">"Google token is required"</span>
            });
        }

        <span class="hljs-keyword">try</span>
        {
            <span class="hljs-comment">// Validate Google token</span>
            <span class="hljs-keyword">var</span> payload = <span class="hljs-keyword">await</span> GoogleJsonWebSignature.ValidateAsync(
                model.IdToken,
                <span class="hljs-keyword">new</span> GoogleJsonWebSignature.ValidationSettings
                {
                    Audience = <span class="hljs-keyword">new</span>[] { _configuration[<span class="hljs-string">"Google:ClientId"</span>] }
                });

            <span class="hljs-comment">// Check if user exists</span>
            <span class="hljs-keyword">var</span> user = <span class="hljs-keyword">await</span> _userManager.FindByEmailAsync(payload.Email);
            <span class="hljs-keyword">if</span> (user == <span class="hljs-literal">null</span>)
            {
                <span class="hljs-comment">// Create new user if doesn't exist</span>
                user = <span class="hljs-keyword">new</span> ApplicationUser
                {
                    UserName = payload.Email,
                    Email = payload.Email,
                    EmailConfirmed = <span class="hljs-literal">true</span>,
                    SecurityStamp = Guid.NewGuid().ToString()
                };
                <span class="hljs-keyword">var</span> createResult = <span class="hljs-keyword">await</span> _userManager.CreateAsync(user);
                <span class="hljs-keyword">if</span> (!createResult.Succeeded)
                {
                    <span class="hljs-keyword">return</span> BadRequest(<span class="hljs-keyword">new</span> AuthResponseDto
                    {
                        IsSuccess = <span class="hljs-literal">false</span>,
                        Message = <span class="hljs-string">"User creation failed: "</span> +
                            <span class="hljs-keyword">string</span>.Join(<span class="hljs-string">", "</span>, createResult.Errors.Select(e =&gt; e.Description))
                    });
                }

                <span class="hljs-comment">// Ensure Customer role exists</span>
                <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">await</span> _roleManager.RoleExistsAsync(<span class="hljs-string">"Customer"</span>))
                {
                    <span class="hljs-keyword">await</span> _roleManager.CreateAsync(<span class="hljs-keyword">new</span> IdentityRole(<span class="hljs-string">"Customer"</span>));
                }

                <span class="hljs-comment">// Add to Customer role</span>
                <span class="hljs-keyword">var</span> roleResult = <span class="hljs-keyword">await</span> _userManager.AddToRoleAsync(user, <span class="hljs-string">"Customer"</span>);
                <span class="hljs-keyword">if</span> (!roleResult.Succeeded)
                {
                    <span class="hljs-keyword">return</span> BadRequest(<span class="hljs-keyword">new</span> AuthResponseDto
                    {
                        IsSuccess = <span class="hljs-literal">false</span>,
                        Message = <span class="hljs-string">"Failed to assign role: "</span> +
                            <span class="hljs-keyword">string</span>.Join(<span class="hljs-string">", "</span>, roleResult.Errors.Select(e =&gt; e.Description))
                    });
                }
            }

            <span class="hljs-comment">// Generate JWT token</span>
            <span class="hljs-keyword">var</span> token = <span class="hljs-keyword">await</span> _tokenService.GenerateToken(user);
            <span class="hljs-keyword">var</span> roles = <span class="hljs-keyword">await</span> _userManager.GetRolesAsync(user);

            <span class="hljs-keyword">return</span> Ok(<span class="hljs-keyword">new</span> AuthResponseDto
            {
                IsSuccess = <span class="hljs-literal">true</span>,
                Token = token,
                UserName = user.UserName,
                Email = user.Email,
                Message = <span class="hljs-string">"Google login successful"</span>,
                Roles = roles.ToList()
            });
        }
        <span class="hljs-keyword">catch</span> (Exception ex)
        {
            <span class="hljs-keyword">return</span> BadRequest(<span class="hljs-keyword">new</span> AuthResponseDto
            {
                IsSuccess = <span class="hljs-literal">false</span>,
                Message = <span class="hljs-string">$"Authentication failed: <span class="hljs-subst">{ex.Message}</span>"</span>
            });
        }
    }
}
</code></pre>
<h2 id="heading-5-data-transfer-objects-dtos">5. Data Transfer Objects (DTOs)</h2>
<p>Create the necessary DTOs for handling requests and responses:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">GoogleLoginDTO</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> IdToken { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">AuthResponseDto</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span> IsSuccess { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Message { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Token { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> UserName { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Email { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> List&lt;<span class="hljs-keyword">string</span>&gt; Roles { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}
</code></pre>
<h2 id="heading-6-frontend-implementation">6. Frontend Implementation</h2>
<p>Here's a simple HTML page with JavaScript to implement Google Sign-In:</p>
<p>Create a <em>wwwroot folder</em> and root and add <em>index.html</em></p>
<pre><code class="lang-csharp">html&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Google OAuth&lt;/title&gt;
    &lt;script src=<span class="hljs-string">"https://accounts.google.com/gsi/client"</span> <span class="hljs-keyword">async</span> defer&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;Login with Google&lt;/h1&gt;
    &lt;div id=<span class="hljs-string">"g_id_onload"</span>
         data-client_id=<span class="hljs-string">"YOUR_GOOGLE_CLIENT_ID"</span>
         data-callback=<span class="hljs-string">"handleGoogleResponse"</span>
         data-auto_prompt=<span class="hljs-string">"false"</span>&gt;
    &lt;/div&gt;
    &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"g_id_signin"</span>
         data-type=<span class="hljs-string">"standard"</span>
         data-size=<span class="hljs-string">"large"</span>
         data-theme=<span class="hljs-string">"outline"</span>
         data-text=<span class="hljs-string">"sign_in_with"</span>
         data-shape=<span class="hljs-string">"rectangular"</span>
         data-logo_alignment=<span class="hljs-string">"left"</span>&gt;
    &lt;/div&gt;
    &lt;script&gt;
        <span class="hljs-function">function <span class="hljs-title">handleGoogleResponse</span>(<span class="hljs-params">response</span>)</span> {
            console.log(<span class="hljs-string">"Google response received"</span>);
            <span class="hljs-comment">// Send the ID token to your backend</span>
            fetch(<span class="hljs-string">'/api/auth/google-login'</span>, {
                method: <span class="hljs-string">'POST'</span>,
                headers: {
                    <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
                },
                body: JSON.stringify({ idToken: response.credential })
            })
            .then(response =&gt; response.json())
            .then(data =&gt; {
                console.log(<span class="hljs-string">'Success:'</span>, data);
                <span class="hljs-keyword">if</span> (data.isSuccess) {
                    <span class="hljs-comment">// Store the JWT token</span>
                    localStorage.setItem(<span class="hljs-string">'jwt'</span>, data.token);
                    <span class="hljs-comment">// Redirect or update UI as needed</span>
                    alert(<span class="hljs-string">'Login successful!'</span>);
                } <span class="hljs-keyword">else</span> {
                    alert(<span class="hljs-string">'Login failed: '</span> + data.message);
                }
            })
            .<span class="hljs-keyword">catch</span>(error =&gt; {
                console.error(<span class="hljs-string">'Error:'</span>, error);
                alert(<span class="hljs-string">'Login failed'</span>);
            });
        }
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>To use static files on your project add <strong><em>app.UseStaticFiles()</em></strong>; before <strong><em>app.run();</em></strong><br /><strong><em>Github:</em></strong> <a target="_blank" href="https://github.com/sudipbhr/asp.net-web-api-auth">https://github.com/sudipbhr/asp.net-web-api-auth</a></p>
]]></content:encoded></item><item><title><![CDATA[How to Build a Login and Registration API with ASP.NET Web API]]></title><description><![CDATA[Authentication is a critical part of any modern web application. In this tutorial, we'll walk you through implementing a secure JWT (JSON Web Token) authentication system in an ASP.NET Core Web API project. We'll use Entity Framework Core with Postgr...]]></description><link>https://sudipbhandari.hashnode.dev/how-to-build-a-login-and-registration-api-with-aspnet-web-api</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/how-to-build-a-login-and-registration-api-with-aspnet-web-api</guid><category><![CDATA[jwt authentication asp.net]]></category><category><![CDATA[asp.net core]]></category><category><![CDATA[authentication]]></category><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Mon, 14 Apr 2025 17:47:12 GMT</pubDate><content:encoded><![CDATA[<p>Authentication is a critical part of any modern web application. In this tutorial, we'll walk you through implementing a secure JWT (JSON Web Token) authentication system in an <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core Web API project. We'll use Entity Framework Core with PostgreSQL and <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core Identity for user management.</p>
<h2 id="heading-what-well-build">What We'll Build</h2>
<p>By the end of this tutorial, you'll have:</p>
<ol>
<li><p>A complete authentication system with registration and login endpoints</p>
</li>
<li><p>JWT token generation and validation</p>
</li>
<li><p>Role-based authorization</p>
</li>
<li><p>Protected API endpoints</p>
</li>
</ol>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li><p>.NET 6.0 or higher</p>
</li>
<li><p>Basic understanding of <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core</p>
</li>
<li><p>PostgreSQL database (or you can adapt to another DB provider)</p>
</li>
<li><p>Visual Studio or VS Code</p>
</li>
</ul>
<h2 id="heading-project-setup">Project Setup</h2>
<p>Let's start by setting up our project structure. We'll need the following components:</p>
<ol>
<li><p>Models for authentication</p>
</li>
<li><p>DbContext for Entity Framework Core</p>
</li>
<li><p>Token generation service</p>
</li>
<li><p>Authentication controllers</p>
</li>
<li><p>Protected API endpoints</p>
</li>
</ol>
<h2 id="heading-required-packages">Required Packages</h2>
<p>Install following required packages</p>
<ol>
<li><p>Microsoft.EntityFrameworkCore.Tools</p>
</li>
<li><p>Microsoft.AspNetCore.Identity</p>
</li>
<li><p>Microsoft.AspNetCore.Authentication.JwtBearer</p>
</li>
</ol>
<h2 id="heading-step-1-setting-up-the-user-model-and-dtos">Step 1: Setting Up the User Model and DTOs</h2>
<p>First, let's create our user model by extending the IdentityUser class from <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core Identity:<br /><strong><em>Models/ApplicationUser.cs</em></strong></p>
<pre><code class="lang-csharp"><span class="hljs-comment">// ApplicationUser.cs</span>
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Identity;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">Ecommerce.Models</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ApplicationUser</span>: <span class="hljs-title">IdentityUser</span>
    {
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> MobileNumber { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Address { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    }
}
</code></pre>
<p>Run migrations and update database:</p>
<p>Go to package manager console :<br /><em>1. add-migration “updated user module”<br />2. update-database</em></p>
<p>Next, we'll need DTOs (Data Transfer Objects) for registration and login:<br />Create a Folder name <strong><em>DTOs/Auth/</em></strong></p>
<pre><code class="lang-csharp"><span class="hljs-comment">//  DTOs/Auth/RegisterDto.cs</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">RegisterDto</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Email { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> UserName { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Password { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> MobileNumber { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Address { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}
</code></pre>
<pre><code class="lang-csharp"><span class="hljs-comment">//  DTOs/Auth/LoginDto.cs</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">LoginDto</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> UserName { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Password { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}
</code></pre>
<pre><code class="lang-csharp">
<span class="hljs-comment">//  DTOs/Auth/AuthResponseDto.cs</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">AuthResponseDto</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span> IsSuccess { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Message { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Token { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> UserName { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Email { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> List&lt;<span class="hljs-keyword">string</span>&gt; Roles { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}
</code></pre>
<h2 id="heading-step-2-setting-up-the-database-context">Step 2: Setting Up the Database Context</h2>
<p>Next, we need to create our database context:</p>
<pre><code class="lang-csharp"><span class="hljs-comment">// Data/ApplicationDbContext.cs</span>
<span class="hljs-keyword">using</span> Ecommerce.Models;
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Identity.EntityFrameworkCore;
<span class="hljs-keyword">using</span> Microsoft.EntityFrameworkCore;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">Ecommerce.Data</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ApplicationDbContext</span> : <span class="hljs-title">IdentityDbContext</span>&lt;<span class="hljs-title">ApplicationUser</span>&gt;
    {
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ApplicationDbContext</span>(<span class="hljs-params">DbContextOptions&lt;ApplicationDbContext&gt; options</span>)
            : <span class="hljs-title">base</span>(<span class="hljs-params">options</span>)</span>
        {
        }
    }
}
</code></pre>
<h2 id="heading-step-3-creating-a-token-service">Step 3: Creating a Token Service</h2>
<p>The most important part of JWT authentication is token generation. Let's create a service that will handle this:</p>
<pre><code class="lang-csharp"><span class="hljs-comment">// Services/TokenService.cs</span>
<span class="hljs-keyword">using</span> System.IdentityModel.Tokens.Jwt;
<span class="hljs-keyword">using</span> System.Security.Claims;
<span class="hljs-keyword">using</span> System.Text;
<span class="hljs-keyword">using</span> Ecommerce.Models;
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Identity;
<span class="hljs-keyword">using</span> Microsoft.Extensions.Configuration;
<span class="hljs-keyword">using</span> Microsoft.IdentityModel.Tokens;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">Ecommerce.Services</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TokenService</span>
    {
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> IConfiguration _configuration;
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> UserManager&lt;ApplicationUser&gt; _userManager;

        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">TokenService</span>(<span class="hljs-params">IConfiguration configuration, UserManager&lt;ApplicationUser&gt; userManager</span>)</span>
        {
            _configuration = configuration;
            _userManager = userManager;
        }

        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;<span class="hljs-keyword">string</span>&gt; <span class="hljs-title">GenerateToken</span>(<span class="hljs-params">ApplicationUser user</span>)</span>
        {
            <span class="hljs-keyword">var</span> jwtTokenHandler = <span class="hljs-keyword">new</span> JwtSecurityTokenHandler();
            <span class="hljs-keyword">var</span> key = Encoding.ASCII.GetBytes(_configuration[<span class="hljs-string">"JwtConfig:Secret"</span>]);

            <span class="hljs-keyword">var</span> roles = <span class="hljs-keyword">await</span> _userManager.GetRolesAsync(user);
            <span class="hljs-keyword">var</span> claims = <span class="hljs-keyword">new</span> List&lt;Claim&gt;
            {
                <span class="hljs-keyword">new</span> Claim(ClaimTypes.NameIdentifier, user.Id),
                <span class="hljs-keyword">new</span> Claim(JwtRegisteredClaimNames.Sub, user.UserName),
                <span class="hljs-keyword">new</span> Claim(JwtRegisteredClaimNames.Email, user.Email),
                <span class="hljs-keyword">new</span> Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
            };

            <span class="hljs-comment">// Add role claims</span>
            <span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> role <span class="hljs-keyword">in</span> roles)
            {
                claims.Add(<span class="hljs-keyword">new</span> Claim(ClaimTypes.Role, role));
            }

            <span class="hljs-comment">// Set defaults if config values are missing</span>
            <span class="hljs-keyword">var</span> issuer = _configuration[<span class="hljs-string">"JwtConfig:Issuer"</span>] ?? <span class="hljs-string">"DefaultIssuer"</span>;
            <span class="hljs-keyword">var</span> audience = _configuration[<span class="hljs-string">"JwtConfig:Audience"</span>] ?? <span class="hljs-string">"DefaultAudience"</span>;
            <span class="hljs-keyword">var</span> expiryMinutesStr = _configuration[<span class="hljs-string">"JwtConfig:ExpiryInMinutes"</span>];
            <span class="hljs-keyword">var</span> expiryMinutes = <span class="hljs-keyword">string</span>.IsNullOrEmpty(expiryMinutesStr) ? <span class="hljs-number">60</span> : Convert.ToDouble(expiryMinutesStr);

            <span class="hljs-comment">// Important: Set the NotBefore time to now and Expires to a future time</span>
            <span class="hljs-keyword">var</span> now = DateTime.UtcNow;
            <span class="hljs-keyword">var</span> expires = now.AddMinutes(expiryMinutes);

            <span class="hljs-keyword">var</span> tokenDescriptor = <span class="hljs-keyword">new</span> SecurityTokenDescriptor
            {
                Subject = <span class="hljs-keyword">new</span> ClaimsIdentity(claims),
                NotBefore = now,
                Expires = expires,
                SigningCredentials = <span class="hljs-keyword">new</span> SigningCredentials(
                    <span class="hljs-keyword">new</span> SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
                Issuer = issuer,
                Audience = audience
            };

            <span class="hljs-keyword">var</span> token = jwtTokenHandler.CreateToken(tokenDescriptor);
            <span class="hljs-keyword">return</span> jwtTokenHandler.WriteToken(token);
        }
    }
}
</code></pre>
<h2 id="heading-step-4-creating-the-authentication-controller">Step 4: Creating the Authentication Controller</h2>
<p>Now, let's create the controller that will handle registration and login:</p>
<pre><code class="lang-csharp"><span class="hljs-comment">// Controllers/AuthController.cs</span>
<span class="hljs-keyword">using</span> Ecommerce.Models;
<span class="hljs-keyword">using</span> Ecommerce.Services;
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Identity;
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Mvc;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">Ecommerce.Controllers</span>
{
    [<span class="hljs-meta">Route(<span class="hljs-meta-string">"api/[controller]"</span>)</span>]
    [<span class="hljs-meta">ApiController</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">AuthController</span> : <span class="hljs-title">ControllerBase</span>
    {
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> UserManager&lt;ApplicationUser&gt; _userManager;
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> SignInManager&lt;ApplicationUser&gt; _signInManager;
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> RoleManager&lt;IdentityRole&gt; _roleManager;
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> TokenService _tokenService;

        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">AuthController</span>(<span class="hljs-params">
            UserManager&lt;ApplicationUser&gt; userManager,
            SignInManager&lt;ApplicationUser&gt; signInManager,
            RoleManager&lt;IdentityRole&gt; roleManager,
            TokenService tokenService</span>)</span>
        {
            _userManager = userManager;
            _signInManager = signInManager;
            _roleManager = roleManager;
            _tokenService = tokenService;
        }

        [<span class="hljs-meta">HttpPost(<span class="hljs-meta-string">"register"</span>)</span>]
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;IActionResult&gt; <span class="hljs-title">Register</span>(<span class="hljs-params">[FromBody] RegisterDto model</span>)</span>
        {
            <span class="hljs-keyword">if</span> (!ModelState.IsValid)
            {
                <span class="hljs-keyword">return</span> BadRequest(<span class="hljs-keyword">new</span> AuthResponseDto
                {
                    IsSuccess = <span class="hljs-literal">false</span>,
                    Message = <span class="hljs-string">"Invalid request"</span>
                });
            }

            <span class="hljs-keyword">var</span> userExists = <span class="hljs-keyword">await</span> _userManager.FindByNameAsync(model.UserName);
            <span class="hljs-keyword">if</span> (userExists != <span class="hljs-literal">null</span>)
            {
                <span class="hljs-keyword">return</span> BadRequest(<span class="hljs-keyword">new</span> AuthResponseDto
                {
                    IsSuccess = <span class="hljs-literal">false</span>,
                    Message = <span class="hljs-string">"User already exists"</span>
                });
            }

            <span class="hljs-keyword">var</span> user = <span class="hljs-keyword">new</span> ApplicationUser
            {
                UserName = model.UserName,
                Email = model.Email,
                MobileNumber = model.MobileNumber,
                Address = model.Address,
                SecurityStamp = Guid.NewGuid().ToString()
            };

            <span class="hljs-keyword">var</span> result = <span class="hljs-keyword">await</span> _userManager.CreateAsync(user, model.Password);
            <span class="hljs-keyword">if</span> (!result.Succeeded)
            {
                <span class="hljs-keyword">return</span> BadRequest(<span class="hljs-keyword">new</span> AuthResponseDto
                {
                    IsSuccess = <span class="hljs-literal">false</span>,
                    Message = <span class="hljs-string">"User creation failed: "</span> + <span class="hljs-keyword">string</span>.Join(<span class="hljs-string">", "</span>, result.Errors.Select(e =&gt; e.Description))
                });
            }

            <span class="hljs-comment">// Ensure the "Customer" role exists, create it if it doesn't</span>
            <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">await</span> _roleManager.RoleExistsAsync(<span class="hljs-string">"Customer"</span>))
            {
                <span class="hljs-keyword">await</span> _roleManager.CreateAsync(<span class="hljs-keyword">new</span> IdentityRole(<span class="hljs-string">"Customer"</span>));
            }

            <span class="hljs-comment">// Add user to Customer role</span>
            <span class="hljs-keyword">await</span> _userManager.AddToRoleAsync(user, <span class="hljs-string">"Customer"</span>);

            <span class="hljs-keyword">return</span> Ok(<span class="hljs-keyword">new</span> AuthResponseDto
            {
                IsSuccess = <span class="hljs-literal">true</span>,
                Message = <span class="hljs-string">"User created successfully"</span>
            });
        }

        [<span class="hljs-meta">HttpPost(<span class="hljs-meta-string">"login"</span>)</span>]
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;IActionResult&gt; <span class="hljs-title">Login</span>(<span class="hljs-params">[FromBody] LoginDto model</span>)</span>
        {
            <span class="hljs-keyword">if</span> (!ModelState.IsValid)
            {
                <span class="hljs-keyword">return</span> BadRequest(<span class="hljs-keyword">new</span> AuthResponseDto
                {
                    IsSuccess = <span class="hljs-literal">false</span>,
                    Message = <span class="hljs-string">"Invalid request"</span>
                });
            }

            <span class="hljs-keyword">var</span> user = <span class="hljs-keyword">await</span> _userManager.FindByNameAsync(model.UserName);
            <span class="hljs-keyword">if</span> (user == <span class="hljs-literal">null</span>)
            {
                <span class="hljs-keyword">return</span> Unauthorized(<span class="hljs-keyword">new</span> AuthResponseDto
                {
                    IsSuccess = <span class="hljs-literal">false</span>,
                    Message = <span class="hljs-string">"Invalid username or password"</span>
                });
            }

            <span class="hljs-keyword">var</span> result = <span class="hljs-keyword">await</span> _signInManager.CheckPasswordSignInAsync(user, model.Password, <span class="hljs-literal">false</span>);
            <span class="hljs-keyword">if</span> (!result.Succeeded)
            {
                <span class="hljs-keyword">return</span> Unauthorized(<span class="hljs-keyword">new</span> AuthResponseDto
                {
                    IsSuccess = <span class="hljs-literal">false</span>,
                    Message = <span class="hljs-string">"Invalid username or password"</span>
                });
            }

            <span class="hljs-keyword">var</span> token = <span class="hljs-keyword">await</span> _tokenService.GenerateToken(user);
            <span class="hljs-keyword">var</span> roles = <span class="hljs-keyword">await</span> _userManager.GetRolesAsync(user);

            <span class="hljs-keyword">return</span> Ok(<span class="hljs-keyword">new</span> AuthResponseDto
            {
                IsSuccess = <span class="hljs-literal">true</span>,
                Token = token,
                UserName = user.UserName,
                Email = user.Email,
                Message = <span class="hljs-string">"Login successful"</span>,
                Roles = roles.ToList()
            });
        }
    }
}
</code></pre>
<h2 id="heading-step-5-creating-protected-endpoints">Step 5: Creating Protected Endpoints</h2>
<p>Finally, let's create some protected endpoints that will require authentication and specific roles:</p>
<pre><code class="lang-csharp"><span class="hljs-comment">// Controllers/ProductsController.cs</span>
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Authorization;
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Mvc;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">Ecommerce.Controllers</span>
{
    [<span class="hljs-meta">Authorize</span>]
    [<span class="hljs-meta">Route(<span class="hljs-meta-string">"api/[controller]"</span>)</span>]
    [<span class="hljs-meta">ApiController</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ProductsController</span> : <span class="hljs-title">ControllerBase</span>
    {
        [<span class="hljs-meta">HttpGet</span>]
        <span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">Get</span>(<span class="hljs-params"></span>)</span>
        {
            <span class="hljs-keyword">return</span> Ok(<span class="hljs-keyword">new</span> { Message = <span class="hljs-string">"This is a protected endpoint"</span> });
        }

        [<span class="hljs-meta">Authorize(Roles = <span class="hljs-meta-string">"Customer"</span>)</span>]
        [<span class="hljs-meta">HttpGet(<span class="hljs-meta-string">"customer"</span>)</span>]
        <span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">GetCustomer</span>(<span class="hljs-params"></span>)</span>
        {
            <span class="hljs-keyword">return</span> Ok(<span class="hljs-keyword">new</span> { Message = <span class="hljs-string">"This endpoint is only accessible to users with the Customer role"</span> });
        }
    }
}
</code></pre>
<h2 id="heading-step-6-configuring-the-application">Step 6: Configuring the Application</h2>
<p>Now, let's configure our application in the Program.cs file:</p>
<pre><code class="lang-csharp"><span class="hljs-comment">// Program.cs</span>
<span class="hljs-keyword">using</span> Microsoft.EntityFrameworkCore;
<span class="hljs-keyword">using</span> Ecommerce.Models;
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Identity;
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Authentication.JwtBearer;
<span class="hljs-keyword">using</span> Ecommerce.Data;
<span class="hljs-keyword">using</span> Microsoft.IdentityModel.Tokens;
<span class="hljs-keyword">using</span> System.Text;
<span class="hljs-keyword">using</span> Ecommerce.Services;

<span class="hljs-keyword">var</span> builder = WebApplication.CreateBuilder(args);

<span class="hljs-comment">// Add services to the container.</span>
builder.Services.AddDbContext&lt;ApplicationDbContext&gt;(
    options =&gt;
    options.UseNpgsql(
        builder.Configuration.GetConnectionString(<span class="hljs-string">"DefaultConnection"</span>)));

builder.Services.AddIdentity&lt;ApplicationUser, IdentityRole&gt;()
    .AddEntityFrameworkStores&lt;ApplicationDbContext&gt;()
    .AddDefaultTokenProviders();
builder.Services.AddScoped&lt;TokenService&gt;();

builder.Services.AddAuthentication(options =&gt;
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =&gt;
{
    options.SaveToken = <span class="hljs-literal">true</span>;
    options.RequireHttpsMetadata = <span class="hljs-literal">false</span>;
    options.TokenValidationParameters = <span class="hljs-keyword">new</span> TokenValidationParameters
    {
        ValidateIssuer = <span class="hljs-literal">true</span>,
        ValidateAudience = <span class="hljs-literal">true</span>,
        ValidateLifetime = <span class="hljs-literal">true</span>,
        ValidateIssuerSigningKey = <span class="hljs-literal">true</span>,
        ValidIssuer = builder.Configuration[<span class="hljs-string">"JwtConfig:Issuer"</span>],
        ValidAudience = builder.Configuration[<span class="hljs-string">"JwtConfig:Audience"</span>],
        IssuerSigningKey = <span class="hljs-keyword">new</span> SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration[<span class="hljs-string">"JwtConfig:Secret"</span>]))
    };
});

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

<span class="hljs-keyword">var</span> app = builder.Build();

<span class="hljs-comment">// Configure the HTTP request pipeline.</span>
<span class="hljs-keyword">if</span> (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthentication(); <span class="hljs-comment">// Don't forget this!</span>
app.UseAuthorization();

app.MapControllers();

<span class="hljs-comment">// Initialize roles</span>
<span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> scope = app.Services.CreateScope())
{
    <span class="hljs-keyword">var</span> roleManager = scope.ServiceProvider.GetRequiredService&lt;RoleManager&lt;IdentityRole&gt;&gt;();

    <span class="hljs-comment">// Ensure Customer role exists</span>
    <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">await</span> roleManager.RoleExistsAsync(<span class="hljs-string">"Customer"</span>))
    {
        <span class="hljs-keyword">await</span> roleManager.CreateAsync(<span class="hljs-keyword">new</span> IdentityRole(<span class="hljs-string">"Customer"</span>));
    }
}

app.Run();
</code></pre>
<h2 id="heading-step-7-configure-jwt-settings-in-appsettingsjson">Step 7: Configure JWT Settings in appsettings.json</h2>
<p>Don't forget to add JWT configuration to your appsettings.json file:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"ConnectionStrings"</span>: {
    <span class="hljs-attr">"DefaultConnection"</span>: <span class="hljs-string">"Host=localhost;Database=EcommerceDb;Username=postgres;Password=yourpassword"</span>
  },
  <span class="hljs-attr">"JwtConfig"</span>: {
    <span class="hljs-attr">"Secret"</span>: <span class="hljs-string">"YourSuperSecretKeyWithAtLeast32Characters"</span>,
    <span class="hljs-attr">"Issuer"</span>: <span class="hljs-string">"YourApiDomain.com"</span>,
    <span class="hljs-attr">"Audience"</span>: <span class="hljs-string">"YourFrontendDomain.com"</span>,
    <span class="hljs-attr">"ExpiryInMinutes"</span>: <span class="hljs-number">60</span>
  },
  <span class="hljs-attr">"Logging"</span>: {
    <span class="hljs-attr">"LogLevel"</span>: {
      <span class="hljs-attr">"Default"</span>: <span class="hljs-string">"Information"</span>,
      <span class="hljs-attr">"Microsoft.AspNetCore"</span>: <span class="hljs-string">"Warning"</span>
    }
  },
  <span class="hljs-attr">"AllowedHosts"</span>: <span class="hljs-string">"*"</span>
}
</code></pre>
<h2 id="heading-security-considerations">Security Considerations</h2>
<p>When implementing JWT authentication, keep the following security considerations in mind:</p>
<ol>
<li><p><strong>Secret Key Protection:</strong> Your JWT secret key should be at least 32 characters long and kept secure. Consider using Azure Key Vault or similar services for production.</p>
</li>
<li><p><strong>Token Expiration:</strong> Always set a reasonable expiration time for your tokens. In our example, we set it to 60 minutes.</p>
</li>
<li><p><strong>HTTPS:</strong> Always use HTTPS in production to encrypt JWT tokens in transit.</p>
</li>
<li><p><strong>Claim Validation:</strong> Validate all claims, including issuer and audience.</p>
</li>
<li><p><strong>Refresh Tokens:</strong> For longer sessions, implement refresh tokens instead of extending JWT token expiration.</p>
</li>
</ol>
<h2 id="heading-testing-the-authentication-flow">Testing the Authentication Flow</h2>
<p>You can test your authentication system using a tool like Postman:</p>
<ol>
<li>Register a new user via the <code>/api/Auth/register</code> endpoint:</li>
</ol>
<pre><code class="lang-json">{
  <span class="hljs-attr">"email"</span>: <span class="hljs-string">"user@example.com"</span>,
  <span class="hljs-attr">"userName"</span>: <span class="hljs-string">"testuser"</span>,
  <span class="hljs-attr">"password"</span>: <span class="hljs-string">"StrongPassword123!"</span>,
  <span class="hljs-attr">"mobileNumber"</span>: <span class="hljs-string">"1234567890"</span>,
  <span class="hljs-attr">"address"</span>: <span class="hljs-string">"123 Test Street"</span>
}
</code></pre>
<ol start="2">
<li>Login via the <code>/api/Auth/login</code> endpoint:</li>
</ol>
<pre><code class="lang-json">{
  <span class="hljs-attr">"userName"</span>: <span class="hljs-string">"testuser"</span>,
  <span class="hljs-attr">"password"</span>: <span class="hljs-string">"StrongPassword123!"</span>
}
</code></pre>
<ol start="3">
<li><p>Copy the token from the response and use it in the Authorization header (Bearer token) to access protected endpoints like <code>/api/Products</code>.  </p>
<p> Github : <a target="_blank" href="https://github.com/sudipbhr/asp.net-web-api-auth">https://github.com/sudipbhr/asp.net-web-api-auth</a></p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, we've implemented a complete JWT authentication system in <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core. We've covered user registration, login, token generation, and role-based authorization. This system is a solid foundation for securing your Web API and can be extended with features like refresh tokens, email confirmation, and more advanced authorization policies.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Dependency Injection in ASP.NET with Real-World Examples]]></title><description><![CDATA[Here is real life example of Dependency Injection (DI) in an ASP.NET Core application. We'll build a simple Order Processing System where the system depends on various services like logging, emailing, and payment processing.
Scenario:
We have a syste...]]></description><link>https://sudipbhandari.hashnode.dev/understanding-dependency-injection-in-aspnet-with-real-world-examples</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/understanding-dependency-injection-in-aspnet-with-real-world-examples</guid><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Sat, 15 Mar 2025 15:58:54 GMT</pubDate><content:encoded><![CDATA[<p>Here is real life example of Dependency Injection (DI) in an <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core application. We'll build a simple <strong>Order Processing System</strong> where the system depends on various services like logging, emailing, and payment processing.</p>
<h3 id="heading-scenario">Scenario:</h3>
<p>We have a system that processes orders. When an order is placed:</p>
<ol>
<li><p>A <strong>Payment</strong> needs to be processed.</p>
</li>
<li><p>A <strong>Confirmation Email</strong> should be sent to the customer.</p>
</li>
<li><p>A <strong>Logging</strong> service logs each step of the order process.</p>
</li>
</ol>
<p>We want to keep these services decoupled so we can easily swap them out or mock them for testing. This is where <strong>Dependency Injection (DI)</strong> comes into play.</p>
<h3 id="heading-1-define-interfaces-and-implementations">1. <strong>Define Interfaces and Implementations</strong></h3>
<p>We'll start by defining the services that our order processing system will depend on.</p>
<h4 id="heading-payment-service">Payment Service</h4>
<pre><code class="lang-xml">public interface IPaymentService
{
    bool ProcessPayment(Order order);
}

public class PaymentService : IPaymentService
{
    public bool ProcessPayment(Order order)
    {
        // Imagine calling an external payment provider API here.
        Console.WriteLine($"Processing payment for Order ID: {order.OrderId}");
        return true;  // Payment success
    }
}
</code></pre>
<h4 id="heading-email-service">Email Service</h4>
<pre><code class="lang-xml">public interface IEmailService
{
    void SendOrderConfirmationEmail(Order order);
}

public class EmailService : IEmailService
{
    public void SendOrderConfirmationEmail(Order order)
    {
        // Imagine sending an email here
        Console.WriteLine($"Sending confirmation email to {order.CustomerEmail} for Order ID: {order.OrderId}");
    }
}
</code></pre>
<h4 id="heading-logging-service">Logging Service</h4>
<pre><code class="lang-xml">public interface ILoggingService
{
    void Log(string message);
}

public class LoggingService : ILoggingService
{
    public void Log(string message)
    {
        // Imagine writing logs to a file, database, or external service.
        Console.WriteLine($"Log: {message}");
    }
}
</code></pre>
<h3 id="heading-2-create-the-order-model">2. <strong>Create the Order Model</strong></h3>
<p>We'll create a simple <code>Order</code> model to pass data through the services.</p>
<pre><code class="lang-xml">public class Order
{
    public int OrderId { get; set; }
    public string CustomerEmail { get; set; }
    public decimal TotalAmount { get; set; }
}
</code></pre>
<h3 id="heading-3-define-the-order-processor">3. <strong>Define the Order Processor</strong></h3>
<p>This is the main service that coordinates the different operations (payment, email, logging) when an order is placed.</p>
<pre><code class="lang-xml">public class OrderProcessor
{
    private readonly IPaymentService _paymentService;
    private readonly IEmailService _emailService;
    private readonly ILoggingService _loggingService;

    // Constructor Injection
    public OrderProcessor(
        IPaymentService paymentService,
        IEmailService emailService,
        ILoggingService loggingService)
    {
        _paymentService = paymentService;
        _emailService = emailService;
        _loggingService = loggingService;
    }

    public void ProcessOrder(Order order)
    {
        // Log the order processing
        _loggingService.Log($"Started processing Order ID: {order.OrderId}");

        // Process payment
        var paymentSuccess = _paymentService.ProcessPayment(order);
        if (paymentSuccess)
        {
            _loggingService.Log($"Payment successful for Order ID: {order.OrderId}");

            // Send email confirmation
            _emailService.SendOrderConfirmationEmail(order);
            _loggingService.Log($"Confirmation email sent for Order ID: {order.OrderId}");
        }
        else
        {
            _loggingService.Log($"Payment failed for Order ID: {order.OrderId}");
        }

        // Final log
        _loggingService.Log($"Finished processing Order ID: {order.OrderId}");
    }
}
</code></pre>
<h3 id="heading-4-register-services-in-the-di-container">4. <strong>Register Services in the DI Container</strong></h3>
<p>Now, we need to register our services (<code>PaymentService</code>, <code>EmailService</code>, <code>LoggingService</code>) in the DI container so that they can be injected into the <code>OrderProcessor</code>.</p>
<h4 id="heading-in-startupcs-for-aspnethttpaspnet-core-3x-or-net-5">In <code>Startup.cs</code> (for <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core 3.x or .NET 5):</h4>
<pre><code class="lang-xml">public void ConfigureServices(IServiceCollection services)
{
    // Register services with DI container
    services.AddTransient<span class="hljs-tag">&lt;<span class="hljs-name">IPaymentService,</span> <span class="hljs-attr">PaymentService</span>&gt;</span>();  // Transient - new instance each time
    services.AddTransient<span class="hljs-tag">&lt;<span class="hljs-name">IEmailService,</span> <span class="hljs-attr">EmailService</span>&gt;</span>();      // Transient - new instance each time
    services.AddTransient<span class="hljs-tag">&lt;<span class="hljs-name">ILoggingService,</span> <span class="hljs-attr">LoggingService</span>&gt;</span>();  // Transient - new instance each time

    // Register OrderProcessor service
    services.AddTransient<span class="hljs-tag">&lt;<span class="hljs-name">OrderProcessor</span>&gt;</span>();

    services.AddControllers();
}
</code></pre>
<h4 id="heading-in-programcs-for-aspnethttpaspnet-core-6">In <code>Program.cs</code> (for <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core 6+):</h4>
<pre><code class="lang-xml">var builder = WebApplication.CreateBuilder(args);

// Register services with DI container
builder.Services.AddTransient<span class="hljs-tag">&lt;<span class="hljs-name">IPaymentService,</span> <span class="hljs-attr">PaymentService</span>&gt;</span>();
builder.Services.AddTransient<span class="hljs-tag">&lt;<span class="hljs-name">IEmailService,</span> <span class="hljs-attr">EmailService</span>&gt;</span>();
builder.Services.AddTransient<span class="hljs-tag">&lt;<span class="hljs-name">ILoggingService,</span> <span class="hljs-attr">LoggingService</span>&gt;</span>();
builder.Services.AddTransient<span class="hljs-tag">&lt;<span class="hljs-name">OrderProcessor</span>&gt;</span>();

builder.Services.AddControllers();

var app = builder.Build();
app.MapControllers();
app.Run();
</code></pre>
<h3 id="heading-5-inject-orderprocessor-into-a-controller">5. <strong>Inject</strong> <code>OrderProcessor</code> into a Controller</h3>
<p>Now, let's use <strong>constructor injection</strong> to inject the <code>OrderProcessor</code> into a controller where we handle HTTP requests.</p>
<pre><code class="lang-xml">[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
    private readonly OrderProcessor _orderProcessor;

    // Constructor Injection
    public OrdersController(OrderProcessor orderProcessor)
    {
        _orderProcessor = orderProcessor;
    }

    [HttpPost]
    [Route("process")]
    public IActionResult ProcessOrder([FromBody] Order order)
    {
        // Use OrderProcessor to handle the order
        _orderProcessor.ProcessOrder(order);

        return Ok("Order processed successfully!");
    }
}
</code></pre>
<h3 id="heading-6-example-request">6. <strong>Example Request</strong></h3>
<p>Now, when you make a POST request to the API endpoint <code>/api/orders/process</code> with an order body:</p>
<pre><code class="lang-xml">{
  "OrderId": 1,
  "CustomerEmail": "customer@example.com",
  "TotalAmount": 99.99
}
</code></pre>
<p>The system will:</p>
<ol>
<li><p>Log the order processing.</p>
</li>
<li><p>Process the payment.</p>
</li>
<li><p>Send a confirmation email.</p>
</li>
<li><p>Log the result at each step.</p>
</li>
</ol>
<h3 id="heading-7-how-di-works-in-this-example">7. <strong>How DI Works in This Example</strong></h3>
<ul>
<li><p>The <code>OrderProcessor</code> depends on three services: <code>IPaymentService</code>, <code>IEmailService</code>, and <code>ILoggingService</code>.</p>
</li>
<li><p>These dependencies are injected by <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core's <strong>DI container</strong> via constructor injection.</p>
</li>
<li><p>The <strong>DI container</strong> automatically resolves and provides the appropriate instances of <code>PaymentService</code>, <code>EmailService</code>, and <code>LoggingService</code> when the <code>OrderProcessor</code> is instantiated.</p>
</li>
<li><p>This means we can easily swap out the implementations of these services without modifying the <code>OrderProcessor</code> class. For example, we could replace <code>PaymentService</code> with a mock version for testing or swap in a new payment provider.</p>
</li>
</ul>
<h3 id="heading-8-benefits-of-dependency-injection">8. <strong>Benefits of Dependency Injection</strong></h3>
<ol>
<li><p><strong>Loose Coupling:</strong> The <code>OrderProcessor</code> is not tightly coupled to specific implementations of <code>PaymentService</code>, <code>EmailService</code>, or <code>LoggingService</code>. You can swap them out as needed.</p>
</li>
<li><p><strong>Testability:</strong> It’s easy to mock or replace services in tests. For example, in unit tests, you can mock <code>IPaymentService</code> and <code>IEmailService</code>.</p>
</li>
<li><p><strong>Maintainability:</strong> Adding new features or services doesn’t require changes to the core logic (e.g., adding a new <code>ShippingService</code>).</p>
</li>
<li><p><strong>Configuration Management:</strong> You can configure services in one central location (DI container), which makes managing complex dependencies easier.</p>
</li>
</ol>
<h3 id="heading-9-conclusion">9. <strong>Conclusion</strong></h3>
<p>This real-life example of DI in <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core demonstrates how you can build a loosely-coupled, maintainable, and testable application. By injecting dependencies like <code>PaymentService</code>, <code>EmailService</code>, and <code>LoggingService</code> into the <code>OrderProcessor</code>, you ensure that the application is flexible and scalable, while also promoting good software engineering practices like separation of concerns and single responsibility.</p>
]]></content:encoded></item><item><title><![CDATA[Building a RESTful API with ASP.NET Core and Data Annotations: A Comprehensive Guide]]></title><description><![CDATA[In today's web-driven world, RESTful APIs have become the backbone of modern applications, enabling seamless communication between different systems. ASP.NET Core offers a powerful framework for building robust APIs, and when combined with data annot...]]></description><link>https://sudipbhandari.hashnode.dev/building-a-restful-api-with-aspnet-core-and-data-annotations-a-comprehensive-guide</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/building-a-restful-api-with-aspnet-core-and-data-annotations-a-comprehensive-guide</guid><category><![CDATA[APIs]]></category><category><![CDATA[asp.net core]]></category><category><![CDATA[Asp.Net Web API]]></category><category><![CDATA[dotnet, ASP.NET Core, Minimal APIs, Route Parameters, RESTful API, Web Development]]></category><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Sat, 08 Mar 2025 17:51:37 GMT</pubDate><content:encoded><![CDATA[<p>In today's web-driven world, RESTful APIs have become the backbone of modern applications, enabling seamless communication between different systems. <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core offers a powerful framework for building robust APIs, and when combined with data annotations, it provides an elegant solution for creating well-structured and validated APIs.</p>
<p>In this guide, we'll explore how to build a complete Book Records API using <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core and implement data validation using annotations. We'll cover everything from creating a new project to implementing CRUD operations with proper validation.</p>
<h2 id="heading-understanding-aspnet-core-web-api">Understanding ASP.NET Core Web API</h2>
<p>ASP.NET Core Web API is a framework for building HTTP services that can be accessed from any client, including browsers and mobile devices. It's built on the ASP.NET Core platform and provides a more lightweight and modular approach compared to traditional ASP.NET.</p>
<p>Key features include:</p>
<ul>
<li><p>Cross-platform compatibility (Windows, macOS, Linux)</p>
</li>
<li><p>High-performance architecture</p>
</li>
<li><p>Built-in dependency injection</p>
</li>
<li><p>Simplified routing using attributes</p>
</li>
<li><p>Content negotiation and formatting</p>
</li>
<li><p>Model binding and validation</p>
</li>
</ul>
<h2 id="heading-data-annotations-in-net">Data Annotations in .NET</h2>
<p>Data annotations are attributes that you can apply to model classes and properties to:</p>
<ul>
<li><p>Enforce validation rules</p>
</li>
<li><p>Specify display formats</p>
</li>
<li><p>Define relationships between models</p>
</li>
<li><p>Configure how model binding behaves</p>
</li>
</ul>
<p>These annotations reside in the <code>System.ComponentModel.DataAnnotations</code> namespace and provide a declarative way to implement validation logic without writing extensive code.</p>
<p>Common annotations include:</p>
<ul>
<li><p><code>[Required]</code>: Ensures a property has a value</p>
</li>
<li><p><code>[StringLength]</code>: Limits the length of a string</p>
</li>
<li><p><code>[Range]</code>: Specifies minimum and maximum values for numeric types</p>
</li>
<li><p><code>[EmailAddress]</code>: Validates email format</p>
</li>
<li><p><code>[RegularExpression]</code>: Validates against a regex pattern</p>
</li>
</ul>
<h2 id="heading-step-by-step-guide-to-create-a-book-api">Step-by-Step Guide to Create a Book API</h2>
<h3 id="heading-1-set-up-your-development-environment">1. Set Up Your Development Environment</h3>
<p>First, ensure you have the following installed:</p>
<ul>
<li><p><a target="_blank" href="https://dotnet.microsoft.com/download">.NET 6.0 SDK</a> or later</p>
</li>
<li><p>An IDE (Visual Studio, VS Code with C# extension, or JetBrains Rider)</p>
</li>
</ul>
<h3 id="heading-2-create-a-new-aspnet-core-web-api-project">2. Create a New ASP.NET Core Web API Project</h3>
<h4 id="heading-using-visual-studio">Using Visual Studio:</h4>
<ol>
<li><p>Open Visual Studio</p>
</li>
<li><p>Select "Create a new project"</p>
</li>
<li><p>Choose "ASP.NET Core Web API"</p>
</li>
<li><p>Name your project (e.g., "BookRecordAPI")</p>
</li>
<li><p>Select .NET 6.0 or later as the target framework</p>
</li>
<li><p>Uncheck "Use controllers" if you prefer minimal API style (for this guide, we'll use controllers)</p>
</li>
<li><p>Click "Create"</p>
</li>
</ol>
<pre><code class="lang-xml">dotnet new webapi -n BookRecordAPI
cd BookRecordAPI
</code></pre>
<h3 id="heading-3-project-structure">3. Project Structure</h3>
<p>After creating the project, you should have a folder structure similar to:</p>
<pre><code class="lang-xml">BookRecordAPI/
├── Controllers/
├── Properties/
├── appsettings.json
├── appsettings.Development.json
├── Program.cs
└── BookRecordAPI.csproj
</code></pre>
<h3 id="heading-4-create-the-model-folder-and-book-class">4. Create the Model Folder and Book Class</h3>
<p>Create a new folder called "Models" and add a Book class:</p>
<pre><code class="lang-xml">using System.ComponentModel.DataAnnotations;

namespace BookRecordAPI.Models
{
    public class Book
    {
        public int Id { get; set; }

        [Required]
        [StringLength(200)]
        public string Title { get; set; }

        [Required]
        [StringLength(100)]
        public string Author { get; set; }

        [Required]
        [StringLength(50)]
        public string Genre { get; set; }

        [Range(1000, 2100, ErrorMessage = "Published Year must be between 1000 and 2100.")]
        public int PublishedYear { get; set; }
    }
}
</code></pre>
<h2 id="heading-implementing-the-book-model-with-annotations">Implementing the Book Model with Annotations</h2>
<p>Let's analyze each annotation in our Book model:</p>
<h3 id="heading-1-required">1. [Required]</h3>
<pre><code class="lang-xml">[Required]
public string Title { get; set; }
</code></pre>
<p>The <code>[Required]</code> attribute ensures that the property must have a value. For string properties, it verifies that the value isn't null or an empty string. When model validation occurs, <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core will automatically check this constraint.</p>
<h3 id="heading-2-stringlength">2. [StringLength]</h3>
<pre><code class="lang-xml">[StringLength(200)]
public string Title { get; set; }
</code></pre>
<p>The <code>[StringLength]</code> attribute restricts the length of a string property. It accepts parameters for maximum length and optionally minimum length. In our example:</p>
<ul>
<li><p>Title has a maximum length of 200 characters</p>
</li>
<li><p>Author has a maximum length of 100 characters</p>
</li>
<li><p>Genre has a maximum length of 50 characters</p>
</li>
</ul>
<h3 id="heading-3-range">3. [Range]</h3>
<pre><code class="lang-xml">[Range(1000, 2100, ErrorMessage = "Published Year must be between 1000 and 2100.")]
public int PublishedYear { get; set; }
</code></pre>
<p>The <code>[Range]</code> attribute specifies minimum and maximum values for numeric properties. In this case, we're ensuring that the PublishedYear is between 1000 and 2100.</p>
<p>The <code>ErrorMessage</code> parameter allows you to customize the validation error message that will be returned if the validation fails.</p>
<h2 id="heading-creating-api-controllers-and-routes">Creating API Controllers and Routes</h2>
<p>Now, let's create a controller to handle HTTP requests for our Book API:</p>
<pre><code class="lang-xml">using Microsoft.AspNetCore.Mvc;
using BookRecordAPI.Models;
using System.Collections.Generic;
using System.Linq;

namespace BookRecordAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class BooksController : ControllerBase
    {
        private static List<span class="hljs-tag">&lt;<span class="hljs-name">Book</span>&gt;</span> books = new List<span class="hljs-tag">&lt;<span class="hljs-name">Book</span>&gt;</span>
        {
            new Book { Id = 1, Title = "1984", Author = "George Orwell", Genre = "Dystopian", PublishedYear = 1949 },
            new Book { Id = 2, Title = "To Kill a Mockingbird", Author = "Harper Lee", Genre = "Fiction", PublishedYear = 1960 }
        };

        // GET: api/books
        [HttpGet]
        public ActionResult<span class="hljs-tag">&lt;<span class="hljs-name">IEnumerable</span>&lt;<span class="hljs-attr">Book</span>&gt;</span>&gt; GetBooks()
        {
            return Ok(books);
        }

        // GET: api/books/{id}
        [HttpGet("{id}")]
        public ActionResult<span class="hljs-tag">&lt;<span class="hljs-name">Book</span>&gt;</span> GetBook(int id)
        {
            var book = books.FirstOrDefault(b =&gt; b.Id == id);
            if (book == null)
                return NotFound(new { message = "Book not found" });

            return Ok(book);
        }

        // POST: api/books
        [HttpPost]
        public ActionResult<span class="hljs-tag">&lt;<span class="hljs-name">Book</span>&gt;</span> AddBook([FromBody] Book book)
        {
            if (books.Any(b =&gt; b.Id == book.Id))
                return BadRequest(new { message = "Book with this ID already exists" });

            books.Add(book);
            return CreatedAtAction(nameof(GetBook), new { id = book.Id }, book);
        }

        // PUT: api/books/{id}
        [HttpPut("{id}")]
        public ActionResult UpdateBook(int id, [FromBody] Book updatedBook)
        {
            var book = books.FirstOrDefault(b =&gt; b.Id == id);
            if (book == null)
                return NotFound(new { message = "Book not found" });

            book.Title = updatedBook.Title;
            book.Author = updatedBook.Author;
            book.Genre = updatedBook.Genre;
            book.PublishedYear = updatedBook.PublishedYear;

            return NoContent();
        }

        // PATCH: api/books/{id}
        [HttpPatch("{id}")]
        public ActionResult PatchBook(int id, [FromBody] Dictionary<span class="hljs-tag">&lt;<span class="hljs-name">string,</span> <span class="hljs-attr">object</span>&gt;</span> updates)
        {
            var book = books.FirstOrDefault(b =&gt; b.Id == id);
            if (book == null)
                return NotFound(new { message = "Book not found" });

            foreach (var key in updates.Keys)
            {
                switch (key.ToLower())
                {
                    case "title":
                        book.Title = updates[key].ToString();
                        break;
                    case "author":
                        book.Author = updates[key].ToString();
                        break;
                    case "genre":
                        book.Genre = updates[key].ToString();
                        break;
                    case "publishedyear":
                        if (int.TryParse(updates[key].ToString(), out int year))
                            book.PublishedYear = year;
                        break;
                }
            }
            return NoContent();
        }

        // DELETE: api/books/{id}
        [HttpDelete("{id}")]
        public ActionResult DeleteBook(int id)
        {
            var book = books.FirstOrDefault(b =&gt; b.Id == id);
            if (book == null)
                return NotFound(new { message = "Book not found" });

            books.Remove(book);
            return NoContent();
        }
    }
}
</code></pre>
<h3 id="heading-key-controller-components-explained">Key Controller Components Explained</h3>
<h4 id="heading-1-controller-attributes">1. Controller Attributes</h4>
<pre><code class="lang-xml">[Route("api/[controller]")]
[ApiController]
</code></pre>
<ul>
<li><p><code>[Route("api/[controller]")]</code>: Defines the route template for the controller. <code>[controller]</code> is replaced with the controller name (minus the "Controller" suffix), resulting in <code>/api/books</code>.</p>
</li>
<li><p><code>[ApiController]</code>: Adds API-specific behaviors, including automatic model validation and binding source parameter inference.</p>
</li>
</ul>
<h4 id="heading-2-http-method-attributes">2. HTTP Method Attributes</h4>
<pre><code class="lang-xml">[HttpGet]
[HttpGet("{id}")]
[HttpPost]
[HttpPut("{id}")]
[HttpPatch("{id}")]
[HttpDelete("{id}")]
</code></pre>
<p>These attributes map HTTP verbs to controller actions and define route templates. For example, <code>[HttpGet("{id}")]</code> maps HTTP GET requests to <code>/api/books/{id}</code> to the <code>GetBook</code> method.</p>
<h4 id="heading-3-model-binding-and-validation">3. Model Binding and Validation</h4>
<pre><code class="lang-xml">public ActionResult<span class="hljs-tag">&lt;<span class="hljs-name">Book</span>&gt;</span> AddBook([FromBody] Book book)
</code></pre>
<ul>
<li><p><code>[FromBody]</code>: Indicates that the parameter should be bound from the request body.</p>
</li>
<li><p>When a request comes in, <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core automatically:</p>
<ol>
<li><p>Deserializes the JSON request body to a Book object</p>
</li>
<li><p>Validates the object against the data annotations</p>
</li>
<li><p>Populates <code>ModelState</code> with any validation errors</p>
</li>
</ol>
</li>
</ul>
<h4 id="heading-4-response-types">4. Response Types</h4>
<pre><code class="lang-xml">return Ok(books);
return NotFound(new { message = "Book not found" });
return BadRequest(new { message = "Book with this ID already exists" });
return CreatedAtAction(nameof(GetBook), new { id = book.Id }, book);
return NoContent();
</code></pre>
<p>These helper methods create appropriate HTTP responses with correct status codes:</p>
<ul>
<li><p><code>Ok()</code>: 200 OK</p>
</li>
<li><p><code>NotFound()</code>: 404 Not Found</p>
</li>
<li><p><code>BadRequest()</code>: 400 Bad Request</p>
</li>
<li><p><code>CreatedAtAction()</code>: 201 Created with a Location header pointing to the new resource</p>
</li>
<li><p><code>NoContent()</code>: 204 No Content</p>
</li>
</ul>
<p>Github link</p>
<p><a target="_blank" href="https://github.com/sudipbhr/asp_web_book_record_api">Book Record Repo</a></p>
]]></content:encoded></item><item><title><![CDATA[Understanding Permissions in Linux]]></title><description><![CDATA[🔒 Understanding Permissions in Linux
Linux permissions control who can read, write, or execute files and directories. They are essential for security and access management.
1. File Permissions: Read, Write, Execute
Each file and directory in Linux h...]]></description><link>https://sudipbhandari.hashnode.dev/understanding-permissions-in-linux</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/understanding-permissions-in-linux</guid><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Mon, 10 Feb 2025 06:43:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1739169483484/351d4748-5a7f-411b-a307-1f42461f3236.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-understanding-permissions-in-linux">🔒 <strong>Understanding Permissions in Linux</strong></h3>
<p>Linux permissions control who can read, write, or execute files and directories. They are essential for security and access management.</p>
<h2 id="heading-1-file-permissions-read-write-execute"><strong>1. File Permissions: Read, Write, Execute</strong></h2>
<p>Each file and directory in Linux has three types of permissions:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Permission</td><td>Symbol</td><td>Meaning</td></tr>
</thead>
<tbody>
<tr>
<td>Read</td><td><code>r</code> (4)</td><td>View the contents of a file or list a directory</td></tr>
<tr>
<td>Write</td><td><code>w</code> (2)</td><td>Modify the file or create/delete files in a directory</td></tr>
<tr>
<td>Execute</td><td><code>x</code> (1)</td><td>Run the file (if it's a script or program) or access a directory</td></tr>
</tbody>
</table>
</div><p>Each file has <strong>three permission groups</strong>:</p>
<ol>
<li><p><strong>Owner (User)</strong> - The creator of the file.</p>
</li>
<li><p><strong>Group</strong> - A group of users who share permissions.</p>
</li>
<li><p><strong>Others</strong> - Everyone else.</p>
</li>
</ol>
<p>You can view file permissions using:</p>
<pre><code class="lang-xml">ls -l
</code></pre>
<p>Example output:</p>
<pre><code class="lang-xml">rwxr--r-- 1 user group 1234 Feb 10 12:00 myfile.sh
</code></pre>
<ul>
<li><p><code>-rwxr--r--</code></p>
<ul>
<li><p><code>-</code> → Regular file (or <code>d</code> for directory)</p>
</li>
<li><p><code>rwx</code> → Owner has <strong>read, write, execute</strong> (<code>r=4</code>, <code>w=2</code>, <code>x=1</code>, total = 7)</p>
</li>
<li><p><code>r--</code> → Group has <strong>read</strong> only (<code>r=4</code>)</p>
</li>
<li><p><code>r--</code> → Others have <strong>read</strong> only (<code>r=4</code>)</p>
</li>
</ul>
</li>
</ul>
<hr />
<h2 id="heading-2-changing-permissions-chmod"><strong>2. Changing Permissions (chmod)</strong></h2>
<p><code>chmod</code> modifies permissions.</p>
<h3 id="heading-symbolic-method"><strong>Symbolic Method</strong></h3>
<pre><code class="lang-xml">chmod u+x file    # Add execute (x) for the user
chmod g-w file    # Remove write (w) for the group
chmod o+r file    # Add read (r) for others
chmod ugo=rwx file  # Give full permissions to everyone
</code></pre>
<h3 id="heading-octal-method"><strong>Octal Method</strong></h3>
<p>Each permission type has a number:</p>
<ul>
<li><p><code>r = 4</code></p>
</li>
<li><p><code>w = 2</code></p>
</li>
<li><p><code>x = 1</code></p>
</li>
<li><p>No permission = <code>0</code></p>
</li>
</ul>
<p>To set permissions:</p>
<pre><code class="lang-xml">chmod 755 file  # Owner: rwx (7), Group: r-x (5), Others: r-x (5)
chmod 644 file  # Owner: rw- (6), Group: r-- (4), Others: r-- (4)
chmod 777 file  # Everyone has full permissions (⚠️ NOT recommended)
</code></pre>
<hr />
<h2 id="heading-3-changing-ownership-chown"><strong>3. Changing Ownership (chown)</strong></h2>
<p><code>chown</code> changes the owner of a file.</p>
<pre><code class="lang-xml">sudo chown user file       # Change owner
sudo chown user:group file # Change owner and group
sudo chown -R user:group directory/  # Apply recursively
</code></pre>
<hr />
<h2 id="heading-4-changing-group-ownership-chgrp"><strong>4. Changing Group Ownership (chgrp)</strong></h2>
<p><code>chgrp</code> changes only the group of a file.</p>
<pre><code class="lang-xml">sudo chgrp group file
</code></pre>
<hr />
<h2 id="heading-5-understanding-special-permissions"><strong>5. Understanding Special Permissions</strong></h2>
<h3 id="heading-sticky-bit-t-prevents-users-from-deleting-others-files-in-a-directory"><strong>Sticky Bit (</strong><code>t</code>): Prevents users from deleting others' files in a directory.</h3>
<pre><code class="lang-xml">chmod +t directory/
</code></pre>
<p>Example: <code>/tmp</code> has a sticky bit so only file owners can delete their own files.</p>
<h3 id="heading-setuid-s-runs-a-file-with-the-owners-privileges"><strong>SetUID (</strong><code>s</code>): Runs a file with the owner's privileges.</h3>
<pre><code class="lang-xml">chmod u+s file
</code></pre>
<p>Example: <code>/bin/passwd</code> lets users change their password.</p>
<h3 id="heading-setgid-s-runs-a-file-with-the-groups-privileges"><strong>SetGID (</strong><code>s</code>): Runs a file with the group's privileges.</h3>
<pre><code class="lang-xml">chmod g+s directory/
</code></pre>
<p>Files created in this directory inherit the group.</p>
<hr />
<h2 id="heading-6-viewing-effective-permissions"><strong>6. Viewing Effective Permissions</strong></h2>
<p>To see effective user permissions:</p>
<pre><code class="lang-xml">whoami      # Show current user
groups      # Show user's groups
id          # Show user and group IDs
</code></pre>
<p>To check access to a file:</p>
<pre><code class="lang-xml">namei -l /path/to/file
</code></pre>
<hr />
<h2 id="heading-7-default-permissions-umask"><strong>7. Default Permissions (umask)</strong></h2>
<p><code>umask</code> sets the default permissions for new files.</p>
<ul>
<li><p>View the current umask:</p>
<pre><code class="lang-xml">  umask
</code></pre>
</li>
<li><p>Set a new umask (e.g., <code>022</code> for <code>755</code>):</p>
<pre><code class="lang-xml">  umask 022
</code></pre>
</li>
</ul>
<hr />
<h2 id="heading-8-common-permission-issues-amp-fixes"><strong>8. Common Permission Issues &amp; Fixes</strong></h2>
<h3 id="heading-permission-denied-errno-13"><strong>Permission Denied (Errno 13)</strong></h3>
<pre><code class="lang-xml">sudo chmod -R 755 /path/to/directory
sudo chown -R user:user /path/to/directory
</code></pre>
<h3 id="heading-cannot-execute-script"><strong>Cannot Execute Script</strong></h3>
<pre><code class="lang-xml">chmod +x script.sh
./script.sh
</code></pre>
<h3 id="heading-cant-write-to-directory"><strong>Can't Write to Directory</strong></h3>
<pre><code class="lang-xml">chmod u+w directory/
</code></pre>
<hr />
<h2 id="heading-9-security-best-practices"><strong>9. Security Best Practices</strong></h2>
<p>✅ Avoid using <code>chmod 777</code> (full access for everyone).<br />✅ Use <code>sudo</code> only when necessary.<br />✅ Set directories to <code>755</code> and files to <code>644</code> unless execution is needed.<br />✅ Use <code>chown</code> carefully to prevent unauthorized access.</p>
<hr />
]]></content:encoded></item><item><title><![CDATA[How to Integrate Sentry with Django for Effective Error Handling]]></title><description><![CDATA[Sentry is a powerful error tracking tool for real-time monitoring of errors and exceptions. Integrating Sentry into your Django project allows you to manage errors effectively. Start by signing up on Sentry's website, creating a new project, and conf...]]></description><link>https://sudipbhandari.hashnode.dev/how-to-integrate-sentry-with-django-for-effective-error-handling</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/how-to-integrate-sentry-with-django-for-effective-error-handling</guid><category><![CDATA[Django]]></category><category><![CDATA[sentry]]></category><category><![CDATA[error handling]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Fri, 02 Aug 2024 14:25:19 GMT</pubDate><content:encoded><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721271596141/ac2157b1-ba32-4595-bc8a-ce3bbdbbfc71.jpeg" alt /></p>
<p>Sentry is a powerful error tracking tool for real-time monitoring of errors and exceptions. Integrating Sentry into your Django project allows you to manage errors effectively. Start by signing up on Sentry's website, creating a new project, and configuring your Django application to send error reports to Sentry's dashboard.</p>
<h3 id="heading-getting-started-with-sentry">Getting Started with Sentry</h3>
<ol>
<li><p><strong>Sign Up</strong>: Visit Sentry's website and create an account.</p>
</li>
<li><p><strong>Create a Project</strong>: Define a new project for your Django application.</p>
</li>
<li><p><strong>Configure Django</strong>: Install the Sentry SDK via pip and configure your settings file to initialize Sentry.</p>
</li>
<li><p><strong>Monitoring Errors</strong>: Sentry captures errors and exceptions, providing detailed reports that help in debugging and resolving issues promptly.</p>
</li>
</ol>
<h4 id="heading-1-install-sentry-sdk">1. Install Sentry SDK</h4>
<p>First, install the Sentry SDK for Python using pip:</p>
<pre><code class="lang-bash">pip install sentry-sdk
</code></pre>
<h4 id="heading-2-configure-sentry-in-django-settings">2. Configure Sentry in Django Settings</h4>
<p>In your Django project's <a target="_blank" href="http://settings.py"><code>settings.py</code></a>, configure Sentry with your Sentry DSN (Data Source Name):</p>
<pre><code class="lang-python"><span class="hljs-comment"># settings.py</span>

<span class="hljs-keyword">import</span> sentry_sdk
<span class="hljs-keyword">from</span> sentry_sdk.integrations.django <span class="hljs-keyword">import</span> DjangoIntegration

<span class="hljs-comment"># Initialize Sentry SDK</span>
sentry_sdk.init(
    dsn=<span class="hljs-string">'YOUR_SENTRY_DSN_HERE'</span>, 
    integrations=[DjangoIntegration()]
)

<span class="hljs-comment"># Your Django settings configuration continues...</span>
</code></pre>
<p>Replace <code>'YOUR_SENTRY_DSN_HERE'</code> with your actual Sentry DSN, which you can obtain from your Sentry project settings.</p>
<h4 id="heading-3-create-a-django-view-with-error-handling">3. Create a Django View with Error Handling</h4>
<p>Next, create a Django view that intentionally raises an error:</p>
<pre><code class="lang-python"><span class="hljs-comment"># views.py</span>

<span class="hljs-keyword">from</span> django.shortcuts <span class="hljs-keyword">import</span> render

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_view</span>(<span class="hljs-params">request</span>):</span>
    <span class="hljs-keyword">try</span>:
        <span class="hljs-comment"># Simulating an intentional error for demonstration</span>
        result = <span class="hljs-number">1</span> / <span class="hljs-number">0</span>  <span class="hljs-comment"># This will raise a ZeroDivisionError</span>
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        <span class="hljs-comment"># Capture the exception and send it to Sentry</span>
        sentry_sdk.capture_exception(e)

    context = {
        <span class="hljs-string">'result'</span>: result  <span class="hljs-comment"># This will not be reached due to the error</span>
    }
    <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'test.html'</span>, context)
</code></pre>
<h4 id="heading-4-define-url-configuration">4. Define URL Configuration</h4>
<p>Configure the URL routing to map the view:</p>
<pre><code class="lang-python"><span class="hljs-comment"># urls.py</span>

<span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> path
<span class="hljs-keyword">from</span> .views <span class="hljs-keyword">import</span> test_view

urlpatterns = [
    path(<span class="hljs-string">'test/'</span>, test_view, name=<span class="hljs-string">'test_view'</span>),
]
</code></pre>
<h4 id="heading-5-create-a-template-to-display-error-information">5. Create a Template to Display Error Information</h4>
<p>Create a template (<code>test.html</code>) to display a user-friendly error message:</p>
<pre><code class="lang-xml"><span class="hljs-comment">&lt;!-- test.html --&gt;</span>

<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Error Test<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Error Test<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>An error occurred while processing your request.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<h3 id="heading-explanation">Explanation:</h3>
<ul>
<li><p><strong>Sentry Initialization</strong>: <code>sentry_sdk.init()</code> initializes Sentry with Django integration. It captures all unhandled exceptions and reports them to Sentry.</p>
</li>
<li><p><strong>Error Handling in View</strong>: The <code>test_view</code> function demonstrates handling an error (<code>ZeroDivisionError</code> in this case) within a <code>try-except</code> block. The <code>capture_exception</code> method sends the exception details to Sentry.</p>
</li>
<li><p><strong>Template</strong>: <code>test.html</code> serves as a basic error page to inform users about the error.</p>
</li>
</ul>
<h3 id="heading-benefits">Benefits:</h3>
<p>Integrating Sentry with Django allows you to:</p>
<ul>
<li><p><strong>Proactively Monitor Errors</strong>: Sentry captures errors in real-time, providing insights into exceptions occurring in your application.</p>
</li>
<li><p><strong>Effective Debugging</strong>: Detailed error reports (including stack traces, request details) help in quickly identifying and resolving issues.</p>
</li>
</ul>
<p>This setup ensures that your Django application remains stable and reliable, enhancing both development and production environments with robust error handling and monitoring capabilities. Adjust the error handling and reporting strategy based on your application's specific requirements and Sentry's features.</p>
]]></content:encoded></item><item><title><![CDATA[How to Become an ASP.NET Core Developer in 2024: A Step-by-Step Guide]]></title><description><![CDATA[https://roadmap.sh/aspnet-core

For developers immersed in the Microsoft ecosystem, ASP.NET Core has emerged as a powerful and flexible framework for building modern web applications. The intricate mind map before us offers a comprehensive overview o...]]></description><link>https://sudipbhandari.hashnode.dev/how-to-become-an-aspnet-core-developer-in-2024-a-step-by-step-guide</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/how-to-become-an-aspnet-core-developer-in-2024-a-step-by-step-guide</guid><category><![CDATA[roadmap asp.net]]></category><category><![CDATA[Roadmap]]></category><category><![CDATA[guide]]></category><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Thu, 06 Jun 2024 15:55:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1717689258690/37620133-bb92-46f3-9c9c-c278a7117276.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://roadmap.sh/aspnet-core">https://roadmap.sh/aspnet-core</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717689043685/4f29c93e-4c5d-44f3-bc22-4bdf867ac68b.jpeg" alt class="image--center mx-auto" /></p>
<p>For developers immersed in the Microsoft ecosystem, <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core has emerged as a powerful and flexible framework for building modern web applications. The intricate mind map before us offers a comprehensive overview of the various components and concepts that underpin this robust platform. At its core, we find the fundamental building blocks such as the HTTP/HTTPS protocols, data access layers, and the MVC (Model-View-Controller) architecture. Branching out from this foundation are the myriad libraries, tools, and technologies that enable developers to craft feature-rich and scalable web solutions. From Entity Framework for seamless data management to SignalR for real-time communication, the diagram illustrates the breadth of <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core's capabilities. Additionally, it highlights the importance of sound development practices, encompassing areas like coding standards, security protocols, and rigorous testing methodologies. Whether you're a seasoned <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core developer or embarking on your first project, this mind map serves as a valuable reference, encapsulating the framework's depth and versatility in a visually compelling format.</p>
]]></content:encoded></item><item><title><![CDATA[The Power of Specialization in Programming Career: A Comprehensive Guide]]></title><description><![CDATA[One common misconception in the world of web development is the need to learn everything. With countless languages, frameworks, and tools available, many aspiring developers feel overwhelmed and believe they must master it all to succeed. However, th...]]></description><link>https://sudipbhandari.hashnode.dev/the-power-of-specialization-in-programming-career-a-comprehensive-guide</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/the-power-of-specialization-in-programming-career-a-comprehensive-guide</guid><category><![CDATA[Programming Tips]]></category><category><![CDATA[Career]]></category><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Fri, 24 May 2024 01:34:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716514349763/c4409e9e-ad1e-4fcd-93b9-7ba442ca5b36.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One common misconception in the world of web development is the need to learn everything. With countless languages, frameworks, and tools available, many aspiring developers feel overwhelmed and believe they must master it all to succeed. However, this approach can be counterproductive. Specialization, rather than an extensive breadth of knowledge, is the key to becoming a proficient and valuable developer.</p>
<h3 id="heading-understanding-the-learning-landscape"><strong>Understanding the Learning Landscape</strong></h3>
<p>The web development field is vast and ever-evolving. Trying to master every aspect is not only impractical but also unnecessary. Instead, it’s more beneficial to treat your learning journey as a targeted exploration. By focusing on specific areas of interest and necessity, you can build a strong, specialized skill set that sets you apart in the job market.</p>
<h3 id="heading-why-specialization-matters"><strong>Why Specialization Matters</strong></h3>
<p>Specialization is crucial in the professional world. Employers are looking for developers with deep, comprehensive knowledge in particular areas rather than those who have a shallow understanding of many different technologies. Specialization allows you to become an expert, capable of solving complex problems and delivering high-quality work efficiently.</p>
<h3 id="heading-quality-over-quantity"><strong>Quality Over Quantity</strong></h3>
<p>A common fallacy in tech learning is equating the number of technologies known to proficiency. However, the true measure of expertise lies in the depth of understanding and the ability to apply knowledge effectively. Think of it as building a house: you’d prefer a contractor who has mastered their craft rather than someone who has only dabbled in various construction techniques. Similarly, employers seek developers with deep expertise in specific areas who can tackle complex challenges with confidence.</p>
<h3 id="heading-steps-to-specialize-effectively"><strong>Steps to Specialize Effectively</strong></h3>
<ol>
<li><p><strong>Identify Your Interests:</strong> Specialization starts with introspection. What aspects of web development excite you? Are you drawn to front-end design, back-end architecture, or database management? Passion will drive your learning and mastery.</p>
</li>
<li><p><strong>Market Research:</strong> After identifying your interests, research the current demand in the job market. Different technologies are more prevalent in different regions and industries. Understanding these trends will help you choose a specialization that is both interesting and in demand.</p>
</li>
<li><p><strong>Choose Your Focus:</strong> With your interests and market demand in mind, select a focus area. This could be a specific programming language like JavaScript or Python, a framework like React or Django, or a niche skill like cybersecurity or e-commerce development.</p>
</li>
<li><p><strong>Deep Dive into Your Field:</strong> Immerse yourself in your chosen specialization. Utilize courses, tutorials, and documentation. Engage with online communities to deepen your understanding and stay updated on best practices and new developments.</p>
</li>
<li><p><strong>Build a Portfolio:</strong> As you learn, create projects that showcase your skills. A well-rounded portfolio is crucial as it provides tangible evidence of your capabilities to potential employers or clients.</p>
</li>
<li><p><strong>Stay Updated:</strong> The tech landscape is continually changing. Stay informed about emerging trends and advancements within your specialization to keep your skills relevant and cutting-edge.</p>
</li>
<li><p><strong>Network and Collaborate:</strong> Networking is a vital aspect of career growth. Connect with professionals on platforms like LinkedIn, attend meetups and workshops, and collaborate on projects. These connections can lead to new opportunities and insights.</p>
</li>
</ol>
<h3 id="heading-final-thoughts"><strong>Final Thoughts</strong></h3>
<p>Breaking into the web development industry is increasingly challenging, making specialization more important than ever. By focusing your learning efforts, staying updated on industry trends, and building a strong portfolio, you can position yourself as a valuable asset in the tech world. Quality and depth of knowledge will always outweigh a superficial understanding of numerous technologies. Embrace specialization, and watch your web development career flourish.</p>
]]></content:encoded></item><item><title><![CDATA[Getting started with Django]]></title><description><![CDATA[Install Python
 python --version


PIP (PIP is the package manager which is included in Python from 3.4)
 pip --version

 if PIP is not installed install by
 curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py

 python get-pip.py


Creating a vir...]]></description><link>https://sudipbhandari.hashnode.dev/getting-started-with-django</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/getting-started-with-django</guid><category><![CDATA[Devops]]></category><category><![CDATA[Python]]></category><category><![CDATA[install django]]></category><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Mon, 06 May 2024 16:28:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1715014721248/8d83ea70-5c1d-4fdf-a31c-341912f8cee5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<ol>
<li><p>Install Python</p>
<pre><code class="lang-python"> python --version
</code></pre>
</li>
<li><p>PIP (PIP is the package manager which is included in Python from 3.4)</p>
<pre><code class="lang-python"> pip --version
</code></pre>
<p> if PIP is not installed install by</p>
<pre><code class="lang-python"> curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
</code></pre>
<pre><code class="lang-python"> python get-pip.py
</code></pre>
</li>
<li><p>Creating a virtual environment</p>
<pre><code class="lang-python"> py -m venv myworld
</code></pre>
<p> Then you have to activate the environment, by typing this command:</p>
<p> Windows:</p>
<pre><code class="lang-python"> myworld\Scripts\activate.bat
</code></pre>
<p> Unix/MacOS:</p>
<pre><code class="lang-python"> source myworld/bin/activate
</code></pre>
</li>
<li><p>Install Django</p>
<pre><code class="lang-python"> python -m pip install Django
</code></pre>
<p> Check django version</p>
<pre><code class="lang-python"> django-admin --version
</code></pre>
</li>
<li><p>First django project</p>
<pre><code class="lang-python"> django-admin startproject quiz
</code></pre>
</li>
<li><p>Running the server</p>
<pre><code class="lang-python"> py manage.py runserver
</code></pre>
</li>
<li><p>Create first app</p>
<pre><code class="lang-python"> py manage.py startapp Questions
</code></pre>
<p> Promoting: <a target="_blank" href="https://digitalpatroapp.com">Digital Patro Nepali Calendar</a><br /> Github: https://github.com/digitalpatro</p>
<p> %[https://www.youtube.com/watch?v=2z3gAXiEoXQ]</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Rock, paper, scissor in python]]></title><description><![CDATA[import random

def get_player_choice():
    choices = ['rock', 'paper', 'scissors']
    player_choice = input("Choose rock, paper, or scissors: ").lower()
    while player_choice not in choices:
        player_choice = input("Invalid choice. Please c...]]></description><link>https://sudipbhandari.hashnode.dev/rock-paper-scissor-in-python</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/rock-paper-scissor-in-python</guid><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Mon, 06 May 2024 07:04:45 GMT</pubDate><content:encoded><![CDATA[<pre><code class="lang-python"><span class="hljs-keyword">import</span> random

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_player_choice</span>():</span>
    choices = [<span class="hljs-string">'rock'</span>, <span class="hljs-string">'paper'</span>, <span class="hljs-string">'scissors'</span>]
    player_choice = input(<span class="hljs-string">"Choose rock, paper, or scissors: "</span>).lower()
    <span class="hljs-keyword">while</span> player_choice <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> choices:
        player_choice = input(<span class="hljs-string">"Invalid choice. Please choose rock, paper, or scissors: "</span>).lower()
    <span class="hljs-keyword">return</span> player_choice

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_computer_choice</span>():</span>
    choices = [<span class="hljs-string">'rock'</span>, <span class="hljs-string">'paper'</span>, <span class="hljs-string">'scissors'</span>]
    computer_choice = random.choice(choices)
    <span class="hljs-keyword">return</span> computer_choice

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">determine_winner</span>(<span class="hljs-params">player_choice, computer_choice</span>):</span>
    <span class="hljs-keyword">if</span> player_choice == computer_choice:
        <span class="hljs-keyword">return</span> <span class="hljs-string">"It's a tie!"</span>
    <span class="hljs-keyword">elif</span> (player_choice == <span class="hljs-string">'rock'</span> <span class="hljs-keyword">and</span> computer_choice == <span class="hljs-string">'scissors'</span>) <span class="hljs-keyword">or</span> \
         (player_choice == <span class="hljs-string">'paper'</span> <span class="hljs-keyword">and</span> computer_choice == <span class="hljs-string">'rock'</span>) <span class="hljs-keyword">or</span> \
         (player_choice == <span class="hljs-string">'scissors'</span> <span class="hljs-keyword">and</span> computer_choice == <span class="hljs-string">'paper'</span>):
        <span class="hljs-keyword">return</span> <span class="hljs-string">"You win!"</span>
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Computer wins!"</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">play_game</span>():</span>
    print(<span class="hljs-string">"Welcome to Rock-Paper-Scissors!"</span>)
    player_choice = get_player_choice()
    computer_choice = get_computer_choice()
    print(<span class="hljs-string">f"You chose <span class="hljs-subst">{player_choice}</span>."</span>)
    print(<span class="hljs-string">f"The computer chose <span class="hljs-subst">{computer_choice}</span>."</span>)
    result = determine_winner(player_choice, computer_choice)
    print(result)

play_game()
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Exception Handling in Python]]></title><description><![CDATA[The try block lets you test a block of code for errors.
The except block lets you handle the error.
The finally block lets you execute code, regardless of the result of the try- and except blocks.
try:
  print(x)
except:
  print("Something went wrong...]]></description><link>https://sudipbhandari.hashnode.dev/exception-handling-in-python</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/exception-handling-in-python</guid><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Mon, 06 May 2024 07:02:35 GMT</pubDate><content:encoded><![CDATA[<p>The <code>try</code> block lets you test a block of code for errors.</p>
<p>The <code>except</code> block lets you handle the error.</p>
<p>The <code>finally</code> block lets you execute code, regardless of the result of the try- and except blocks.</p>
<pre><code class="lang-python"><span class="hljs-keyword">try</span>:
  print(x)
<span class="hljs-keyword">except</span>:
  print(<span class="hljs-string">"Something went wrong"</span>)
<span class="hljs-keyword">finally</span>:
  print(<span class="hljs-string">"The 'try except' is finished"</span>)
</code></pre>
<pre><code class="lang-python"><span class="hljs-keyword">try</span>:
    <span class="hljs-comment"># code that might raise an exception</span>
    result = <span class="hljs-number">10</span> / <span class="hljs-number">0</span>
<span class="hljs-keyword">except</span> ZeroDivisionError:
    <span class="hljs-comment"># code to handle the exception</span>
    print(<span class="hljs-string">"Error: Division by zero"</span>)
</code></pre>
<pre><code class="lang-python"><span class="hljs-keyword">try</span>:
    number = int(input(<span class="hljs-string">"Enter a number: "</span>))
    result = <span class="hljs-number">10</span> / number
<span class="hljs-keyword">except</span> ValueError:
    print(<span class="hljs-string">"Error: Invalid input"</span>)
<span class="hljs-keyword">except</span> ZeroDivisionError:
    print(<span class="hljs-string">"Error: Division by zero"</span>)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">f"Result: <span class="hljs-subst">{result}</span>"</span>)
</code></pre>
<p>Different types of exception in python</p>
<ul>
<li><p><strong>SyntaxError</strong>: This exception is raised when there is a syntax error in the Python code. It occurs when the code violates the rules of the Python language syntax.</p>
</li>
<li><p><strong>IndentationError</strong>: This exception is raised when there is an incorrect indentation in the Python code. Indentation is crucial in Python as it is used to define code blocks.</p>
</li>
<li><p><strong>NameError</strong>: This exception is raised when an identifier (e.g., a variable or function name) is not found in the local or global namespace.</p>
</li>
<li><p><strong>TypeError</strong>: This exception is raised when an operation or function is applied to an object of an inappropriate type.</p>
</li>
<li><p><strong>ValueError</strong>: This exception is raised when a function receives an argument of the correct type but an inappropriate value.</p>
</li>
<li><p><strong>IndexError</strong>: This exception is raised when an index is out of range for a sequence (e.g., list, string, or tuple).</p>
</li>
<li><p><strong>KeyError</strong>: This exception is raised when a dictionary key is not found in the dictionary.</p>
</li>
<li><p><strong>ZeroDivisionError</strong>: This exception is raised when an attempt is made to divide a number by zero.</p>
</li>
<li><p><strong>ImportError</strong>: This exception is raised when an imported module or package is not found or cannot be loaded.</p>
</li>
<li><p><strong>IOError</strong>: This exception is raised when an input/output operation (e.g., reading or writing to a file) fails.</p>
</li>
<li><p><strong>FileNotFoundError</strong>: This exception is a subclass of <code>IOError</code> and is raised when a file or directory is not found.</p>
</li>
<li><p><strong>AttributeError</strong>: This exception is raised when an attribute reference or assignment fails.</p>
</li>
<li><p><strong>KeyboardInterrupt</strong>: This exception is raised when the user interrupts the program's execution, usually by pressing <code>Ctrl+C</code>.</p>
</li>
<li><p><strong>MemoryError</strong>: This exception is raised when the program runs out of memory.</p>
</li>
<li><p><strong>OverflowError</strong>: This exception is raised when an arithmetic operation exceeds the maximum limit for a numeric type.</p>
</li>
<li><p><strong>RecursionError</strong>: This exception is raised when the maximum recursion depth is exceeded.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Functions and Classes in Python]]></title><description><![CDATA[Defining a function
def keyword, followed by the function name and parentheses (). Any parameters go inside the parentheses.
def function_name(parameters):
    """
    Docstring: Brief description of the function
    """
    # Function body
    # Cod...]]></description><link>https://sudipbhandari.hashnode.dev/functions-and-classes-in-python</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/functions-and-classes-in-python</guid><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Mon, 06 May 2024 06:24:14 GMT</pubDate><content:encoded><![CDATA[<p><strong>Defining a function</strong></p>
<p><code>def</code> keyword, followed by the function name and parentheses <code>()</code>. Any parameters go inside the parentheses.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">function_name</span>(<span class="hljs-params">parameters</span>):</span>
    <span class="hljs-string">"""
    Docstring: Brief description of the function
    """</span>
    <span class="hljs-comment"># Function body</span>
    <span class="hljs-comment"># Code block</span>
    <span class="hljs-keyword">return</span> value
</code></pre>
<p><strong>Calling a function</strong></p>
<p>function name followed by parentheses <code>()</code></p>
<pre><code class="lang-python">function_name(arguments)
</code></pre>
<p><strong>Parameters and Arguments</strong></p>
<p>The values you pass into a function when calling it are called arguments. The variables listed in the function definition are called parameters.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">greet</span>(<span class="hljs-params">name, greeting=<span class="hljs-string">"Hello"</span></span>):</span>  <span class="hljs-comment"># name is a parameter, greeting is a parameter with a default value</span>
    print(<span class="hljs-string">f"<span class="hljs-subst">{greeting}</span>, <span class="hljs-subst">{name}</span>!"</span>)

greet(<span class="hljs-string">"Alice"</span>)  <span class="hljs-comment"># Alice is the argument</span>
greet(<span class="hljs-string">"Bob"</span>, <span class="hljs-string">"Hi"</span>)  <span class="hljs-comment"># Bob is the argument, Hi is the argument</span>
</code></pre>
<p><strong>\</strong>Arbitrary Arguments (args)<em>*</em></p>
<p>If you don't know how many arguments will be passed to a function, you can use the <code>*args</code> syntax to collect them into a tuple.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">print_numbers</span>(<span class="hljs-params">*args</span>):</span>
    <span class="hljs-keyword">for</span> arg <span class="hljs-keyword">in</span> args:
        print(arg)

print_numbers(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>)  <span class="hljs-comment"># Output: 1 2 3</span>
</code></pre>
<p><strong><em>\</em>*Keyword Arguments (kwargs)*</strong></p>
<p>You can also collect arbitrary keyword arguments into a dictionary using the <code>**kwargs</code> syntax.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">print_info</span>(<span class="hljs-params">**kwargs</span>):</span>
    <span class="hljs-keyword">for</span> key, value <span class="hljs-keyword">in</span> kwargs.items():
        print(<span class="hljs-string">f"<span class="hljs-subst">{key}</span>: <span class="hljs-subst">{value}</span>"</span>)

print_info(name=<span class="hljs-string">"Alice"</span>, age=<span class="hljs-number">25</span>)  <span class="hljs-comment"># Output: name: Alice, age: 25</span>
</code></pre>
<p><strong>Lambda Functions</strong></p>
<p>Python supports the creation of anonymous functions (lambda functions). These are small, one-line functions.</p>
<pre><code class="lang-python">square = <span class="hljs-keyword">lambda</span> x: x ** <span class="hljs-number">2</span>
print(square(<span class="hljs-number">5</span>))
</code></pre>
<h2 id="heading-python-classesobjects">Python Classes/Objects</h2>
<p>Python is an object oriented programming language.</p>
<p>Almost everything in Python is an object, with its properties and methods.</p>
<p>A Class is like an object constructor, or a "blueprint" for creating objects.</p>
<h2 id="heading-define-python-class">Define Python Class</h2>
<p>We use the <code>class</code><a target="_blank" href="https://www.programiz.com/python-programming/keywords-identifier">keyword to cr</a>eate a class i<a target="_blank" href="https://www.programiz.com/python-programming/keywords-identifier">n Pytho</a>n. For example,</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ClassName</span>:</span>
    <span class="hljs-comment"># class definition</span>
</code></pre>
<p>Here, we have created a class named <code>ClassNam</code><a target="_blank" href="https://www.programiz.com/python-programming/keywords-identifier"><code>e</code>.</a></p>
<p><a target="_blank" href="https://www.programiz.com/python-programming/keywords-identifier">Let</a>'s see an example,</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Room</span>:</span>
    length = <span class="hljs-number">0</span>
    breadth = <span class="hljs-number">0</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">area</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> self.length * self.breadth
</code></pre>
<ol>
<li><p><code>Room</code> - the name of the class</p>
</li>
<li><p><code>length and breadth</code> are the attributes of the class</p>
</li>
<li><p><code>area</code> is the method of the class</p>
</li>
</ol>
<p>Understanding <strong>init</strong> method</p>
<pre><code class="lang-python"> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, length=<span class="hljs-number">0</span>, breadth=<span class="hljs-number">0</span></span>):</span>
        self.length = length
        self.breadth = breadth
</code></pre>
<p>It is the constructor of the class Room. Meaning it is initialized everytime when the class is called(when object is created)</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Room</span>:</span>


    <span class="hljs-comment"># Constructor</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, length=<span class="hljs-number">0</span>, breadth=<span class="hljs-number">0</span></span>):</span>
        self.length = length
        self.breadth = breadth

    <span class="hljs-comment"># Instance methods</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">area</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> self.length * self.breadth

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">perimeter</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> <span class="hljs-number">2</span> * (self.length + self.breadth)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">print_details</span>(<span class="hljs-params">self</span>):</span>
        print(<span class="hljs-string">f"Room dimensions: <span class="hljs-subst">{self.length}</span> x <span class="hljs-subst">{self.breadth}</span> meters"</span>)
        print(<span class="hljs-string">f"Area: <span class="hljs-subst">{self.area()}</span> square meters"</span>)
        print(<span class="hljs-string">f"Perimeter: <span class="hljs-subst">{self.perimeter()}</span> meters"</span>)



<span class="hljs-comment"># Creating instances (objects) of the Room class</span>
room1 = Room(<span class="hljs-number">5</span>, <span class="hljs-number">4</span>)
room2 = Room(<span class="hljs-number">3</span>, <span class="hljs-number">3</span>)

<span class="hljs-comment"># Calling instance methods</span>
room1.print_details()
print()
room2.print_details()
print()
</code></pre>
<p><strong>Inheritance:</strong></p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Room</span>:</span>
    <span class="hljs-comment"># Class attribute</span>
    num_rooms = <span class="hljs-number">0</span>

    <span class="hljs-comment"># Constructor</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, length=<span class="hljs-number">0</span>, breadth=<span class="hljs-number">0</span></span>):</span>
        self.length = length
        self.breadth = breadth
        Room.num_rooms += <span class="hljs-number">1</span>

    <span class="hljs-comment"># Instance methods</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">area</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> self.length * self.breadth

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">perimeter</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> <span class="hljs-number">2</span> * (self.length + self.breadth)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">print_details</span>(<span class="hljs-params">self</span>):</span>
        print(<span class="hljs-string">f"Room dimensions: <span class="hljs-subst">{self.length}</span> x <span class="hljs-subst">{self.breadth}</span> meters"</span>)
        print(<span class="hljs-string">f"Area: <span class="hljs-subst">{self.area()}</span> square meters"</span>)
        print(<span class="hljs-string">f"Perimeter: <span class="hljs-subst">{self.perimeter()}</span> meters"</span>)

<span class="hljs-comment"># Child class inheriting from Room</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bedroom</span>(<span class="hljs-params">Room</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, length, breadth, num_beds</span>):</span>
        super().__init__(length, breadth)
        self.num_beds = num_beds

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">print_details</span>(<span class="hljs-params">self</span>):</span>
        super().print_details()
        print(<span class="hljs-string">f"Number of beds: <span class="hljs-subst">{self.num_beds}</span>"</span>)

<span class="hljs-comment"># Creating instances of the classes</span>
room1 = Room(<span class="hljs-number">5</span>, <span class="hljs-number">4</span>)
bedroom1 = Bedroom(<span class="hljs-number">4</span>, <span class="hljs-number">3</span>, <span class="hljs-number">2</span>)

<span class="hljs-comment"># Calling instance methods</span>
room1.print_details()
print()
bedroom1.print_details()
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Install Python on Windows, Linux and Mac OS]]></title><description><![CDATA[Step 1:
Download the Python Installer:
The first step is to download the latest version of Python from the official Python website (https://www.python.org/downloads/windows/). The website will automatically detect your operating system and offer the ...]]></description><link>https://sudipbhandari.hashnode.dev/install-python-on-windows-linux-and-mac-os</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/install-python-on-windows-linux-and-mac-os</guid><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Mon, 06 May 2024 01:44:32 GMT</pubDate><content:encoded><![CDATA[<p>Step 1:</p>
<p>Download the Python Installer:</p>
<p>The first step is to download the latest version of Python from the official Python website (<a target="_blank" href="https://www.python.org/downloads/windows/">https://www.python.org/downloads/windows/</a>)<a target="_blank" href="https://www.python.org/downloads/windows/">. The website will automatically detect y</a>our operating system and offer the appropriate installer for your system (32-bit or 64-bit).</p>
<p>Step 2:</p>
<p>Run the Installer Once the installer has been downloadeddouble-click on it to run the installation process. <a target="_blank" href="https://www.python.org/downloads/windows/">You may be prompted by the User Account C</a>ontrol (UAC) to allow the installation. Click Yes to proceed.</p>
<p>Step 3:</p>
<p>During the installation process, you'll have the option to customize the installation. It's highly recommended to check the box <a target="_blank" href="https://www.python.org/downloads/windows/">next to "Add Python to PATH" before proc</a>eeding. This will ensure that Python is added to your system's PATH variable, making it easier to run Python from the command prompt.</p>
<p>Step 4: <a target="_blank" href="https://www.python.org/downloads/windows/">Install Python After selecting your desir</a>ed installation settings, click Install to begin the installation process. This may take a few minutes.</p>
<p>Step 5: Verify the <a target="_blank" href="https://www.python.org/downloads/windows/">Installation Once the installation is com</a>plete, you can verify that Python has been installed correctly by opening the Command Prompt (search for "cmd" in <a target="_blank" href="https://www.python.org/downloads/windows/">the Start menu) and typing the following</a> command:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">python</span> <span class="hljs-selector-tag">--version</span>
</code></pre>
<p>Press Enter, and you should see the version of Python you installed displayed in the output.</p>
<p>Alternate Installation Method: Microsoft Store If you prefer, you can also inst<a target="_blank" href="https://www.python.org/downloads/windows/">all Python on Windows using the Microsoft</a> Store. Search for "Python" in the Microsoft Store, f<a target="_blank" href="https://www.python.org/downloads/windows/">ind the latest version of Python 3.11, an</a>d click Install.</p>
<p>ubuntu/Debian</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">sudo</span> <span class="hljs-selector-tag">apt-get</span> <span class="hljs-selector-tag">install</span> <span class="hljs-selector-tag">python3</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Conditional statements and loops in python]]></title><description><![CDATA[Some of the python acceptable conditions

Equals: a == b

Not Equals: a != b

Less than: a < b

Less than or equal to: a <= b

Greater than: a > b

Greater than or equal to: a >= b


if statement:
if condition:
    # code block
    # executed if cond...]]></description><link>https://sudipbhandari.hashnode.dev/conditional-statements-and-loops-in-python</link><guid isPermaLink="true">https://sudipbhandari.hashnode.dev/conditional-statements-and-loops-in-python</guid><dc:creator><![CDATA[Sudip Bhandari]]></dc:creator><pubDate>Mon, 06 May 2024 01:42:17 GMT</pubDate><content:encoded><![CDATA[<p>Some of the python acceptable conditions</p>
<ul>
<li><p>Equals: a == b</p>
</li>
<li><p>Not Equals: a != b</p>
</li>
<li><p>Less than: a &lt; b</p>
</li>
<li><p>Less than or equal to: a &lt;= b</p>
</li>
<li><p>Greater than: a &gt; b</p>
</li>
<li><p>Greater than or equal to: a &gt;= b</p>
</li>
</ul>
<p><strong>if statement:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> condition:
    <span class="hljs-comment"># code block</span>
    <span class="hljs-comment"># executed if condition is true</span>
</code></pre>
<p><strong>else statement:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> condition:
    <span class="hljs-comment"># code block 1</span>
<span class="hljs-keyword">else</span>:
    <span class="hljs-comment"># code block 2</span>
</code></pre>
<p><strong>elif statement:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> condition1:
    <span class="hljs-comment"># code block 1</span>
<span class="hljs-keyword">elif</span> condition2:
    <span class="hljs-comment"># code block 2</span>
<span class="hljs-keyword">else</span>:
    <span class="hljs-comment"># code block 3</span>
</code></pre>
<p>Loops:</p>
<p>There are two primitive looping statements in python</p>
<p>a. for loop</p>
<p>b. while loop</p>
<p><strong>For loop:</strong></p>
<p>The <code>for</code> loop is used to iterate over a sequence (such as a list, tuple, or string) or other iterable objects.</p>
<pre><code class="lang-python">fruits = [<span class="hljs-string">"apple"</span>, <span class="hljs-string">"banana"</span>, <span class="hljs-string">"cherry"</span>]
<span class="hljs-keyword">for</span> fruit <span class="hljs-keyword">in</span> fruits:
    print(fruit)
</code></pre>
<p>You can also use the <code>range()</code> function to generate a sequence of numbers:</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">5</span>):
    print(i)
</code></pre>
<p><strong>While Loop</strong> The <code>while</code> loop executes a block of code as long as a given condition is true.</p>
<pre><code class="lang-python">count = <span class="hljs-number">0</span>
<span class="hljs-keyword">while</span> count &lt; <span class="hljs-number">5</span>:
    print(count)
    count += <span class="hljs-number">1</span>
</code></pre>
<p><strong>Break Statement</strong> The <code>break</code> statement is used to exit a loop prematurely.</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>):
    <span class="hljs-keyword">if</span> i == <span class="hljs-number">5</span>:
        <span class="hljs-keyword">break</span>
    print(i)  <span class="hljs-comment"># Output: 0 1 2 3 4</span>
</code></pre>
<p><strong>Continue Statement</strong> The <code>continue</code> statement is used to skip the current iteration of a loop and move to the next one.</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>):
    <span class="hljs-keyword">if</span> i == <span class="hljs-number">5</span>:
        <span class="hljs-keyword">continue</span>
    print(i)  <span class="hljs-comment"># Output: 0 1 2 3 4 6 7 8 9</span>
</code></pre>
<p><strong>Else Clause</strong> You can use an <code>else</code> clause with <code>for</code> and <code>while</code> loops. The <code>else</code> block is executed if the loop completes normally (without encountering a <code>break</code> statement).</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">5</span>):
    print(i)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">"Loop completed"</span>)
</code></pre>
<p><strong>Nested Loops</strong> You can have one loop inside another loop. This is known as a nested loop.</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">3</span>):
    <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> range(<span class="hljs-number">3</span>):
        print(i, j)
</code></pre>
]]></content:encoded></item></channel></rss>