হ্যালো হাসিব! আজকের লেকচারটি হলো “Dynamic Layout Views” নিয়ে। আগের লেকচারগুলোতে আমরা দেখেছি কীভাবে _ViewStart.cshtml ব্যবহার করে সব View-এর জন্য একটি কমন Layout সেট করতে হয়। কিন্তু বাস্তব দুনিয়ার প্রোজেক্টে অনেক সময় আমাদের শর্ত বা কন্ডিশনের ওপর ভিত্তি করে Layout পরিবর্তন করতে হয়। আজকের টপিকটি ঠিক সেই বিষয়েই।
চলো প্রথমে একটি কুইক সামারি দেখে নিই।
📝 শর্ট সামারি (Quick Revision)
- Dynamic Layout: C# কন্ডিশন (যেমন
if-else) ব্যবহার করে রানটাইমে পেজেরLayoutপ্রপার্টি পরিবর্তন করা। - Use Case: ইউজারের ইনপুট, Route Parameter, বা ডাটাবেসের তথ্যের ওপর ভিত্তি করে ভিন্ন ভিন্ন Layout (যেমন Admin Layout বা User Layout) দেখানো।
- Controller Setup: Action Method-এ অপশনাল Route Parameter (যেমন
{productId?}) রিসিভ করে সেটিViewBag-এ স্টোর করা। - View Logic: View ফাইলে Razor Code Block (
@{ ... })-এর ভেতরেViewBagচেক করে কন্ডিশনালিLayoutভ্যালু অ্যাসাইন করা। - Execution Flow:
_ViewStart.cshtmlপ্রথমে ডিফল্ট Layout সেট করে, কিন্তু View-এর ভেতরের কন্ডিশনাল কোড সেই ডিফল্ট সেটিংকে Override করে দেয়।
🚀 বিস্তারিত আলোচনা (Comprehensive Breakdown)
১. Dynamic Layout View কী এবং কেন প্রয়োজন? (Priority: 10/10)
কী (What): যখন আমরা কোনো Hardcoded Layout পাথ ব্যবহার না করে, C# লজিকের মাধ্যমে সিদ্ধান্ত নিই যে একটি নির্দিষ্ট View কোন Layout-টি ব্যবহার করবে, তখন তাকে Dynamic Layout View বলে।
কেন (Why): ধরো, তোমার একটি ই-কমার্স অ্যাপ্লিকেশন আছে। যখন ইউজার সাধারণ প্রোডাক্ট পেজ দেখবে, তখন তুমি Navigation Bar সহ _Layout.cshtml দেখাতে চাও। কিন্তু ইউজার যখন কোনো নির্দিষ্ট প্রোডাক্টের ডিটেইলস (যেমন productId = 10) দেখবে, তখন তুমি Navigation Bar ছাড়া একটি ফোকাসড ডিজাইন (_ProductsLayout.cshtml) দেখাতে চাও। এ ধরনের ফিচারের জন্যই Layout ডাইনামিক করা প্রয়োজন।
২. Controller-এ Route Parameter এবং ViewBag সেট করা (Priority: 8/10)
ভিডিওর উদাহরণ অনুযায়ী, আমরা ProductsController-এর Search Action Method-কে একটু মডিফাই করব, যেন এটি একটি অপশনাল Parameter রিসিভ করতে পারে।
Code Implementation:
using Microsoft.AspNetCore.Mvc;
namespace LayoutViewsExample.Controllers
{
public class ProductsController : Controller
{
// {productId?} মানে হলো এই প্যারামিটারটি অপশনাল
[Route("/search-products/{productId?}")]
public IActionResult Search(int? productId)
{
// ইউজারের দেওয়া productId আমরা ViewBag-এ স্টোর করছি
// যেন View-তে গিয়ে এটি চেক করা যায়।
ViewBag.ProductID = productId;
return View();
}
}
}
৩. View-তে Condition চেক করে Layout Override করা (Priority: 10/10)
এবার আমরা Search.cshtml ফাইলে যাব। এখানে আমরা চেক করব ইউজার কোনো productId দিয়েছে কি না।
Code Implementation:
<!-- Views/Products/Search.cshtml -->
@{
// কন্ডিশন চেক করা হচ্ছে
if (ViewBag.ProductID != null)
{
// যদি productId থাকে, তবে নতুন Layout সেট হবে
Layout = "~/Views/Shared/_ProductsLayout.cshtml";
}
// else ব্লকের প্রয়োজন নেই, কারণ _ViewStart.cshtml আগে থেকেই
// ডিফল্ট Layout (_Layout.cshtml) সেট করে রেখেছে।
}
<h1>Search Products</h1>
@if (ViewBag.ProductID != null)
{
<p>Searching details for Product ID: @ViewBag.ProductID</p>
}
else
{
<p>Showing all products search page.</p>
}
৪. Execution Flow (কীভাবে এটি কাজ করে) (Priority: 9/10)
পুরো বিষয়টি ব্যাকএন্ডে কীভাবে কাজ করছে তা বোঝা খুব জরুরি:
- Scenario 1 (No Product ID): ইউজার
localhost/search-productsভিজিট করল।
- প্রথমে
_ViewStart.cshtmlএক্সিকিউট হয়ে ডিফল্ট_Layout.cshtmlসেট করবে। - এরপর
Search.cshtmlরান হবে। যেহেতুViewBag.ProductIDnull, তাইifকন্ডিশনটি ফলস (false) হবে। - ফলাফল: পেজটি ডিফল্ট
_Layout.cshtmlনিয়েই রেন্ডার হবে।
- Scenario 2 (With Product ID): ইউজার
localhost/search-products/10ভিজিট করল।
- প্রথমে
_ViewStart.cshtmlএক্সিকিউট হয়ে ডিফল্ট_Layout.cshtmlসেট করবে। - এরপর
Search.cshtmlরান হবে। এবারViewBag.ProductIDএর মান 10। তাইifকন্ডিশনটি ট্রু (true) হবে। - ফলাফল: View-এর ভেতরের কোড
_ViewStart-এর সেটিংকে Override করে ফেলবে এবং পেজটি_ProductsLayout.cshtmlদিয়ে রেন্ডার হবে।
💡 .NET 10 Smarter Approach & Enhancements
ভিডিওতে ইনস্ট্রাক্টর ViewBag ব্যবহার করে Layout ডাইনামিক করেছেন। এটি বেসিক শেখার জন্য চমৎকার, কিন্তু আধুনিক .NET 10 এন্টারপ্রাইজ লেভেল প্রজেক্টে ViewBag বা ViewData (Magic Strings) এড়িয়ে চলা হয়, কারণ টাইপ ভুল হলে রানটাইম এরর আসতে পারে।
Smarter MVC Approach (Using Strongly Typed ViewModels): Smart ডেভেলপাররা লজিক চেক করার জন্য Strongly Typed Model ব্যবহার করেন অথবা Controller থেকেই Layout-এর সিদ্ধান্ত View-তে পাঠান।
উন্নত পদ্ধতি (Strongly Typed):
// 1. Controller
[Route("/search-products/{productId?}")]
public IActionResult Search(int? productId)
{
// Model হিসেবে ডেটা পাঠানো হচ্ছে
var model = new ProductSearchViewModel
{
ProductId = productId,
HasSpecificProduct = productId.HasValue
};
return View(model);
}
<!-- 2. Search.cshtml -->
@model ProductSearchViewModel
@{
// কোনো Magic String বা ViewBag নেই, সরাসরি Model প্রপার্টি ব্যবহার
if (Model.HasSpecificProduct)
{
Layout = "_ProductsLayout"; // .NET 10-এ শর্ট পাথ সাপোর্ট করে
}
}
<h1>Search Products</h1>
🏆 Best Practices (Dynamic Layouts in MVC)
- Avoid Complex Logic in Views: View ফাইলের
@{ ... }ব্লকে কখনোই খুব জটিলif-else if-elseলজিক বা ডাটাবেস কলিং লিখবে না। View-এর কাজ শুধু UI রেন্ডার করা। লজিকগুলো Controller বা ViewModel-এ প্রসেস করে View-তে পাঠানো উচিত। - Use
_ViewStart.cshtmlfor Global Logic: যদি তোমার এমন কোনো লজিক থাকে যা পুরো অ্যাপ্লিকেশনের Layout পরিবর্তন করবে (যেমন: ইউজার লগ-ইন থাকলে_AdminLayoutআর না থাকলে_GuestLayout), তবে সেই কন্ডিশনগুলো প্রতিটি View-তে না লিখে সরাসরি_ViewStart.cshtmlফাইলে লেখা বেস্ট প্র্যাকটিস। Example in_ViewStart.cshtml:
@{
if (User.Identity.IsAuthenticated)
{
Layout = "_AdminLayout";
}
else
{
Layout = "_Layout";
}
}
- Tilde (~) Avoidance in .NET 10: আধুনিক .NET প্রজেক্টে পুরো পাথ (
"~/Views/Shared/_ProductsLayout.cshtml") লেখার প্রয়োজন হয় না। ফ্রেমওয়ার্ক স্বয়ংক্রিয়ভাবে Shared ফোল্ডারে Layout খুঁজে নেয়। তাই শুধু ফাইলের নাম (Layout = "_ProductsLayout";) লেখাই যথেষ্ট এবং এটি দেখতেও ক্লিন লাগে।