হাসিব, তোমার প্রোভাইড করা লেকচার ট্রান্সক্রিপ্টটি আমি খুব গভীরভাবে অ্যানালাইজ করেছি। এই লেকচারে মূলত HTTP Request-এর মাধ্যমে ব্রাউজার থেকে সার্ভারে ডেটা পাঠানোর অন্যতম একটি গুরুত্বপূর্ণ উপায়— Query String নিয়ে আলোচনা করা হয়েছে।

ভবিষ্যতে দ্রুত রিভিশন দেওয়ার জন্য নিচে প্রথমে একটি কুইক সামারি এবং এরপর প্রতিটি বিষয়ের ইন-ডেপ্ত ব্রেকডাউন দেওয়া হলো।


📝 Quick Summary for Revision

  • Query String: এটি হলো URL-এর শেষে যুক্ত করা একটি সিনট্যাক্স, যার মাধ্যমে ব্রাউজার থেকে সার্ভারে প্যারামিটার বা Key-Value পেয়ার পাঠানো হয়।
  • Structure: URL-এর পাথ (Path) এবং Query String-কে আলাদা করা হয় একটি কোশ্চেন মার্ক (?) দিয়ে। একাধিক Key-Value পেয়ারকে আলাদা করা হয় অ্যাম্পারস্যান্ড (&) চিহ্ন দিয়ে। URL-এর কোথাও কোনো Space অ্যালাউড নয়।
  • GET vs POST: GET Request-এর ক্ষেত্রে Query String সরাসরি URL-এর অংশ হিসেবে যুক্ত থাকে। কিন্তু POST Request-এর ক্ষেত্রে এটি URL-এ থাকে না, বরং Request Body-র ভেতরে পাঠানো হয়।
  • context.Request.Query: ASP.NET Core-এ এটি IQueryCollection (এক ধরণের Dictionary) টাইপের একটি প্রোপার্টি, যা রিকোয়েস্টের সব Query String প্যারামিটার ধারণ করে।
  • Safe Reading: কোনো ভ্যালু রিড করার আগে ContainsKey() মেথড দিয়ে Key-টি আসলে রিকোয়েস্টে আছে কি না, তা চেক করে নেওয়া উচিত, যা কোডকে Error-free রাখে।
  • Real-world Use Case: ডাটাবেজ থেকে নির্দিষ্ট কোনো ডেটা (যেমন: কোনো নির্দিষ্ট Course ID বা Product ID-র ডিটেইলস) কুয়েরি করে এনে পেজে দেখানোর জন্য এটি ব্যবহার করা হয়।

🧠 Comprehensive Breakdown

এখানে লেকচারের প্রতিটি কনসেপ্ট বিস্তারিতভাবে ব্যাখ্যা করা হলো এবং এর পেছনের “Why” (কেন এবং কীভাবে কাজ করে) যুক্তিগুলো তুলে ধরা হলো।

1. What is a Query String? [Priority: 10/10]

Why do we need this? ধরে নাও, তুমি একটি ওয়েবসাইট স্ক্রোল করছো যেখানে হাজার হাজার প্রোডাক্ট বা কোর্স আছে। এখন তুমি যখন নির্দিষ্ট কোনো কোর্সের ওপর ক্লিক করবে, তখন ব্যাকএন্ড সার্ভার কীভাবে বুঝবে যে কোন কোর্সের ডিটেইলসটি স্ক্রিনে দেখাতে হবে? এর জন্য ব্রাউজারকে সার্ভারের কাছে একটি নির্দিষ্ট আইডেন্টিফায়ার (যেমন: ID বা Name) পাঠাতে হয়। এই ডেটা বা আর্গুমেন্ট পাঠানোর অন্যতম সহজ ও ডিফল্ট উপায় হলো Query String

