স্বাগতম! আজকে আমরা আপনার আউটলাইনের #312: UseExceptionHandler টপিকটি শিখতে যাচ্ছি।

আগের লেকচারগুলোতে আমরা দেখেছি কীভাবে Custom Exception তৈরি করতে হয় এবং Custom Middleware দিয়ে Error ধরতে হয়। কিন্তু Production-এ ইউজারকে তো শুধু একটি প্লেন টেক্সট দেখালে হবে না, তাই না? ইউজারকে একটি সুন্দর UI বা Error Page (যেমন একটি ইমেজ বা সুন্দর মেসেজ) দেখানো উচিত। আজকে আমরা শিখবো ASP.NET Core-এর Built-in UseExceptionHandler ব্যবহার করে কীভাবে এই কাজটি খুব সহজেই করা যায়।


📝 Quick Summary (For Future Revision)

  • Purpose: UseExceptionHandler হলো একটি Built-in Middleware যা Exception ঘটলে ইউজারকে একটি নির্দিষ্ট Route-এ (যেমন /Home/Error) রিডাইরেক্ট করে।
  • Custom vs Built-in: Custom Middleware মূলত Error লগ করার জন্য (যেমন Serilog) ব্যবহৃত হয়। আর Built-in Middleware-টি Error পেজে রিডাইরেক্ট করার জন্য ব্যবহৃত হয়।
  • Rethrowing: Custom Middleware-এ Error ক্যাচ করে লগ করার পর throw; ব্যবহার করে পুনরায় Exception-টি থ্রো করতে হয়, যেন UseExceptionHandler তা ধরতে পারে।
  • IExceptionHandlerPathFeature: Error Page-এর Controller-এ এই ইন্টারফেসটি ব্যবহার করে আমরা ঘটা Exception-এর বিস্তারিত তথ্য (যেমন Exception Message, Stack Trace) অ্যাক্সেস করতে পারি।
  • UseStatusCodePages: নির্দিষ্ট Status Code (যেমন 404, 500)-এর জন্য আলাদা আলাদা Error Page দেখানোর জন্য UseStatusCodePagesWithRedirects ব্যবহৃত হয়।

🧠 Comprehensive Breakdown

১. Built-in UseExceptionHandler কেন ব্যবহার করবো? (Priority: 9/10)

Why: Custom Exception Handling Middleware দিয়ে আমরা Exception ক্যাচ করে ডাটাবেস বা ফাইলে লগ (Log) করতে পারি। কিন্তু ইউজারকে একটি প্রপার HTML Error Page (যেখানে নেভিগেশন বার, ফুটার, সুন্দর ইমেজ থাকবে) দেখানোর জন্য একটি Controller এবং View-তে রিডাইরেক্ট করা সবচেয়ে ভালো পদ্ধতি। UseExceptionHandler ঠিক এই কাজটিই করে।

২. Pipeline-এ Middleware সেটআপ করা (Priority: 10/10)

Program.cs ফাইলে Production Environment-এর জন্য এই Middleware-টি একদম শুরুতে বসাতে হবে।

Code Implementation:

if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    // Redirects to /Home/Error when any exception occurs
    app.UseExceptionHandler("/Home/Error"); 
    
    // Our custom middleware for logging
    app.UseMiddleware<ExceptionHandlingMiddleware>();
}
 

৩. Custom Middleware থেকে Exception Rethrow করা (Priority: 8/10)

যেহেতু Request Pipeline-এ আমাদের Custom Middleware-টি UseExceptionHandler-এর ঠিক নিচেই থাকে, তাই Custom Middleware-এর catch ব্লকে Error লগ করার পর সেটিকে আবার Rethrow করতে হবে।

Why: Rethrow না করলে UseExceptionHandler জানতেই পারবে না যে কোনো Exception ঘটেছে।

Code Implementation:

public async Task Invoke(HttpContext httpContext)
{
    try
    {
        await _next(httpContext);
    }
    catch (Exception ex)
    {
        // 1. Log the exception to Serilog
        _logger.LogError(ex, ex.Message);
 
        // 2. Rethrow the exception so UseExceptionHandler can catch it
        throw; 
    }
}
 

৪. Home Controller এবং Error View তৈরি করা (Priority: 8/10)

যেহেতু আমরা app.UseExceptionHandler("/Home/Error") দিয়েছি, তাই আমাদের একটি HomeController এবং তার ভেতরে Error Action Method লাগবে।

  • View Location: Error View-টি Views/Shared ফোল্ডারে রাখা ভালো, কারণ এটি পুরো প্রজেক্টের যেকোনো Controller-এর Error-এর জন্য কল হতে পারে।

View (Views/Shared/Error.cshtml):

