স্বাগতম! আপনার কোর্সের Section 20 (Filters)-এর অত্যন্ত গুরুত্বপূর্ণ একটি টপিক—“Filter Attribute Classes” (লেকচার ৩০২)-এ আমরা চলে এসেছি।

আগের লেকচারগুলোতে আমরা ফিল্টার অ্যাপ্লাই করার জন্য [TypeFilter(typeof(MyFilter))] বা [ServiceFilter(typeof(MyFilter))] ব্যবহার করেছি। কিন্তু এগুলো দেখতে একটু “Messy” বা এলোমেলো লাগে। যদি আমরা সরাসরি আমাদের ফিল্টারের নাম দিয়েই [MyFilter] লিখতে পারতাম, তবে কোড দেখতে কত সুন্দর হতো, তাই না? আজ আমরা শিখব কীভাবে ActionFilterAttribute ক্লাস ইনহেরিট করে সরাসরি ফিল্টারকে অ্যাট্রিবিউট হিসেবে ব্যবহার করা যায়। চলুন শুরু করি!


📝 Quick Revision Summary

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

  • The Goal: [TypeFilter(typeof(MyFilter))]-এর বদলে সরাসরি [MyFilter] ব্যবহার করা।
  • How to do it: IActionFilter ইন্টারফেস ইমপ্লিমেন্ট করার বদলে, বিল্ট-ইন ActionFilterAttribute ক্লাসকে ইনহেরিট (inherit) করতে হবে।
  • Benefits: 1. এটি ব্যাকগ্রাউন্ডে Attribute ক্লাস থেকে ইনহেরিট করা থাকে, তাই সরাসরি [FilterName] হিসেবে ব্যবহার করা যায়।
  1. এতে আগে থেকেই IOrderedFilter ইমপ্লিমেন্ট করা থাকে, তাই Order প্রপার্টি আলাদা করে লিখতে হয় না।
  2. মেথডগুলো virtual থাকে, তাই আপনার যেটা দরকার শুধু সেটাকেই override করলেই হয়।
  • The Biggest Drawback: Constructor Injection সাপোর্ট করে না! অর্থাৎ, আপনি ILogger বা অন্য কোনো সার্ভিস কনস্ট্রাক্টরের মাধ্যমে ইনজেক্ট করতে পারবেন না।

🔍 Comprehensive Breakdown

১. Interface vs Attribute Class (মূল পার্থক্য) [Priority: 10/10]

এতদিন আমরা ফিল্টার বানানোর সময় Interface (IActionFilter, IAsyncActionFilter) ব্যবহার করতাম। এর কিছু সুবিধা ও অসুবিধা আছে:

  • Interface-এর সুবিধা: Dependency Injection (DI) দারুণভাবে সাপোর্ট করে।
  • Interface-এর অসুবিধা: ফিল্টার অ্যাপ্লাই করার সময় [TypeFilter] লিখতে হয়, যা দেখতে একটু বড়। ইন্টারফেসের সবগুলো মেথড বাধ্যতামূলকভাবে ইমপ্লিমেন্ট করতে হয়।

এবার আসি Attribute Class (ActionFilterAttribute, ResultFilterAttribute)-এর কথায়:

  • Attribute Class-এর সুবিধা: সরাসরি [MyFilter] লেখা যায়। শুধু যে মেথড দরকার, সেটাকেই override করা যায়।
  • Attribute Class-এর অসুবিধা: Constructor Injection কাজ করে না! (এটি রিয়েল-ওয়ার্ল্ড প্রোজেক্টের জন্য বড় একটি সমস্যা)।

২. Code Implementation: Converting to Attribute Class [Priority: 10/10]

লেকচারে আমাদের আগের ResponseHeaderActionFilter-কে ইন্টারফেস থেকে অ্যাট্রিবিউট ক্লাসে কনভার্ট করে দেখানো হয়েছে।

using Microsoft.AspNetCore.Mvc.Filters;
 