Syntax & Components: ধরি একটি URL হলো: localhost:port/dashboard?id=1&name=Scott

  • URL Path: কোশ্চেন মার্ক (?)-এর বাম পাশের অংশটি (/dashboard) হলো রিকোয়েস্টের পাথ।
  • The Separator (?): কোশ্চেন মার্কটি পাথ এবং কুয়েরি স্ট্রিং-এর মধ্যে সীমানা প্রাচীর হিসেবে কাজ করে।
  • Key-Value Pair: ইকুয়াল টু (=) চিহ্নের মাধ্যমে Key এবং Value ডিফাইন করা হয় (যেমন: id=1)।
  • Multiple Parameters (&): যদি একের বেশি ডেটা পাঠাতে হয়, তবে তাদের মাঝখানে কোনো স্পেস না দিয়ে অ্যাম্পারস্যান্ড (&) চিহ্ন দিয়ে যুক্ত করতে হয় (যেমন: id=1&name=Scott)।

2. The Internal Mechanism: context.Request.Query [Priority: 10/10]

যখন Kestrel Server ব্রাউজার থেকে কোনো URL রিসিভ করে, তখন ASP.NET Core আন্ডার-দ্য-হুড পুরো URL-টি পার্স (Parse) করে। কোশ্চেন মার্কের ডানপাশের সব Key-Value পেয়ারকে সে context.Request.Query প্রোপার্টির ভেতরে একটি ডিকশনারি ফরম্যাটে জমা করে।

ইন্টারনালি এর ডেটা টাইপ হলো IQueryCollection। তাই আমরা একটি রেগুলার C# Dictionary-র মতোই এর ভেতরে থাকা যেকোনো Key-র নাম ধরে তার ভ্যালু এক্সেস করতে পারি।

3. Defensive Coding: Checking Key Existence [Priority: 9/10]

লেকচারার একটি অত্যন্ত গুরুত্বপূর্ণ পরামর্শ দিয়েছেন—“Without checking, blindly trying to read the value may be error-prone.” ইউজার যদি ভুলবশত URL-এ id না পাঠায়, আর তোমার কোড যদি সরাসরি সেই id রিড করার চেষ্টা করে, তবে অ্যাপ্লিকেশন ক্র্যাশ করতে পারে বা বাগ তৈরি হতে পারে। তাই ভ্যালু রিড করার আগে ContainsKey() দিয়ে ভেরিফাই করে নেওয়া উত্তম।

// Checking if the key "id" exists in the query collection
if (context.Request.Query.ContainsKey("id"))
{
    // Safe to read the value now
    string idValue = context.Request.Query["id"];
}
 

💻 Code Implementation

লেকচারে যেভাবে মিডলওয়্যার পাইপলাইনে context.Request.Query ব্যবহার করে GET রিকোয়েস্টের ডেটা রিড করা হয়েছে, তার সম্পূর্ণ কোড ইমপ্লিমেন্টেশন নিচে দেওয়া হলো:

// Program.cs
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
 
app.Run(async (HttpContext context) =>
{
    // 1. Setting Content-Type header before writing anything to the response body
    context.Response.Headers.ContentType = "text/html";
 
    // 2. Query String checks should ideally be done for GET requests
    if (HttpMethods.IsGet(context.Request.Method))
    {
        // Check if the 'id' parameter is present in the URL
        if (context.Request.Query.ContainsKey("id"))
        {
            // Reading the value of 'id' from the query string dictionary
            string id = context.Request.Query["id"]!;
 
            // Reading another optional parameter 'name' if exists
            string name = context.Request.Query.ContainsKey("name") 
                ? context.Request.Query["name"]! 
                : "Unknown";
 
            // 3. Writing the output to the response body
            await context.Response.WriteAsync($"""
                <h3>Query String Data Received successfully!</h3>
                <p><b>Course ID:</b> {id}</p>
                <p><b>Student Name:</b> {name}</p>
            """);
            return;
        }
    }
 
    // Default fallback response if 'id' is not supplied
    context.Response.StatusCode = StatusCodes.Status400BadRequest;
    await context.Response.WriteAsync("<p>Bad Request: Please supply an 'id' in the query string (e.g., ?id=101)</p>");
});
 
app.Run();
 

🔍 Debugging & Shortcuts in VS Code

