হাসিব, চলো তোমার কোর্সের ১০১ নম্বর লেকচারটি নিয়ে আলোচনা করি। আউটলাইন অনুযায়ী এটি (Section 8: Views - MVC Architecture Pattern) এর একদম শেষ লেকচার, যার শিরোনাম “Shared Views”

আগের লেকচারগুলোতে আমরা দেখেছি যে, সাধারণত একটি Controller-এর View গুলো Views/{ControllerName}/ ফোল্ডারের ভেতরে থাকে। কিন্তু যদি এমন হয় যে একাধিক Controller-এর একই View দরকার? এই লেকচারে ইনস্ট্রাক্টর ঠিক সেই সমস্যার সমাধান হিসেবে Shared Views এর কনসেপ্ট বুঝিয়েছেন।

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


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

ভবিষ্যতে দ্রুত রিভিশন দেওয়ার জন্য এই লেকচারের মূল বিষয়গুলো নিচে পয়েন্ট আকারে দেওয়া হলো:

  • Shared View কী: এটি এমন একটি View, যা প্রজেক্টের যেকোনো Controller থেকে অ্যাক্সেস করা যায়।
  • Folder Name: Shared View-গুলোকে অবশ্যই Views/Shared/ ফোল্ডারের ভেতর রাখতে হয়। Shared নামটি Razor View Engine-এর জন্য ফিক্সড (Fixed)।
  • View Discovery Order (খোঁজার নিয়ম): যখন return View(); কল করা হয়, তখন ইঞ্জিন প্রথমে Views/{ControllerName}/ ফোল্ডারে View-টি খোঁজে। সেখানে না পেলে দ্বিতীয় অপশন হিসেবে Views/Shared/ ফোল্ডারে খোঁজে।
  • Conflict Resolution: যদি একই নামের View নির্দিষ্ট Controller ফোল্ডার এবং Shared ফোল্ডার—উভয় জায়গায় থাকে, তবে Controller ফোল্ডারের View-টিই প্রায়োরিটি পাবে এবং Shared View-টি ইগনোর হবে।
  • Best Use Cases: সাধারণত Layout Views (_Layout.cshtml), Partial Views এবং Error পেজগুলো Shared ফোল্ডারে রাখা হয়।

📌 Introduction to Shared Views [Priority: 10/10]

The Concept: MVC আর্কিটেকচারে বাই-ডিফল্ট প্রতিটি Controller-এর View-গুলো তার নিজস্ব নামের ফোল্ডারে (যেমন- HomeController এর View থাকে Views/Home/ ফোল্ডারে) আবদ্ধ থাকে। অন্য কোনো Controller চাইলেই সেই ফোল্ডারের View ব্যবহার করতে পারে না।

কিন্তু রিয়েল-ওয়ার্ল্ড প্রজেক্টে এমন অনেক সময় আসে যখন দুটি সম্পূর্ণ ভিন্ন Controller-এর জন্য একই UI বা HTML দেখানোর প্রয়োজন হয়। এই ডুপ্লিকেট কোড (Redundant code) এড়ানোর জন্য ASP.NET Core-এ Views/Shared ফোল্ডারের কনসেপ্ট রয়েছে। এই ফোল্ডারে রাখা যেকোনো View পুরো অ্যাপ্লিকেশনের যেকোনো Controller-এর জন্য “Global” বা “Shared” হয়ে যায়।


📌 View Discovery: How ASP.NET Core finds a View [Priority: 10/10]

এটি ইন্টারভিউয়ের জন্য খুবই গুরুত্বপূর্ণ একটি প্রশ্ন। যখন তুমি কোনো Action Method থেকে return View(); লেখো, তখন Razor View Engine ঠিক কীভাবে ওই View ফাইলটি খুঁজে বের করে?

ইঞ্জিন মূলত দুটি লোকেশনে (Locations) ফাইলটি খোঁজে:

  1. Primary Location: প্রথমে সে খোঁজে Views/{ControllerName}/{ViewName}.cshtml পাথে।
  2. Secondary Location (Fallback): যদি প্রথম লোকেশনে ফাইলটি না পাওয়া যায়, তখন সে স্বয়ংক্রিয়ভাবে Views/Shared/{ViewName}.cshtml পাথে খোঁজে।

Conflict Scenario (যদি ফাইল দুই জায়গাতেই থাকে?): ইনস্ট্রাক্টর বলেছেন, যদি all.cshtml ফাইলটি Views/Products/ ফোল্ডারেও থাকে এবং Views/Shared/ ফোল্ডারেও থাকে, তবে MVC সবসময় Controller-specific ফোল্ডারের (অর্থাৎ Products ফোল্ডারের) ফাইলটিকেই আগে রেন্ডার করবে। Shared ফোল্ডারের ফাইলটি ইগনোর হবে।


📌 Step-by-Step Code Implementation [Priority: 9/10]

চলো দেখি ইনস্ট্রাক্টর কীভাবে ProductsController এবং HomeController থেকে একই Shared View অ্যাক্সেস করেছেন।

Step 1: Moving the View to the Shared Folder