// ১. IActionFilter-এর বদলে ActionFilterAttribute ক্লাসকে ইনহেরিট করা হচ্ছে
public class ResponseHeaderActionFilter : ActionFilterAttribute
{
    private readonly string _key;
    private readonly string _value;
 
    // ২. Constructor Injection রিমুভ করতে হয়েছে! (ILogger বাদ দেওয়া হয়েছে)
    // Order প্রপার্টিটি ActionFilterAttribute-এ আগে থেকেই আছে, তাই এখানে ডিক্লেয়ার করার দরকার নেই।
    public ResponseHeaderActionFilter(string key, string value, int order)
    {
        _key = key;
        _value = value;
        Order = order; // Base ক্লাসের প্রপার্টিতে সেট করা হচ্ছে
    }
 
    // ৩. মেথডগুলোকে override কিওয়ার্ড দিয়ে লিখতে হবে
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        // Before logic
        // (এখানে Logger ব্যবহার করা যাচ্ছে না, কারণ DI নেই)
    }
 
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        // After logic
        context.HttpContext.Response.Headers[_key] = _value;
    }
}
 

৩. Applying the Filter Attribute [Priority: 10/10]

যেহেতু এটি এখন একটি অ্যাট্রিবিউট, তাই Controller-এ এর ব্যবহার অত্যন্ত ক্লিন হয়ে গেছে:

using Microsoft.AspNetCore.Mvc;
 
public class PersonsController : Controller
{
    // TypeFilter বা ServiceFilter-এর আর কোনো দরকার নেই!
    // সরাসরি ফিল্টারের নাম এবং আর্গুমেন্ট পাস করা যাচ্ছে।
    [ResponseHeaderActionFilter("X-Custom-Key", "Awesome-Value", 1)]
    public IActionResult Index()
    {
        return View();
    }
}
 

৪. The Microsoft Recommendation [Priority: 9/10]

লেকচারের শেষের দিকে একটি অত্যন্ত গুরুত্বপূর্ণ কথা বলা হয়েছে। মাইক্রোসফটের অফিশিয়াল গাইডলাইন অনুযায়ী, Interface (IActionFilter) ব্যবহার করাটাই Best Practice। কারণ, আধুনিক ওয়েব ডেভেলপমেন্টে লগিং (ILogger), ডেটাবেস অ্যাক্সেস (DbContext) বা অন্য কোনো সার্ভিস ফিল্টারের ভেতরে প্রয়োজন হতেই পারে। Attribute Class ব্যবহার করলে আপনি সেই সার্ভিসগুলো কনস্ট্রাক্টরে ইনজেক্ট করতে পারবেন না, যা আর্কিটেকচারের জন্য একটি বড় বাধা।


🚀 Best Practices & The Next Step

The Ultimate Question: আমরা কি এমন কোনো উপায় বের করতে পারি, যেখানে:

  1. আমরা [MyFilter]-এর মতো ক্লিন অ্যাট্রিবিউট সিনট্যাক্স পাব।
  2. আবার Constructor Injection (যেমন ILogger) ঠিকই কাজ করবে।

The Answer: হ্যাঁ! এই “Best of both worlds” (দোকানের সেরা দুটি জিনিস একসাথে পাওয়া) অর্জনের জন্যই ASP.NET Core-এ IFilterFactory নামের একটি চমৎকার ফিচার আছে।

.NET 10 Modern Approach: .NET 10 এবং আধুনিক MVC আর্কিটেকচারে কাস্টম ফিল্টার বানানোর সবচেয়ে প্রফেশনাল, স্কেলেবল এবং ক্লিন উপায় হলো এই IFilterFactory ব্যবহার করা।

আপনার কোর্সের ঠিক পরের লেকচারেই (IFilterFactory) এটি নিয়ে বিস্তারিত আলোচনা করা হবে, যা ফিল্টার সেকশনের সবচেয়ে অ্যাডভান্সড এবং কাজের টপিকগুলোর একটি। আপনি রেডি হলে আমরা পরের লেকচার শুরু করতে পারি!