এই লেকচারে ASP.NET Core-এ Custom Route Constraints কীভাবে তৈরি এবং ব্যবহার করতে হয়, তা নিয়ে বিস্তারিত আলোচনা করা হয়েছে। আগের লেকচারে আমরা ডিফল্ট Constraints (যেমন: int, regex, alpha) দেখেছি। কিন্তু যদি আমাদের নিজেদের কোনো জটিল লজিক বারবার বিভিন্ন Endpoint-এ ব্যবহার করতে হয়, তখন এই Custom Constraints খুব কাজে আসে।
চলো পুরো বিষয়টি ধাপে ধাপে বিস্তারিতভাবে বুঝে নিই।
১. বিস্তারিত বিশ্লেষণ (Comprehensive Breakdown)

ক. Custom Constraint কী এবং কেন প্রয়োজন?
যদি তোমার অ্যাপ্লিকেশনের একাধিক জায়গায় একই Regular Expression বা লজিক বারবার লিখতে হয় (যেমন: মাসের নাম যাচাই করা), তবে ম্যানুয়ালি কোড রিপিট না করে তুমি একটি Custom Constraint তৈরি করতে পারো।
- এটি মূলত একটি ক্লাস (Class), যা একটি সাধারণ Constraint-এর মতোই কাজ করে।
- যখন কোনো Request আসে, তখন Routing Middleware এই ক্লাসটিকে এক্সিকিউট করে চেক করে যে URL Value-টি এই কাস্টম লজিকের সাথে ম্যাচ করে কি না।
খ. Custom Constraint ক্লাস তৈরি করা (Step-by-Step)
- ফোল্ডার ও ফাইল তৈরি: প্রজেক্ট ক্লিন রাখার জন্য
CustomConstraintsনামে একটি আলাদা ফোল্ডার তৈরি করে তার ভেতরMonthsCustomConstraint.csনামে একটি ক্লাস ফাইল তৈরি করতে হবে। - Interface ইমপ্লিমেন্ট করা: ক্লাসটিকে অবশ্যই
IRouteConstraintনামের একটি বিল্ট-ইন ইন্টারফেস ইমপ্লিমেন্ট করতে হবে। - Match মেথড: এই ইন্টারফেসের ভেতরে
Matchনামের একটি নির্দিষ্ট মেথড থাকে, যা ক্লাসের ভেতর ইমপ্লিমেন্ট করা বাধ্যতামূলক। রিকোয়েস্ট আসার সাথে সাথে ASP.NET Core স্বয়ংক্রিয়ভাবে এই মেথডটি কল করে।
গ. Match মেথডের প্যারামিটার পরিচিতি
Match মেথডে বেশ কয়েকটি গুরুত্বপূর্ণ প্যারামিটার থাকে:
HttpContext: এটি বর্তমান Request এবং Response অবজেক্ট ধারণ করে।IRouter: এটি সেই Route-কে রিপ্রেজেন্ট করে, যেখানে এই কনস্ট্রেইন্টটি অ্যাপ্লাই করা হয়েছে।routeKey: এটি Route Parameter-এর নাম (যেমন আমাদের ক্ষেত্রেmonth)।values(RouteValueDictionary): এটি URL থেকে আসা সমস্ত প্যারামিটারের ভ্যালু ধারণ করে।routeDirection: এটি বোঝায় রিকোয়েস্টটি কি Incoming Request নাকি URL Generation (এটি মূলত MVC আর্কিটেকচারে কাজে লাগে, তাই আপাতত এটি ইগনোর করা যায়)।
ঘ. Custom Constraint-এর লজিক লেখা (Code Implementation)
নিচে MonthsCustomConstraint ক্লাসের সম্পূর্ণ ইমপ্লিমেন্টেশন দেওয়া হলো:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using System.Text.RegularExpressions;
namespace YourProjectName.CustomConstraints
{
public class MonthsCustomConstraint : IRouteConstraint
{
public bool Match(HttpContext? httpContext, IRouter? route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
// ১. চেক করা হচ্ছে URL-এ 'month' প্যারামিটারটি আছে কি না
if (!values.ContainsKey(routeKey))
{
return false; // না থাকলে ম্যাচ ফেইল করবে
}
// ২. ভ্যালুটিকে স্ট্রিংয়ে কনভার্ট করা
string? monthValue = values[routeKey]?.ToString();
// ৩. Regular Expression লজিক (শুধু apr, jul, oct, jan এক্সেপ্ট করবে)
Regex regex = new Regex("^(apr|jul|oct|jan)$", RegexOptions.IgnoreCase);
// ৪. চেক করা হচ্ছে ভ্যালুটি Regex-এর সাথে ম্যাচ করে কি না
if (monthValue != null && regex.IsMatch(monthValue))
{
return true; // ম্যাচ করলে true রিটার্ন করবে
}
return false; // কোনো কারণে ম্যাচ না করলে false
}
}
}
ঙ. Constraint রেজিস্টার করা (Program.cs)
ক্লাস তৈরি করার পর এটিকে সরাসরি ব্যবহার করা যাবে না। প্রথমে একে অ্যাপ্লিকেশন বিল্ডারের Constraint Map-এ রেজিস্টার করতে হবে।
// Program.cs ফাইলে builder.Build() এর আগে লিখতে হবে:
builder.Services.AddRouting(options =>
{
// "months" নামে আমাদের Custom Constraint টি রেজিস্টার করা হলো
options.ConstraintMap.Add("months", typeof(MonthsCustomConstraint));
});
চ. Endpoint-এ Custom Constraint ব্যবহার করা
রেজিস্ট্রেশন হয়ে যাওয়ার পর, তুমি যেকোনো Endpoint-এ ঠিক ডিফল্ট কনস্ট্রেইন্টের মতোই এটি ব্যবহার করতে পারবে।
// আগে আমরা লিখতাম: {month:regex(^(apr|jul|oct|jan)$)}
// এখন আমরা লিখব: {month:months}
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("sales-report/{year:min(1900)}/{month:months}", async context =>
{
var month = context.Request.RouteValues["month"];
await context.Response.WriteAsync($"Sales report for: {month}");
});
});
- Runtime Behavior: ইউজার যখন
sales-report/2024/janলিখে হিট করবে, অ্যাপ্লিকেশনMonthsCustomConstraintক্লাসে যাবে এবংMatchমেথড এক্সিকিউট করবে।trueরিটার্ন হলে কোড রান হবে, আর ভুল মাস দিলেfalseরিটার্ন হয়ে Fallback Route এক্সিকিউট হবে।
ছ. Best Practice & Recommendation (রিয়েল ওয়ার্ল্ড সিনারিও)
লেকচারের শেষে ইন্সট্রাক্টর একটি অত্যন্ত গুরুত্বপূর্ণ কথা মনে করিয়ে দিয়েছেন:
- Reusability: যদি লজিকটি পুরো প্রোজেক্টে একবারই ব্যবহার হয়, তবে কাস্টম কনস্ট্রেইন্ট বানানোর কোনো মানে নেই। এটি শুধু তখনি বানাবে, যখন লজিকটি বিভিন্ন জায়গায় বারবার ব্যবহার (Reuse) করতে হবে।
- Validation vs Constraints: Microsoft-এর মতে ডেটা ভ্যালিডেশনের জন্য Route Constraints ব্যবহার করা উচিত নয়। এর বদলে প্যারামিটার এক্সেপ্ট করে, কোডের ভেতর
if-elseদিয়ে চেক করে ক্লায়েন্টকে একটি নির্দিষ্ট 400 Bad Request রেসপন্স পাঠানো রিয়েল-ওয়ার্ল্ড অ্যাপ্লিকেশনের জন্য বেস্ট প্র্যাকটিস।
২. মূল্যায়ন (Critical Evaluation)
-
সবল দিক (Strengths):
-
কাস্টম ক্লাস তৈরি থেকে শুরু করে
Program.cs-এ রেজিস্টার করা পর্যন্ত পুরো ফ্লো-টি অত্যন্ত ক্লিয়ারলি ধাপে ধাপে দেখানো হয়েছে। -
Matchমেথডের প্রতিটি প্যারামিটারের কাজ সহজভাবে ব্যাখ্যা করা হয়েছে। -
Visual Studio-তে Breakpoint ব্যবহার করে রানটাইমে কীভাবে ডেটা ফ্লো হয়, সেটি চেক করার পদ্ধতিটি বেশ প্র্যাকটিক্যাল।
-
কখন Custom Constraint ব্যবহার করা উচিত এবং কখন উচিত নয়— এই বিষয়ে স্পষ্ট গাইডলাইন দেওয়া হয়েছে।
-
সীমাবদ্ধতা (Limitations):
-
Custom Constraint ক্লাসের ভেতর Dependency Injection (যেমন: ডাটাবেস থেকে কিছু চেক করা) কীভাবে কাজ করে, তা দেখানো হয়নি।
-
RouteDirectionপ্যারামিটারের ব্যবহার শুধু মুখে বলা হয়েছে, এর কোনো কোড উদাহরণ দেওয়া হয়নি।
৩. পরবর্তী ধাপ ও প্রাসঙ্গিক বিষয় (Future Learning Path)
এই টপিকটি আয়ত্ত করার পর তোমার লার্নিং পাথ হিসেবে নিচের বিষয়গুলো স্টাডি করা উচিত:
IRouteConstraintwith Dependency Injection: (Custom Constraint-এর ভেতর ডাটাবেস বা অন্যান্য সার্ভিস কল করা)।- Model Validation in ASP.NET Core: (Route Constraint-এর বদলে Data Annotations বা FluentValidation ব্যবহার করা)।
- URL Generation (
RouteDirection.UrlGeneration): (MVC বা Razor Pages-এ কোড থেকে ডাইনামিকভাবে URL তৈরি করার সময় কনস্ট্রেইন্ট কীভাবে কাজ করে)। - Endpoint Routing Middleware Pipeline: (রিকোয়েস্ট ঠিক কোন ধাপে কনস্ট্রেইন্ট চেক করে তা আরও গভীরভাবে বোঝা)।