হাসিব, চলো তোমার কোর্সের ৯৮ নম্বর লেকচারটি নিয়ে বিস্তারিত আলোচনা করি। আউটলাইন অনুযায়ী এটি (Section 8: Views - MVC Architecture Pattern) এর অংশ, যার শিরোনাম “Strongly Typed Views - Part 2”

আগের লেকচারে আমরা দেখেছি কীভাবে একটি View-কে একটি Collection (List) এর সাথে বাইন্ড করতে হয়। এই লেকচারে ইনস্ট্রাক্টর দেখিয়েছেন কীভাবে একটি View-কে Single Object (যেমন একজন ইউজারের বিস্তারিত তথ্য) এর সাথে বাইন্ড করতে হয় এবং কীভাবে দুটি View-এর মধ্যে Hyperlink তৈরি করতে হয়।

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


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

  • Objective: একটি নতুন Details Action Method এবং View তৈরি করা, যা শুধু একজন ইউজারের (Single Object) ডেটা দেখাবে।
  • Routing: Route Parameter (/PersonDetails/{name}) ব্যবহার করে নির্দিষ্ট ইউজারের ডেটা ফিল্টার করা হয়েছে।
  • LINQ (FirstOrDefault): কালেকশন থেকে নির্দিষ্ট নাম অনুযায়ী অবজেক্ট খুঁজে বের করতে FirstOrDefault ব্যবহার করা হয়েছে।
  • Single Object Binding: Details.cshtml-এ @model Person ডিরেক্টিভ ব্যবহার করে View-টিকে একটি সিঙ্গেল অবজেক্টের সাথে বাইন্ড করা হয়েছে।
  • Navigation (Hyperlinks): Index এবং Details পেজের মধ্যে যাওয়া-আসার জন্য ট্যাগ দিয়ে ডায়নামিক হাইপারলিংক তৈরি করা হয়েছে।
  • View Method Overloads: Controller-এর View() মেথডের ৪টি ওভারলোড (Overload) নিয়ে আলোচনা করা হয়েছে।

📌 Step 1: Creating the Details Action Method [Priority: 10/10]

প্রথম কাজ হলো HomeController-এ একটি নতুন Action Method তৈরি করা, যা ইনপুট হিসেবে ইউজারের নাম (Name) নেবে এবং সেই ইউজারের ডেটা খুঁজে বের করে View-তে পাঠাবে।

// Controllers/HomeController.cs
using Microsoft.AspNetCore.Mvc;
using MyWebApp.Models;
using System.Linq;
 
public class HomeController : Controller
{
    // ... আগের Index মেথড ...
 
    // Route প্যারামিটার ডিক্লেয়ার করা হয়েছে: name
    [Route("PersonDetails/{name}")] 
    public IActionResult Details(string name)
    {
        // Null চেকিং
        if (string.IsNullOrEmpty(name))
            return Content("Person name cannot be null");
 
        // ডেমো ডেটা (আগের লেকচারের মতোই)
        List<Person> people = new List<Person>
        {
            new Person { Name = "John", Gender = "Male" },
            new Person { Name = "Hasib", Gender = "Male" }
        };
 
        // LINQ ব্যবহার করে নির্দিষ্ট ইউজারকে খুঁজে বের করা
        // FirstOrDefault: যদি নাম মিলে যায় তবে প্রথম অবজেক্টটি দিবে, না মিললে null দিবে
        Person? matchingPerson = people.FirstOrDefault(p => p.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
 
        if (matchingPerson == null)
            return Content("Person not found");
 
        // View এর নাম উল্লেখ না করলে মেথডের নাম (Details) কেই View এর নাম হিসেবে ধরে নেবে
        return View(matchingPerson); 
    }
}
 

Why this code? (কেন এই কোড?) এখানে name প্যারামিটারটি URL থেকে ডেটা রিসিভ করবে (যেমন: /PersonDetails/John)। এরপর LINQ-এর FirstOrDefault মেথড পুরো কালেকশন খুঁজে John নামের অবজেক্টটিকে বের করে আনবে এবং View(matchingPerson) এর মাধ্যমে সেই সিঙ্গেল অবজেক্টটিকে View-তে পাঠিয়ে দেবে।

(নোট: ইনস্ট্রাক্টর বলেছেন একই ডেটা দুই মেথডে লেখা ভালো প্র্যাকটিস নয়, পরে সার্ভিস লেয়ার বা ডাটাবেজ ব্যবহার করে এটি ঠিক করা হবে)।


📌 Step 2: Creating the Details View (Single Object Binding) [Priority: 10/10]

এবার Views/Home/ ফোল্ডারে Details.cshtml নামে একটি নতুন Razor View তৈরি করতে হবে।

আগের লেকচারে আমরা কালেকশন (IEnumerable) রিসিভ করেছিলাম। কিন্তু এই লেকচারে আমরা শুধু একটি সিঙ্গেল অবজেক্ট রিসিভ করবো।

<!-- Views/Home/Details.cshtml -->
 
<!-- View কে Person মডেলের সাথে বাইন্ড করা হচ্ছে (Single Object) -->
@model MyWebApp.Models.Person
 
<div class="page-content">
    <div class="box">
        <!-- @Model ব্যবহার করে সরাসরি প্রোপার্টি এক্সেস করা হচ্ছে -->
        <h3>@Model.Name Details</h3>
        
