হাসিব, চলো আজকের টপিকটা নিয়ে আলোচনা করি। আউটলাইন অনুযায়ী এটি তোমার কোর্সের ৮৯ নম্বর লেকচার (Section 8: Views - MVC Architecture Pattern)। এই লেকচারে Razor View-তে foreach লুপ কীভাবে কাজ করে এবং কীভাবে Collection বা Array থেকে ডেটা নিয়ে HTML রেন্ডার করতে হয়, তা নিয়ে বিস্তারিত আলোচনা করা হয়েছে।

নিচে পুরো লেকচারটির বিস্তারিত ব্রেকডাউন দেওয়া হলো:

📝 Summary (সারসংক্ষেপ)

  • Topic: Razor Views-এ foreach লুপের ব্যবহার।
  • Purpose: একটি Array বা Collection-এর ডেটা রিড করে একই HTML tag বারবার জেনারেট করা।
  • Common Use Cases: HTML Unordered/Ordered List (, ), Table Rows (), অথবা Link () এর লিস্ট তৈরি করা।
  • Execution Process: C# কোডটি Server-এ এক্সিকিউট হয় এবং ব্রাউজারে (Client) শুধুমাত্র প্লেন HTML Response হিসেবে পাঠানো হয়।
  • Combination: foreach লুপের ভেতরে প্রয়োজন অনুযায়ী Razor @if কন্ডিশন ব্যবহার করা যায়।

📌 Introduction to @foreach in Razor Views [Priority: 10/10]

C# এ আমরা যেভাবে foreach লুপ ব্যবহার করি, Razor View-তেও কনসেপ্ট সম্পূর্ণ এক। শুধু পার্থক্য হলো, Razor ফাইলে এটি ব্যবহার করার আগে একটি @ (At symbol) বসাতে হয়।

কেন ব্যবহার করবো (Why)? ধরে নাও, তোমার কাছে ১০ জন ইউজারের ডেটা আছে। এখন তুমি যদি ১০ জনের জন্য ১০ বার আলাদা বা লেখো, সেটা মোটেও ডায়নামিক হলো না। foreach লুপ ব্যবহার করলে তুমি শুধু একবার একটি HTML টেমপ্লেট লিখবে, আর লুপটি কালেকশনের প্রতিটি আইটেমের জন্য সেই টেমপ্লেটটিকে অটোমেটিকভাবে রিপিট করবে।


📌 Step 1: Setting up the Data Collection [Priority: 7/10]

লেকচারের শুরুতে পূর্ববর্তী কোডগুলো ক্লিন করে একটি নতুন Person অবজেক্টের Collection তৈরি করা হয়েছে।

@{
    // একটি List<Person> ডিক্লেয়ার এবং ইনিশিয়ালাইজ করা হচ্ছে
    List<Person> people = new List<Person>
    {
        new Person { Name = "John", Gender = "Male", DateOfBirth = new DateTime(1990, 5, 20) },
        new Person { Name = "Mary", Gender = "Female", DateOfBirth = null },
        new Person { Name = "David", Gender = "Male", DateOfBirth = new DateTime(1985, 8, 15) }
    };
}
 

এখানে লেকচারের সুবিধার্থে View-এর ভেতরেই ডেটা তৈরি করা হয়েছে। তবে রিয়েল-ওয়ার্ল্ড প্রজেক্টে এই ডেটা Controller থেকে Model হিসেবে আসে।


📌 Step 2: Implementing the @foreach Loop [Priority: 10/10]

এবার আমরা উপরের people কালেকশনটি লুপের মাধ্যমে রিড করবো এবং ডেটাগুলো HTML এ প্রিন্ট করবো।

<!-- Body ট্যাগের ভেতরে লুপ চালানো হচ্ছে -->
@foreach (var person in people)
{
    <div>
        <span>@person.Name</span>, 
        <span>@person.Gender</span>
 
        <!-- কন্ডিশনাল রেন্ডারিং -->
        @if (person.DateOfBirth != null)
        {
            <span> - @person.DateOfBirth.Value.ToString("yyyy-MM-dd")</span>
        }
    </div>
}
 

