হ্যালো হাসিব! কোর্স আউটলাইন অনুযায়ী, আমরা এখন Section 10: Partial Views-এর দ্বিতীয় লেকচার “Partial Views with ViewData” (Lecture 115) নিয়ে আলোচনা করবো। আগের লেকচারে তুমি শিখেছিলে কীভাবে স্ট্যাটিক কন্টেন্ট দিয়ে Partial View বানাতে হয়। এই লেকচারে আমরা শিখবো কীভাবে ViewData/ViewBag ব্যবহার করে Partial View-তে ডায়নামিক ডেটা পাঠানো যায়।

চলো, পুরো বিষয়টি ধাপে ধাপে ডিকোড করে ফেলি।


সারসংক্ষেপ (Quick Revision List)

  • Dynamic Data in Partial View: Partial View-তে স্ট্যাটিক কন্টেন্টের বদলে ডায়নামিক ডেটা (যেমন: লিভার টাইটেল, লিস্ট আইটেমস) পাঠানোর জন্য ViewData বা ViewBag ব্যবহার করা হয়।
  • How it Works: Controller থেকে ডেটা Parent View-তে আসে, আর Parent View যখন Partial View কল করে, তখন সে তার ViewData-এর একটি Copy (কপি) Partial View-কে পাঠিয়ে দেয়।
  • Crucial Rule: যেহেতু Partial View অরিজিনাল ViewData-এর একটি কপি পায়, তাই Partial View-এর ভেতরে ViewData আপডেট করলে Parent View-এর ডাটা চেঞ্জ বা ওভাররাইট হয় না।
  • Explicit ViewData Passing: Parent View চাইলে তার পুরো ViewData না পাঠিয়ে, নতুন একটি ViewDataDictionary তৈরি করে শুধুমাত্র নির্দিষ্ট ডেটা Partial View-তে পাঠাতে পারে (view-data অ্যাট্রিবিউট ব্যবহার করে)।

Comprehensive Breakdown

১. Partial View-তে ডায়নামিক ডেটা পাঠানো (The Concept) [Priority: 10/10]

আগের লেকচারে আমাদের লিস্টটি ছিল স্ট্যাটিক (<li>New York</li> ইত্যাদি)। কিন্তু বাস্তবে আমরা চাইবো ডাটাবেস থেকে পাওয়া লিস্ট (যেমন: কোনো পেজে Cities, অন্য পেজে Countries) Partial View দিয়ে রেন্ডার করতে।

Step A: Controller থেকে Data পাঠানো প্রথমে HomeController-এর Index অ্যাকশন মেথডে ViewData ব্যবহার করে ডেটা সেট করতে হবে।

// Controllers/HomeController.cs
public IActionResult Index()
{
    // Partial View-এর Title-এর জন্য
    ViewData["ListTitle"] = "Cities"; 
    
    // Partial View-এর List Items-এর জন্য
    ViewData["ListItems"] = new List<string>() { "New York", "London", "Dhaka", "Tokyo" };
 
    return View();
}
 

Step B: Partial View-তে Data রিসিভ করা ও প্রিন্ট করা যেহেতু Parent View-এর সব ViewData বাই ডিফল্ট Partial View-তে চলে যায়, তাই আমরা সরাসরি _ListPartialView.cshtml ফাইলে সেই ডেটা অ্যাক্সেস করতে পারবো। (ViewData এবং ViewBag মূলত একই ডেটা ডিকশনারি, শুধু অ্যাক্সেস করার সিনট্যাক্স ভিন্ন। লুপ চালানোর জন্য ViewBag ব্যবহার করা সুবিধাজনক)।

<!-- Views/Shared/_ListPartialView.cshtml -->
<div class="list-container">
    <!-- ViewData থেকে টাইটেল প্রিন্ট করা হচ্ছে -->
    <h2>@ViewBag.ListTitle</h2> 
    
    <ul class="list">
        <!-- ViewBag থেকে আইটেমগুলো লুপ করে প্রিন্ট করা হচ্ছে -->
        @foreach (var item in ViewBag.ListItems)
        {
            <li>@item</li>
        }
    </ul>
</div>
 

২. একই পেজে ভিন্ন ভিন্ন ডেটা পাঠানো [Priority: 9/10]

ধরো, তুমি Index.cshtml-এ দু’বার Partial View-টি কল করবে। প্রথমবার “Cities” দেখাবে, দ্বিতীয়বার “Countries” দেখাবে।

<!-- Views/Home/Index.cshtml -->
 
<!-- প্রথম কল: Controller থেকে আসা ডিফল্ট "Cities" রেন্ডার হবে -->
<partial name="_ListPartialView" />
 
