হাসিব, চলো তোমার কোর্সের ৯৬ নম্বর লেকচারটি নিয়ে বিস্তারিত আলোচনা করি। আউটলাইন অনুযায়ী এটি (Section 8: Views - MVC Architecture Pattern) এর অংশ, যার শিরোনাম “ViewBag”।
আগের দুটি লেকচারে আমরা ViewData নিয়ে আলোচনা করেছি, যেখানে ডেটা টাইপকাস্টিং একটি বড় ইস্যু ছিল। এই লেকচারে মূলত ViewBag ব্যবহার করে সেই টাইপকাস্টিংয়ের ঝামেলা কীভাবে এড়ানো যায় এবং ViewData ও ViewBag-এর মধ্যকার ইন্টারনাল সম্পর্ক কী, তা নিয়ে বিস্তারিত আলোচনা করা হয়েছে।
নিচে পুরো লেকচারটির বিস্তারিত ব্রেকডাউন দেওয়া হলো:
📝 Summary (সারসংক্ষেপ)
- The Problem with ViewData: ViewData সব ডেটাকে object টাইপ হিসেবে রিটার্ন করে, তাই View-তে Complex Object বা Collection রিড করার সময় ম্যানুয়ালি Typecast করতে হয়।
- What is ViewBag? ViewBag হলো dynamic টাইপের একটি প্রোপার্টি, যা টাইপকাস্টিংয়ের প্রয়োজন দূর করে।
- How it works: ViewBag ইন্টারনালি ViewData-কেই ব্যবহার করে। এটি শুধু ViewData থেকে ডেটা রিড করার একটি “Syntactical Sugar” বা সহজ উপায়।
- Key Benefit: ViewBag-এ [“Key”] এর বদলে সরাসরি .Property ব্যবহার করা যায়, যা দেখতে অনেক ক্লিন।
- Null Conditioning: Null Reference Exception এড়াতে ? (Null-conditional operator) এর ব্যবহার দেখানো হয়েছে।
📌 The Problem with ViewData [Priority: 8/10]
আগের লেকচারে আমরা দেখেছি, যখন আমরা Controller থেকে একটি List ViewData-এর মাধ্যমে পাঠাই, তখন View-তে সেটি রিসিভ করার সময় এভাবে লিখতে হয়:
// ViewData-এর সমস্যা: ম্যানুয়াল টাইপকাস্টিং
List<Person>? people = (List<Person>?)ViewData["People"];
এই টাইপকাস্টিং কোডটিকে লেংথি (Lengthy) এবং কিছুটা জটিল করে তোলে। এই সমস্যা সমাধানের জন্যই ASP.NET Core-এ ViewBag নিয়ে আসা হয়েছে।
📌 Introduction to ViewBag [Priority: 10/10]
ViewBag হলো ControllerBase এবং RazorPage ক্লাসের একটি dynamic টাইপের প্রোপার্টি।
Dynamic Keyword কী? C#-এ dynamic টাইপের ভ্যারিয়েবল কম্পাইল-টাইমে কোনো টাইপ চেকিং করে না। এর ডেটা টাইপ রানটাইমে (যখন অ্যাপ্লিকেশন চলে) CLR (Common Language Runtime) দ্বারা নির্ধারিত হয়। এর ফলেই ViewBag ব্যবহার করলে আমাদের ম্যানুয়াল টাইপকাস্টিং করতে হয় না।
🛠️ Code Implementation: Using ViewBag
চলো দেখি Controller এবং View-তে ViewBag কীভাবে কাজ করে:
Controller (ডেটা পাঠানো): তুমি চাইলে Controller-এ ডেটা অ্যাড করার সময়ও ViewBag ব্যবহার করতে পারো।
// Controllers/HomeController.cs
public IActionResult Index()
{
// ViewData এর বদলে ViewBag ব্যবহার করে ডেটা অ্যাসাইন করা
ViewBag.AppTitle = "My Application Title";
List<Person> people = new List<Person>
{
new Person { Name = "Hasib", Gender = "Male" }
};
// Array বা List পাঠানো
ViewBag.People = people;
return View();
}
View (ডেটা রিড করা): View-তে রিসিভ করার সময় কোনো কাস্টিং লাগবে না।
<!-- Views/Home/Index.cshtml -->
<!-- সরাসরি প্রোপার্টির মতো অ্যাক্সেস করা যায় -->
<h1>@ViewBag.AppTitle</h1>
<!-- কোনো Typecast ছাড়াই সরাসরি লুপ চালানো যায় -->
@foreach (Person person in ViewBag.People)
{
<div>@person.Name</div>
}
ViewData বনাম ViewBag এর সিনট্যাক্স পার্থক্য:
- ViewData: ViewData[“AppTitle”] (Square bracket এবং string key)
- ViewBag: ViewBag.AppTitle (Dot notation)
📌 Behind the Scenes: The Relationship [Priority: 10/10]
এটি ইন্টারভিউয়ের জন্য খুবই গুরুত্বপূর্ণ একটি টপিক। “ViewBag internally depends on ViewData.”
আসলে ViewBag সম্পূর্ণ নতুন কোনো ডেটা স্টোরেজ নয়। এটি মূলত ViewData-এর ওপরে একটি মোড়ক (Wrapper) বা “Syntactical Sugar”। তুমি যখন ViewBag.People = people; লেখো, ব্যাকগ্রাউন্ডে ASP.NET Core সেটিকে ViewData[“People”] = people; হিসেবেই স্টোর করে।
যেহেতু সোর্স একই, তাই তুমি চাইলে:
- Controller-এ ViewData দিয়ে সেট করে View-তে ViewBag দিয়ে রিড করতে পারো।
- Controller-এ ViewBag দিয়ে সেট করে View-তে ViewData দিয়ে রিড করতে পারো।
- দুটিই সম্পূর্ণ মিক্সেবল (Mixable)।
📌 The Loophole: Intellisense Issue [Priority: 9/10]
ViewBag ব্যবহার করার একটি বড় সমস্যা হলো Intellisense (Auto-completion) না পাওয়া।
যখন তুমি foreach (var person in ViewBag.People) লেখো, তখন ViewBag.People যেহেতু dynamic টাইপের, তাই var কি-ওয়ার্ড সেটিকে System.Object হিসেবে ধরে নেয়। এর ফলে লুপের ভেতরে যখন তুমি @person. লিখবে, তখন Visual Studio তোমাকে Name, Gender ইত্যাদি প্রোপার্টির কোনো সাজেশন (Intellisense) দেবে না।
How to fix this: এই সমস্যা সমাধানের জন্য লুপের ভেতরে var এর বদলে সরাসরি আসল ক্লাসের নাম (যেমন- Person) ব্যবহার করতে হয়।
<!-- ❌ Bad: var ব্যবহার করলে ইন্টেলিসেন্স পাওয়া যাবে না -->
@foreach (var p in ViewBag.People)
<!-- ✅ Good: Person ব্যবহার করলে @person. লেখার সাথে সাথে সাজেশন আসবে -->
@foreach (Person person in ViewBag.People)
{
<span>@person.Name</span>
}
📌 Handling Null Reference Exceptions [Priority: 10/10]
লেকচারের শেষের দিকে ইনস্ট্রাক্টর একটি খুব সুন্দর C# ট্রিক দেখিয়েছেন।
ধরে নাও, কোনো ইউজারের DateOfBirth ডাটাবেজ থেকে Null এসেছে। তুমি যদি ভিউতে @person.DateOfBirth.Value.ToString() লিখতে যাও, তাহলে অ্যাপ্লিকেশন Null Reference Exception থ্রো করে ক্র্যাশ করবে।
The Fix (Null-conditional Operator ?.): C#-এ ডট (.) এর আগে একটি প্রশ্নবোধক চিহ্ন (?) বসিয়ে দিলে, অবজেক্টটি যদি Null হয় তবে সে আর সামনের মেথড (যেমন- ToString()) কল করবে না, সরাসরি Null রিটার্ন করবে।
<!-- ❌ এরর খাবে যদি DateOfBirth null হয় -->
<td>@person.DateOfBirth.Value.ToString("MMM-dd-yyyy")</td>
<!-- ✅ নিরাপদ কোড: DateOfBirth null হলে কোনো এরর হবে না -->
<td>@person.DateOfBirth?.ToString("MMM-dd-yyyy")</td>
⭐ Best Practices (Modern .NET 10 Context)
- Avoid ViewBag/ViewData for Model Data: যদিও ViewBag টাইপকাস্টিংয়ের ঝামেলা কমায়, তবুও এটি Magic Strings / Dynamic Properties এর ওপর নির্ভরশীল। তুমি যদি ViewBag.Peoples (ভুল বানান) লেখো, কম্পাইলার কোনো এরর ধরবে না, কিন্তু রানটাইমে পেজ ক্র্যাশ করবে। আধুনিক .NET 10 প্রজেক্টে ডেটা (বিশেষ করে Model/Collection) পাঠানোর জন্য সবসময় Strongly Typed Views (@model) ব্যবহার করা হয় (যা ঠিক এর পরের লেকচারেই তুমি শিখবে)।
- When to actually use ViewBag: রিয়েল-ওয়ার্ল্ড প্রজেক্টে ViewBag শুধুমাত্র পেজের মেটা-ডেটা (যেমন- Page Title, Active Sidebar Menu Name) সেট করার জন্য ব্যবহার করা হয়।
// Controller
ViewBag.Title = "Dashboard";
return View(userData); // Model ডাটা সরাসরি View তে পাঠানো