কোড ব্রেকডাউন (কিভাবে কাজ করছে?):

  1. var person in people: people কালেকশন থেকে লুপটি একে একে একেকটি অবজেক্ট বের করে আনবে এবং person নামক Temporary variable-এ স্টোর করবে। তুমি চাইলে var-এর জায়গায় স্পেসিফিক টাইপ Person person ও লিখতে পারো।
  2. Repeating HTML: লুপের ভেতরের ট্যাগটি কালেকশনের আইটেম সংখ্যার সমান (আমাদের ক্ষেত্রে ৩ বার) রিপিট হবে।
  3. Accessing Properties: @person.Name এবং @person.Gender দিয়ে ইউজারের ডেটা ডায়নামিকালি প্রিন্ট করা হচ্ছে।
  4. HTML Tag: ইনস্ট্রাক্টর ডেটাগুলোকে ট্যাগের ভেতরে রেখেছেন। হলো একটি ইনলাইন ট্যাগ, যা মূলত ছোট টেক্সট ব্লক তৈরি করতে এবং পরবর্তীতে CSS (যেমন- color, bold) অ্যাপ্লাই করতে ব্যবহৃত হয়।
  5. Inner Condition (@if): লুপের ভেতরে একটি if কন্ডিশন ব্যবহার করা হয়েছে। যদি ইউজারের DateOfBirth নাল (Null) না হয়, শুধুমাত্র তখনই জন্মতারিখের ট্যাগটি প্রিন্ট হবে।

📌 Behind the Scenes: Server vs Client Execution [Priority: 8/10]

এটি ইন্টারভিউয়ের জন্য খুবই গুরুত্বপূর্ণ একটি কনসেপ্ট। যখন তুমি এই কোডটি রান করবে এবং ব্রাউজারের Network Tab বা Inspect Element চেক করবে, তুমি সেখানে কোনো C# কোড (@foreach, @if) দেখতে পাবে না। তুমি শুধু দেখবে ৩টি সাধারণ ট্যাগ।

কেন এমন হয়? কারণ, Browser শুধুমাত্র HTML, CSS এবং JavaScript বুঝতে পারে। ব্রাউজার C# কোড রান করতে পারে না। তাই ক্লায়েন্ট (Browser) যখন রিকোয়েস্ট পাঠায়, তখন সার্ভারে থাকা Razor Engine প্রথমে C# এর লুপটি রান করে, ডেটা দিয়ে HTML জেনারেট করে, এবং শুধুমাত্র সেই জেনারেটেড HTML রেজাল্ট ব্রাউজারে পাঠায়।


⭐ Best Practices & .NET 10 Context

এই লেকচারে লুপ বোঝানোর জন্য ভিউয়ের ভেতরে ডেটা জেনারেট করা হয়েছে, কিন্তু প্রোডাকশন লেভেলে কিছু Best Practice ফলো করতে হয়:

1. Thin View, Fat Controller (View-তে ডেটা তৈরি না করা): কখনোই View (.cshtml) এর ভেতরে new List() দিয়ে ডেটা তৈরি করা উচিত নয়। View এর কাজ শুধু ডেটা দেখানো, ডেটা প্রসেস করা নয়। ডেটা সবসময় Controller থেকে পাঠাতে হয়।

2. Null Check Before Looping: লুপ চালানোর আগে সবসময় কালেকশনটি Null কিনা তা চেক করে নেওয়া উচিত। না হলে NullReferenceException খেতে পারো।

3. Modern C# (.NET 10) Example: .NET 10 এবং আধুনিক C# (C# 12/13) ব্যবহার করলে তুমি Controller থেকে আধুনিক Collection Expression ব্যবহার করে ডেটা পাঠাতে পারো এবং View-তে Null চেকিংটা আরও ক্লিন ভাবে করতে পারো।

Controller.cs:

public IActionResult Index()
{
    // C# 12/13 Collection Expression ব্যবহার করে ডেটা তৈরি
    List<Person> people = [
        new() { Name = "John", Gender = "Male" },
        new() { Name = "Mary", Gender = "Female" }
    ];
 
    return View(people);
}
 

Index.cshtml (Modern Approach):

@model IEnumerable<Person>
 
@* Null ચેક এবং Pattern Matching এর স্মার্ট ব্যবহার *@
@if (Model is not null && Model.Any())
{
    foreach (var person in Model)
    {
        <div class="user-card">
            <span>@person.Name</span>
            <span>@person.Gender</span>
        </div>
    }
}
else
{
    <div class="alert alert-warning">No people found in the collection.</div>
}
 

এখানে আমরা Controller থেকে Model রিসিভ করেছি এবং লুপ চালানোর আগে Model is not null && Model.Any() দিয়ে নিশ্চিত হয়েছি যে কালেকশনটি ফাঁকা নয়। এটি অনেক বেশি সেফ এবং স্ট্যান্ডার্ড প্র্যাকটিস।