<!-- ViewData আপডেট করে দ্বিতীয় কলের জন্য প্রস্তুত করা হচ্ছে -->
@{
    ViewData["ListTitle"] = "Countries";
    ViewData["ListItems"] = new List<string>() { "Bangladesh", "USA", "UK", "Japan" };
}
 
<!-- দ্বিতীয় কল: এখন "Countries" রেন্ডার হবে -->
<partial name="_ListPartialView" />
 

৩. Important Interview Concept: ViewData Isolation (Copy vs Reference) [Priority: 10/10]

লেকচারার এখানে একটি খুবই গুরুত্বপূর্ণ পয়েন্ট প্রমাণ করেছেন। যখন একটি Partial View কল হয়, ASP.NET Core অরিজিনাল ViewData অবজেক্টটি পাঠায় না, বরং সেটার একটি Copy (ক্লোন) পাঠায়।

প্রমাণ: যদি তুমি Partial View-এর ভেতরে গিয়ে ViewData পরিবর্তন করো:

<!-- Inside _ListPartialView.cshtml -->
@{
    ViewBag.ListTitle = "Updated Title from Partial View";
}
<h2>@ViewBag.ListTitle</h2>
 

এটি শুধু Partial View-এর ভেতরেই কাজ করবে। কিন্তু এরপর যদি Parent View-তে এসে ViewData["ListTitle"] প্রিন্ট করো, দেখবে অরিজিনাল ডাটা (যেমন: Cities বা Countries) অক্ষত আছে। Why? কারণ Partial View অরিজিনাল মেমোরি রেফারেন্সে কাজ করে না, কপির উপর কাজ করে। এতে করে Child কম্পোনেন্ট ভুল করে Parent-এর ডাটা নষ্ট করতে পারে না।

৪. নির্দিষ্ট বা কাস্টম ViewData পাঠানো (Explicit view-data parameter) [Priority: 7/10]

মাঝে মাঝে সিকিউরিটি বা পারফরম্যান্সের কারণে তুমি চাইতে পারো Parent View-এর পুরো ViewData Partial View-তে না পাঠিয়ে, শুধু নির্দিষ্ট ডাটা পাঠাতে। তখন আমরা নতুন একটি ViewDataDictionary তৈরি করে Tag Helper-এর view-data অ্যাট্রিবিউট ব্যবহার করি।

<!-- Views/Home/Index.cshtml -->
@{
    // নতুন একটি ViewDataDictionary তৈরি
    var myCustomData = new ViewDataDictionary(ViewData)
    {
        { "ListTitle", "Exclusive Items" },
        { "ListItems", new List<string>() { "Item 1", "Item 2" } }
    };
}
 
<!-- শুধুমাত্র ঐ নির্দিষ্ট ViewData পাঠানো হচ্ছে -->
<partial name="_ListPartialView" view-data="myCustomData" />
 

Best Practices & .NET 10 Context

Best Practices for Passing Data to Partial Views:

  1. Avoid ViewData/ViewBag for Complex Models: যদিও এই লেকচারে ViewData দেখানো হয়েছে, প্রফেশনাল প্রজেক্টে ViewData/ViewBag-এর উপর অতিরিক্ত নির্ভর করা একটি Bad Practice, কারণ এটি Weakly Typed (রানটাইমে এরর দিতে পারে এবং ইন্টেলিসেন্স কাজ করে না)।
  2. Use Strongly Typed Partial Views: ডায়নামিক ডেটা পাঠানোর সবচেয়ে রিলায়েবল ও স্ট্যান্ডার্ড উপায় হলো Strongly Typed Models ব্যবহার করা (যা তুমি পরবর্তী লেকচারেই শিখতে যাবে)।

.NET 10 Context: ASP.NET Core 10-এ ViewData/ViewBag দিয়ে Partial View-তে ডেটা পাস করার মেকানিজম .NET 6-এর মতোই রয়ে গেছে।

তবে মডার্ন প্র্যাকটিসে (খুব সাধারণ স্ট্রিং বা ছোট ডেটা ছাড়া) সবসময় মডেল পাস করা হয়, যেমন:

<!-- Modern Standard: Strongly Typed Data Passing -->
<partial name="_ListPartialView" model="myListObject" />
 

হাসিব, Partial View-তে ViewData পাঠানোর এই কনসেপ্ট এবং এর Copy vs Reference ইস্যুটি কি তোমার কাছে ক্লিয়ার? রেডি হলে আমরা পরের লেকচার “Strongly Typed Partial Views”-এ মুভ করতে পারি!