Browser Testing Steps:

  1. অ্যাপ্লিকেশনটি রান করতে কীবোর্ড থেকে F5 চাপো (VS Code এবং Visual Studio দুটোর জন্যই এটি ডিফল্ট শর্টকাট)।
  2. ব্রাউজার ওপেন হলে URL-এর শেষে এটি লিখে এন্টার দাও: ?id=500&name=Hasib
  3. কীবোর্ড থেকে Ctrl + Shift + I চেপে Developer Tools ওপেন করো।
  4. Network ট্যাবে যাও এবং পেজটি Refresh করো। localhost রিকোয়েস্টে ক্লিক করলে তুমি General সেকশনে পুরো URL-টি দেখতে পাবে এবং স্ক্রিনে C# কোড দ্বারা এক্সট্র্যাক্ট করা ID ও Name-এর আউটপুট দেখতে পাবে।

🚀 Best Practices & .NET 10 / C# 13 Updates

Best Practices with Examples

  1. Never Trust Query String Data (Always Validate): কুয়েরি স্ট্রিং-এর ডেটা ইউজার ব্রাউজারের URL বার থেকে সরাসরি পরিবর্তন করতে পারে। তাই ডাটাবেজে পাঠানোর আগে ডেটা টাইপ এবং রেঞ্জ অবশ্যই ভ্যালিডেট করবে।
// Bad Practice: Directly passing string to DB
string idStr = context.Request.Query["id"];
 
// Good Practice: Safely parsing string to integer
if (int.TryParse(context.Request.Query["id"], out int courseId)) {
    // Use courseId safely here
}
 
  1. Do Not Pass Sensitive Data: পাসওয়ার্ড, ওটিপি (OTP) বা কোনো সেনসিটিভ ডেটা কখনোই Query String-এ পাঠাবে না। কারণ কুয়েরি স্ট্রিং-এর ডেটা ব্রাউজারের হিস্ট্রি (History) এবং সার্ভার লগে সেভ হয়ে থাকে, যা সিকিউরিটি রিস্ক তৈরি করে। এই কাজের জন্য সবসময় POST Request এবং Request Body ব্যবহার করবে।

Modern .NET 10 / C# 13 Approaches

ট্রান্সক্রিপ্টে মিডলওয়্যার লেভেলে ডিকশনারি ধরে কুয়েরি স্ট্রিং রিড করার যে ওল্ড-স্টাইল পদ্ধতি দেখানো হয়েছে, আধুনিক .NET 10-এ আমরা সেভাবে কোড করি না। আধুনিক .NET-এ আমরা Minimal APIs ব্যবহার করি।

Minimal API-তে ফ্রেমওয়ার্ক এত বেশি স্মার্ট যে, ল্যাম্বডা ফাংশনের প্যারামিটারে তুমি সাধারণ ভেরিয়েবলের নাম লিখে দিলেই সে অটোমেটিকভাবে URL-এর Query String থেকে সেই নামের ভ্যালুটি রিড এবং টাইপ-কাষ্ট (Type-cast) করে নেয়! তোমার কোনো ম্যানুয়াল কোড বা ContainsKey চেক করার দরকারই পড়ে না।

.NET 10 Modern Minimal API Code Example:

// Program.cs (.NET 10 Standard Minimal API)
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
 
// .NET 10 automatically maps '?id=10&name=Hasib' directly to the parameters!
// It even handles the parsing from string to integer automatically!
app.MapGet("/course", (int id, string? name) =>
{
    // If 'id' is missing in URL, .NET 10 automatically returns 400 Bad Request!
    string studentName = name ?? "Guest User";
    
    return Results.Content($"""
        <h3>Modern .NET 10 Query String Mapping</h3>
        <p>Course ID (Parsed automatically): {id}</p>
        <p>Name: {studentName}</p>
    """, "text/html");
});
 
app.Run();
 

Why this is a game-changer: এখানে কোড ১০ গুণ ছোট হয়ে গেছে। ইউজার যদি URL-এ id-র জায়গায় কোনো ক্যারেক্টার (যেমন ?id=abc) পাঠায়, তবে আধুনিক .NET 10 রানটাইম এক্সেপশন না খাইয়ে নিজে থেকেই ক্লায়েন্টকে একটি স্ট্যান্ডার্ড 400 Bad Request রেসপন্স রিটার্ন করে দেয়।