        <table class="table w-100">
            <tr>
                <td>Gender:</td>
                <td>@Model.Gender</td>
            </tr>
            <tr>
                <td>Date of Birth:</td>
                <!-- Null-conditional operator (?) ব্যবহার করা হয়েছে -->
                <td>@Model.DateOfBirth?.ToString("MMM-dd-yyyy")</td>
            </tr>
        </table>
 
        <!-- Back Button (Hyperlink) -->
        <a href="/Home">Back to Persons List</a>
    </div>
</div>
 

কীভাবে কাজ করছে?

  • এখানে @model Person লেখার ফলে View বুঝে নিয়েছে যে সে একটিমাত্র ইউজারের ডেটা পাবে।
  • তাই ডেটা দেখানোর জন্য কোনো foreach লুপ দরকার হয়নি। সরাসরি @Model.Name লিখে ডেটা প্রিন্ট করা গেছে।

এখন আমাদের Index পেজ (যেখানে সবার নাম দেখায়) থেকে Details পেজে যাওয়ার জন্য একটি ডায়নামিক লিংক বা বাটন তৈরি করতে হবে।

<!-- Views/Home/Index.cshtml এর ভেতরের লুপের অংশ -->
 
@foreach (var person in Model)
{
    <div class="box float-left w-50">
        <h3>@person.Name</h3>
        
        <!-- ডায়নামিক URL তৈরি করা হচ্ছে -->
        <!-- URL হবে: /PersonDetails/John, /PersonDetails/Hasib ইত্যাদি -->
        <a href="/PersonDetails/@person.Name">View Details</a>
    </div>
}
 

📌 Advantages of Strongly Typed Views [Priority: 8/10]

ইনস্ট্রাক্টর Strongly Typed View ব্যবহারের তিনটি প্রধান সুবিধার কথা বলেছেন:

  1. Intellisense Support: @Model. লেখার সাথে সাথে Visual Studio সব প্রোপার্টির নাম সাজেশন হিসেবে দেখায়, ফলে টাইপিং মিসটেক হওয়ার সুযোগ থাকে না।
  2. Compile-time Checking: যদি তুমি ভুল করে @Model.Genderr (ভুল বানান) লেখো, তবে কোড রান করার আগেই Visual Studio লাল দাগ দিয়ে এরর ধরিয়ে দেবে। ViewBag ব্যবহার করলে এটি রানটাইমে ক্র্যাশ করত।
  3. Clarity (সহজবোধ্যতা): View ফাইলের প্রথম লাইন (@model Person) দেখেই বোঝা যায় এই View-টি কোন ডেটার জন্য তৈরি করা হয়েছে।

📌 The 4 Overloads of the View() Method [Priority: 7/10]

Controller থেকে View-তে ডেটা পাঠানোর সময় আমরা return View(); লিখি। এই মেথডটির মূলত ৪টি ওভারলোড আছে:

  1. return View(); View এর নাম মেথডের নামের সমান হবে এবং কোনো ডেটা (Model) পাঠানো হবে না।
  2. return View(modelObject); View এর নাম মেথডের নামের সমান হবে এবং modelObject ডেটা হিসেবে পাঠানো হবে। (সবচেয়ে বেশি ব্যবহৃত)।
  3. return View(“CustomViewName”); ডেটা পাঠানো হবে না, কিন্তু মেথডের নামের বদলে “CustomViewName.cshtml” ফাইলটি রেন্ডার হবে।
  4. return View(“CustomViewName”, modelObject); আলাদা নামের একটি View রেন্ডার হবে এবং তার কাছে ডেটা পাঠানো হবে।

⭐ Best Practices (Modern .NET 10 Context)

  1. Use Tag Helpers for Links: ইনস্ট্রাক্টর href=“/PersonDetails/@person.Name” ব্যবহার করে ম্যানুয়ালি URL তৈরি করেছেন। কিন্তু আধুনিক ASP.NET Core-এ এভাবে হার্ডকোডেড URL তৈরি করা “Bad Practice”। এর বদলে Tag Helpers ব্যবহার করা উচিত (যা এই কোর্সের ১৬ নম্বর সেকশনে আছে)। Modern Approach (Tag Helper):
<a asp-controller="Home" asp-action="Details" asp-route-name="@person.Name">View Details</a>
 
 

এর সুবিধা হলো, ভবিষ্যতে যদি তুমি [Route] এর নাম পরিবর্তন করো, তবে সব View-তে গিয়ে href পরিবর্তন করতে হবে না, Tag Helper অটোমেটিকভাবে সঠিক URL জেনারেট করে নেবে।

  1. Always use Unique Identifiers (IDs): লেকচারে name দিয়ে ইউজার খোঁজা হয়েছে। রিয়েল-ওয়ার্ল্ড প্রজেক্টে কখনোই Name বা Email দিয়ে ডেটাবেজ থেকে ডেটা খোঁজা (Details page এর জন্য) উচিত নয়, কারণ দুজনের নাম এক হতে পারে। সবসময় Id (যেমন Guid বা int) ব্যবহার করতে হবে (যেমন: /PersonDetails/101)।