প্রথমে Views/Products/ ফোল্ডারে থাকা all.cshtml ফাইলটি কাট (Cut) করে Views/Shared/ ফোল্ডারে পেস্ট করতে হবে।

Step 2: Accessing from ProductsController

// Controllers/ProductsController.cs
using Microsoft.AspNetCore.Mvc;
 
public class ProductsController : Controller
{
    // URL: /products/all
    public IActionResult All()
    {
        // ইঞ্জিন প্রথমে Views/Products/all.cshtml খুঁজবে। 
        // না পেয়ে Views/Shared/all.cshtml রেন্ডার করবে।
        return View(); 
    }
}
 

Step 3: Accessing from HomeController

এবার HomeController-এ একটি নতুন Action Method তৈরি করা হলো যা সম্পূর্ণ ভিন্ন একটি URL-এ কাজ করবে, কিন্তু একই View রেন্ডার করবে।

// Controllers/HomeController.cs
using Microsoft.AspNetCore.Mvc;
 
public class HomeController : Controller
{
    // URL: /home/allproducts
    [Route("home/allproducts")]
    public IActionResult All()
    {
        // ইঞ্জিন প্রথমে Views/Home/all.cshtml খুঁজবে। 
        // না পেয়ে Views/Shared/all.cshtml রেন্ডার করবে।
        return View(); 
    }
}
 

Testing the output: তুমি যদি ব্রাউজারে /products/all হিট করো অথবা /home/allproducts হিট করো—উভয় ক্ষেত্রেই তুমি হুবহু একই HTML আউটপুট (Shared View) দেখতে পাবে।


📌 Why is this important for the Future? [Priority: 8/10]

লেকচারের একদম শেষে ইনস্ট্রাক্টর একটি খুব সুন্দর কথা বলেছেন, যা তোমার পরবর্তী সেকশনগুলোর (Section 9 & 10) জন্য বেস তৈরি করে দিচ্ছে।

রিয়েল-ওয়ার্ল্ড প্রজেক্টে আমরা সাধারণত সাধারণ View-গুলোকে (যেমন- ইউজারের প্রোফাইল, প্রোডাক্ট লিস্ট) Shared ফোল্ডারে রাখি না। আমরা Shared ফোল্ডারটি মূলত নিচের জিনিসগুলোর জন্য ব্যবহার করি:

  1. Layout Views: ওয়েবসাইটের কমন হেডার (Navbar) এবং ফুটার, যা সব পেজেই থাকে।
  2. Partial Views: ছোট ছোট Reusable UI কম্পোনেন্ট (যেমন- একটি ছোট লগিন ফর্ম বা প্রোডাক্ট কার্ড)।
  3. Error Pages: গ্লোবাল এরর হ্যান্ডলিংয়ের জন্য Error.cshtml পেজ।

⭐ Best Practices & Modern .NET 10 Context

Shared ফোল্ডার এবং View Discovery-এর কনসেপ্টটি MVC-এর একদম শুরুর দিক থেকে আজ .NET 10 পর্যন্ত সম্পূর্ণ অপরিবর্তিত আছে। নিচে আধুনিক প্রজেক্টের কিছু বেস্ট প্র্যাকটিস দেওয়া হলো:

  1. Don’t Dump Everything in Shared: কখনোই অযথা সাধারণ View-গুলোকে Shared ফোল্ডারে রাখবে না। Shared ফোল্ডারে ফাইল বেশি হয়ে গেলে প্রজেক্ট মেইনটেইন করা খুব কঠিন হয়ে যায়। শুধুমাত্র সেই ফাইলগুলোকেই Shared-এ রাখবে যেগুলো সত্যি সত্যি অ্যাপ্লিকেশনের গ্লোবাল লেভেলে (একাধিক Controller-এ) ব্যবহৃত হয়।
  2. Specify View Name if Action Method differs (Modern Approach): যদি তোমার Action Method-এর নাম AllProducts() হয়, কিন্তু তুমি Shared ফোল্ডার থেকে all.cshtml রেন্ডার করতে চাও, তবে তোমাকে অবশ্যই View-এর নামটি String হিসেবে পাস করতে হবে।
public IActionResult AllProducts()
{
    // যেহেতু মেথডের নাম AllProducts, ইঞ্জিন AllProducts.cshtml খুঁজবে।
    // তাই স্পেসিফিকভাবে "all" বলে দিতে হবে।
    return View("all"); 
}
 
 
  1. Using Shared Partial Views (Modern Component-based Thinking): .NET 10-এ যদি দুটি Controller-এর কোনো নির্দিষ্ট অংশের UI (যেমন- একটি টেবিল) সেম হয়, তবে পুরো পেজটিকে Shared না করে, ওই টেবিলটুকুকে একটি Partial View বা View Component (যা তুমি Section 11-এ শিখবে) হিসেবে তৈরি করে Shared ফোল্ডারে রাখা হয়। এরপর নির্দিষ্ট Controller-এর View থেকে ওই Partial View-টিকে কল করা হয়। এটি অনেক বেশি ক্লিন এবং স্ট্যান্ডার্ড এপ্রোচ।