<div class="text-center mt-5">
    <h1 class="text-danger">Error</h1>
    <h3 class="text-danger">@ViewBag.ErrorMessage</h3>
    <img src="~/error.svg" alt="Error Icon" style="margin-top: 100px;" />
</div>
 

৫. IExceptionHandlerPathFeature দিয়ে Exception ডিটেইলস বের করা (Priority: 10/10)

Why: Error Action Method-এ বসে আমরা কীভাবে জানবো যে ঠিক কী Exception ঘটেছিল? ASP.NET Core যখন UseExceptionHandler-এর মাধ্যমে রিডাইরেক্ট করে, তখন সে Exception-এর সমস্ত ডিটেইলস HttpContext.Features-এর ভেতর সেভ করে দেয়।

Code Implementation:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Diagnostics;
 
public class HomeController : Controller
{
    [Route("Error")]
    public IActionResult Error()
    {
        // Extracting the exception feature
        var exceptionHandlerPathFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
 
        if (exceptionHandlerPathFeature != null && exceptionHandlerPathFeature.Error != null)
        {
            // Getting the actual exception message
            ViewBag.ErrorMessage = exceptionHandlerPathFeature.Error.Message;
        }
        else
        {
            ViewBag.ErrorMessage = "An unexpected error occurred.";
        }
 
        return View();
    }
}
 

৬. Status Code-এর ভিত্তিতে আলাদা Error Page (Bonus) (Priority: 7/10)

যদি আপনি 404 (Not Found) এবং 500 (Internal Server Error)-এর জন্য আলাদা আলাদা পেজ দেখাতে চান, তবে Microsoft Docs অনুযায়ী আপনি UseStatusCodePagesWithRedirects ব্যবহার করতে পারেন।

// If a 404 occurs, it redirects to /StatusCode/404
app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");
 

🚀 Modern .NET 10 Update (Smarter & Updated)

ভিডিওর প্রসেসটি (MVC-এর জন্য app.UseExceptionHandler("/Home/Error")) .NET 10-এও একদম 100% স্ট্যান্ডার্ড এবং ভ্যালিড। MVC অ্যাপ্লিকেশনের ক্ষেত্রে View দেখানোর জন্য এটাই বেস্ট অ্যাপ্রোচ।

তবে, আধুনিক .NET-এ (বিশেষ করে Web API বা Minimal API-এর ক্ষেত্রে) গ্লোবাল Exception Handling-এর জন্য IExceptionHandler (যা আমরা আগের লেকচারে আলোচনা করেছি) অনেক বেশি জনপ্রিয়। MVC-এর ক্ষেত্রে যদি আপনি IExceptionHandler ব্যবহার করেন, তাহলেও Error পেজে রিডাইরেক্ট করার কাজটা আপনি ওই ইন্টারফেসের ভেতর থেকেই করতে পারেন:

// .NET 10 Modern Approach using IExceptionHandler for MVC
public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken)
{
    _logger.LogError(exception, "System Error");
    
    // Redirecting manually programmatically
    httpContext.Response.Redirect("/Home/Error");
    
    return true; // Mark as handled
}
 

⌨️ Shortcuts for Controllers & Views

  • Visual Studio: নতুন Controller বা View অ্যাড করার জন্য ফোল্ডারের ওপর রাইট-ক্লিক করে Add মেনুতে যাওয়ার বদলে, ফোল্ডার সিলেক্ট করে Ctrl + Shift + A চাপুন।
  • Visual Studio Code: VS Code-এ সরাসরি UI থেকে Controller বানানোর অপশন নেই। Terminal ব্যবহার করা সবচেয়ে স্মার্ট:
  • Controller বানাতে: dotnet new mvccontroller -n HomeController
  • View বানাতে: dotnet new view -n Error

🏆 Best Practices (Error Handling UI)

  1. Do NOT Expose Real Errors in Production: ভিডিওতে exceptionHandlerPathFeature.Error.Message সরাসরি UI-তে (ViewBag দিয়ে) দেখানো হয়েছে শেখানোর উদ্দেশ্যে। কিন্তু রিয়েল-ওয়ার্ল্ড Production অ্যাপ্লিকেশনে ডাটাবেসের একচুয়াল Error Message বা Stack Trace কখনোই ইউজারকে দেখাবেন না। এর বদলে সবসময় “Sorry, something went wrong. Our team has been notified.” জাতীয় জেনেরিক মেসেজ দেখাবেন এবং আসল Error-টি Serilog-এ লগ করে রাখবেন।
  2. Use Shared Folder: Error View সবসময় Views/Shared ফোল্ডারে রাখবেন। এতে করে অ্যাপ্লিকেশন আর্কিটেকচার ক্লিন থাকে এবং যেকোনো জায়গার Error একই View ব্যবহার করতে পারে।