হাসিব, চলো তোমার কোর্সের ৯৪ নম্বর লেকচারটি নিয়ে বিস্তারিত আলোচনা করি। আউটলাইন অনুযায়ী এটি (Section 8: Views - MVC Architecture Pattern) এর অংশ, যার শিরোনাম “ViewData - Part 1”। আগের লেকচারে আমরা Html.Raw দেখেছি, আর এর পরের টপিক হলো ViewData-র Part 2। এই লেকচারে মূলত Controller থেকে View-তে ডেটা পাঠানোর সবচেয়ে প্রাথমিক পদ্ধতি বা মাধ্যম নিয়ে আলোচনা করা হয়েছে।
নিচে পুরো লেকচারটির বিস্তারিত ব্রেকডাউন দেওয়া হলো:
📝 Summary (সারসংক্ষেপ)
- The Core Concept: MVC প্যাটার্নের নিয়ম অনুযায়ী View-এর ভেতরে কখনো ডেটা তৈরি বা ইনিশিয়ালাইজ করতে হয় না। Controller ডেটা সাপ্লাই দেবে, আর View তা রিসিভ করে শুধু দেখাবে।
- What is ViewData? Controller থেকে View-তে ডেটা ট্রান্সফার করার একটি বিল্ট-ইন মেকানিজম বা ডিকশনারি অবজেক্ট হলো ViewData।
- How it works: এটি C#-এর Dictionary-এর মতো কাজ করে। এটি Key-Value pair আকারে ডেটা স্টোর করে (যেখানে Key হলো string এবং Value হলো object)।
- Casting Requirement: যেহেতু ViewData সব ডেটাকে object টাইপ হিসেবে সেভ করে, তাই View-তে সেই ডেটা (বিশেষ করে Collection বা Complex object) রিড করার সময় ম্যানুয়ালি Typecast করতে হয়।
📌 MVC Golden Rule: Controller Supplies, View Uses [Priority: 10/10]
লেকচারের শুরুতেই ইনস্ট্রাক্টর একটি অত্যন্ত গুরুত্বপূর্ণ প্রশ্ন করেছেন: View (.cshtml) এর ভেতরে ভ্যারিয়েবল বা কালেকশন ইনিশিয়ালাইজ করা কি ঠিক? উত্তর: না, একদমই না।
Why? (কেন?) MVC (Model-View-Controller) আর্কিটেকচারের মূল ভিত্তি হলো Separation of Concerns।
- Controller: লজিক প্রসেস করবে, ডাটাবেজ থেকে ডেটা আনবে এবং সব রেডি করে View-কে পাঠাবে।
- View: শুধু এবং শুধুমাত্র ডেটা রেন্ডার (প্রদর্শন) করবে।
কিন্তু Controller কীভাবে View-কে ডেটা পাঠাবে? এটার জন্য ASP.NET Core-এ কয়েকটি মেকানিজম আছে। তার মধ্যে সবচেয়ে বেসিক হলো ViewData।
📌 What is ViewData? [Priority: 10/10]
ViewData হলো ControllerBase ক্লাসের একটি বিল্ট-ইন প্রোপার্টি। এর ডেটা টাইপ হলো ViewDataDictionary।
- এটি মূলত একটি Dictionary of Key-Value pairs।
- এর Key সব সময় string টাইপের হয়।
- এর Value সব সময় object টাইপের হয় (যার মানে তুমি এখানে string, int, List, Object যেকোনো কিছু রাখতে পারবে)।
- Controller-এ তুমি ViewData-তে যা কিছু অ্যাড করবে, View-তে হুবহু সেই একই ViewData অবজেক্ট অ্যাক্সেস করতে পারবে।
📌 Step 1: Sending Data from Controller [Priority: 9/10]
ইনস্ট্রাক্টর আগের লেকচারের View-তে থাকা সব ডেটা কাট করে Controller-এ নিয়ে এসেছেন। চলো দেখি Controller-এর কোড কেমন হবে:
// Controllers/HomeController.cs
using Microsoft.AspNetCore.Mvc;
using MyWebApp.Models; // Person মডেল ইমপোর্ট করা হলো
public class HomeController : Controller
{
public IActionResult Index()
{
// ১. সাধারণ String ডেটা
ViewData["AppTitle"] = "My ASP.NET Core Application";
// ২. Complex Data / Collection
List<Person> people = new List<Person>
{
new Person { Name = "Hasib", Gender = "Male" },
new Person { Name = "John", Gender = "Male" }
};
// Collection-টিকে ViewData-তে স্টোর করা হচ্ছে
ViewData["People"] = people;
return View();
}
}
কিভাবে কাজ করছে?
- ViewData[“AppTitle”] এ আমরা একটি সাধারণ string রাখলাম। এখানে “AppTitle” হলো Key।
- ViewData[“People”] এ আমরা পুরো List কালেকশনটি রেখে দিলাম।
📌 Step 2: Reading Data in View [Priority: 10/10]
Controller থেকে পাঠানো ডেটা এখন View-তে রিড করতে হবে।
1. Reading Simple Types (String/Int)
সাধারণ String বা Int রিড করা খুবই সহজ। সরাসরি Key ধরে কল করলেই ব্রাউজারে ভ্যালু প্রিন্ট হয়ে যায়।
<!-- Views/Home/Index.cshtml -->
<!-- AppTitle রিড করে প্রিন্ট করা হচ্ছে -->
<h1>@ViewData["AppTitle"]</h1>
2. Reading Complex Types & Typecasting (The Catch!)
সমস্যা শুরু হয় যখন আমরা Collection বা অবজেক্ট রিড করতে যাই। যেহেতু ViewData বাই-ডিফল্ট সব ভ্যালুকে object হিসেবে ট্রিট করে, তাই View জানে না যে ViewData[“People”] এর ভেতরে আসলে একটি List আছে।
তাই লুপ চালানোর আগে আমাদের Typecasting (টাইপ কাস্টিং) করে নিতে হবে।
@{
// ViewData থেকে ডেটা রিড করে List<Person>-এ কাস্ট করা হচ্ছে।
// ? (Question mark) দেওয়া হয়েছে Nullable Warning দূর করার জন্য।
List<Person>? people = (List<Person>?)ViewData["People"];
}
<!-- লুপ চালানোর আগে Null Check করে নেওয়া ভালো প্র্যাকটিস -->
@if (people != null)
{
@foreach (var person in people)
{
<div>
<span>@person.Name</span> - <span>@person.Gender</span>
</div>
}
}
Typecasting কেন দরকার? তুমি যদি সরাসরি @foreach(var p in ViewData[“People”]) লিখতে যাও, তাহলে C# এরর দিবে, কারণ একটি সাধারণ object-এর ওপর foreach লুপ চালানো যায় না। তাকে অবশ্যই IEnumerable বা List এ কাস্ট করে নিতে হয়।
⭐ Best Practices & Modern .NET 10 Context
ViewData জানাটা বেসিক ক্লিয়ার করার জন্য খুব জরুরি, কিন্তু রিয়েল-ওয়ার্ল্ড প্রজেক্টে বা আধুনিক MVC অ্যাপ্লিকেশনে এর ব্যবহার বেশ সীমিত।
Why avoid ViewData for Complex Objects? (কেন এড়িয়ে চলবো?)
- Magic Strings: ViewData[“People”] এ “People” একটি হার্ডকোডেড স্ট্রিং। যদি Controller-এ তুমি বানান ভুল করে “Peoples” লেখো এবং View-তে “People” খোঁজো, তাহলে কম্পাইল-টাইমে কোনো এরর আসবে না। অ্যাপ্লিকেশন রান করার পর পেজ ক্র্যাশ করবে বা ডেটা আসবে না। একে Magic String এর সমস্যা বলে।
- Typecasting Overhead: বারবার View-তে (List) কাস্ট করাটা বিরক্তিকর এবং View-এর কোডকে নোংরা করে ফেলে।
The Better Approach (Strongly Typed Views): ভিডিওর আউটলাইনে দেখো, এরপরই (লেকচার ৯৭ থেকে) “Strongly Typed Views” নামে একটি টপিক আছে। আধুনিক .NET 10 MVC প্রজেক্টে ViewData-এর বদলে সবসময় Strongly Typed Models ব্যবহার করা হয়।
Modern Approach Example:
// Controller
return View(people); // ViewData-তে না রেখে সরাসরি Model হিসেবে পাঠানো
<!-- View -->
@model IEnumerable<Person>
<!-- কাস্টিংয়ের দরকার নেই, সরাসরি Model এর ওপর লুপ চলবে -->
@foreach (var person in Model) { ... }
Where to actually use ViewData? (কোথায় ব্যবহার করবো?) ViewData পুরোপুরি বাতিল নয়। খুব ছোটখাটো ডেটা (যেমন- Page Title, Meta Description, Notification message) যা মূল Model-এর অংশ নয়, সেগুলো পাঠানোর জন্য ViewData এখনও ব্যাপকভাবে ব্যবহৃত হয়। যেমন: ViewData[“Title”] = “Home Page”;