আজকের লেকচারে স্বাগতম!

কোথায় আছি আমরা? আপনি বর্তমানে Section 25: Identity-তে আছেন। গত লেকচারগুলোতে আমরা রেজিস্ট্রেশন এবং লগইন সম্পন্ন করেছি। কিন্তু একটি সমস্যা হলো, যদি কোনো ইউজার এমন একটি ইমেইল দিয়ে রেজিস্ট্রেশন করার চেষ্টা করে যা অলরেডি ডাটাবেসে আছে, তবে ফর্মটি সাবমিট হওয়ার পর পুরো পেজটি রিলোড হয় এবং তারপর এরর দেখায়। এটি ইউজারের এক্সপেরিয়েন্সের জন্য খুব একটা ভালো নয়।

আজকে আমরা শিখবো Remote Validation। এর মাধ্যমে ইউজার ইমেইল টাইপ করে অন্য টেক্সট বক্সে যাওয়ার (Tab press) সাথে সাথেই ব্যাকগ্রাউন্ডে একটি Asynchronous (AJAX) রিকোয়েস্ট সার্ভারে যাবে এবং পেজ রিলোড ছাড়াই চেক করে জানাবে ইমেইলটি অলরেডি ডাটাবেসে আছে কিনা। চলুন শুরু করি!


📝 Quick Summary for Revision

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

  • The Problem: ডুপ্লিকেট ইমেইল দিলে ফর্ম সাবমিট হওয়ার পর পুরো পেজ রিলোড হয়ে এরর দেখায়।
  • The Solution (Remote Validation): ফর্ম সাবমিট করার আগেই ব্যাকগ্রাউন্ডে AJAX কল করে সার্ভার থেকে ভ্যালিডেশন চেক করা।
  • Action Method: Controller-এ এমন একটি মেথড তৈরি করতে হয় যা ইনপুট স্ট্রিং (ইমেইল) রিসিভ করবে এবং true বা false (JSON আকারে) রিটার্ন করবে।
  • UserManager Check: _userManager.FindByEmailAsync() ব্যবহার করে চেক করা হয় ওই ইমেইলে কোনো ইউজার আছে কিনা।
  • NuGet Package: Remote অ্যাট্রিবিউট ব্যবহার করার জন্য Core প্রজেক্টে Microsoft.AspNetCore.Mvc.ViewFeatures প্যাকেজটি ইন্সটল করতে হয়।
  • Model Configuration: DTO ক্লাসে প্রপার্টির ওপর [Remote(action: "MethodName", controller: "ControllerName")] যুক্ত করতে হয়।

🧠 Comprehensive Breakdown

এখানে লেকচারের প্রতিটি বিষয় বিস্তারিতভাবে এবং ধাপে ধাপে ব্যাখ্যা করা হলো:

১. The Existing Problem (Priority: 9/10)

বর্তমানে যখন কেউ smith@example.com (যা অলরেডি ডাটাবেসে আছে) দিয়ে রেজিস্ট্রেশন করার চেষ্টা করে:

  1. ইউজার সব ডেটা ফিলাপ করে সাবমিট বাটনে ক্লিক করে।
  2. সার্ভারে পুরো ডেটা (নাম, ফোন, পাসওয়ার্ড সব) যায়।
  3. UserManager এর CreateAsync মেথড ডুপ্লিকেট ইমেইল ধরে ফেলে এবং ఫেইল করে।
  4. সার্ভার পুরো HTML পেজটি আবার রিলোড করে ব্রাউজারে পাঠায়।
  5. সিকিউরিটির কারণে পাসওয়ার্ড ফিল্ডগুলো খালি হয়ে যায়।

পুরো পেজ রিলোড হওয়া সার্ভার এবং ইউজার উভয়ের জন্যই বিরক্তিকর। ব্রাউজার নিজে থেকে ডাটাবেস চেক করতে পারে না। তাই আমাদের এমন কিছু দরকার যা পেজ রিলোড না করেই ডাটাবেসের সাথে কথা বলতে পারবে।

২. Step 1: Creating the Validation Action Method (Priority: 10/10)

আমাদের AccountController-এ একটি নতুন মেথড তৈরি করতে হবে। এই মেথডটির কাজ হবে শুধু ইমেইলটি রিসিভ করা এবং চেক করে true বা false জানানো।

  • Return true: মানে ইমেইলটি ইউনিক, রেজিস্ট্রেশন করা যাবে।
  • Return false: মানে ইমেইলটি অলরেডি ডাটাবেসে আছে, রেজিস্ট্রেশন করা যাবে না।

💻 Code Implementation (AccountController.cs):

[HttpGet] // এটি একটি GET রিকোয়েস্ট হবে
[AllowAnonymous] // লগইন ছাড়াই যেন কল করা যায়
public async Task<IActionResult> IsEmailAlreadyRegistered(string email)
{
    // ডাটাবেসে ইমেইলটি খোঁজা হচ্ছে
    ApplicationUser user = await _userManager.FindByEmailAsync(email);
 
    if (user == null)
    {
        // ইউজার না পাওয়া গেলে (মানে ইমেইলটি নতুন), true রিটার্ন করবে
        return Json(true); 
    }
    else
    {
        // ইউজার পাওয়া গেলে (মানে ইমেইলটি অলরেডি আছে), false রিটার্ন করবে
        return Json(false); 
    }
}
 

৩. Step 2: Installing the NuGet Package (Priority: 8/10)

DTO ক্লাসে Remote Validation ব্যবহার করার জন্য একটি নির্দিষ্ট অ্যাট্রিবিউট লাগে যা বাই ডিফল্ট Core প্রজেক্টে থাকে না।

  • Core প্রজেক্টের ওপর রাইট ক্লিক করে Manage NuGet Packages-এ যান।
  • সার্চ করুন: Microsoft.AspNetCore.Mvc.ViewFeatures
  • আপনার অ্যাপ্লিকেশনের .NET ভার্সনের সাথে মিলিয়ে এটি ইন্সটল করুন।

৪. Step 3: Applying [Remote] Attribute in DTO (Priority: 10/10)

এখন আমাদের RegisterDTO ক্লাসের ইমেইল প্রপার্টিতে গিয়ে বলে দিতে হবে যে, “এই ইমেইলটি ভ্যালিডেট করার জন্য তুমি ব্যাকগ্রাউন্ডে ওই কন্ট্রোলারের ওই মেথডকে কল করবে।”

💻 Code Implementation (RegisterDTO.cs):

using Microsoft.AspNetCore.Mvc; // Remote অ্যাট্রিবিউটের জন্য
 
public class RegisterDTO
{
    [Required(ErrorMessage = "Email can't be blank")]
    [EmailAddress(ErrorMessage = "Email should be in a proper valid email format")]
    
    // Remote Validation যুক্ত করা হচ্ছে
    [Remote(action: "IsEmailAlreadyRegistered", controller: "Account", ErrorMessage = "Email is already in use")]
    
    public string Email { get; set; }
    
    // ... অন্যান্য প্রপার্টি ...
}
 

৫. How it Works at Runtime (Priority: 9/10)

  1. যখন প্রজেক্ট রান করবেন, Register.cshtml পেজে থাকা jquery.validate.unobtrusive.js স্ক্রিপ্টটি [Remote] অ্যাট্রিবিউট দেখে অটোমেটিকভাবে একটি জাভাস্ক্রিপ্ট কোড তৈরি করে নিবে।
  2. ইউজার ইমেইল বক্সে smith@example.com টাইপ করে যখনই ইনপুট ফিল্ড থেকে বের হবে (Tab press বা অন্য কোথাও ক্লিক করবে), সাথে সাথেই ব্রাউজার পেজ রিলোড না করে একটি AJAX (Asynchronous) GET রিকোয়েস্ট পাঠাবে।
  • URL: .../Account/IsEmailAlreadyRegistered?email=smith@example.com
  1. সার্ভার চেক করে false রেসপন্স দিবে (যেহেতু smith আগে থেকেই আছে)।
  2. ব্রাউজার সাথে সাথেই ইনপুট বক্সের নিচে লাল রঙের মেসেজ দেখাবে: “Email is already in use”।
  3. এই অবস্থায় ফর্ম সাবমিট বাটনটি ডিজেবল (Disable) হয়ে থাকবে বা সাবমিট করলেও ক্লায়েন্ট-সাইডেই আটকে দিবে।

🌟 Best Practices & Modern Updates (.NET 10 Context)

  • Performance Optimization: রিমোট ভ্যালিডেশন সার্ভারে রিকোয়েস্ট পাঠায়, তাই এটি অন্যান্য ক্লায়েন্ট-সাইড ভ্যালিডেশনের মতো পারফরম্যান্স-ফ্রি নয়। ইমেইলের মতো ইউনিক ডেটা চেক করার জন্যই এটি সবচেয়ে বেশি উপযুক্ত।
  • Double Check on POST is MUST: রিমোট ভ্যালিডেশন শুধু ক্লায়েন্ট-সাইড ইউজার এক্সপেরিয়েন্স ভালো করে। হ্যাকাররা চাইলে জাভাস্ক্রিপ্ট অফ করে বা সরাসরি API কল করে ডুপ্লিকেট ইমেইল দিয়ে রেজিস্ট্রেশন করার চেষ্টা করতে পারে। তাই POST অ্যাকশনে (Register মেথড) _userManager.CreateAsync কল করার পর যে result.Succeeded চেক করা হয়, তা কোনোভাবেই রিমুভ করা যাবে না। রিমোট ভ্যালিডেশন এবং সার্ভার-সাইড ভ্যালিডেশন—দুটিই একসাথে থাকা বাধ্যতামূলক!
  • Smarter Controller Action (.NET 10): আধুনিক প্র্যাকটিসে মেথডটি আরও ক্লিন করে লেখা যায়:
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> IsEmailAlreadyRegistered(string email)
{
    // এক লাইনে রিটার্ন করা
    return Json(await _userManager.FindByEmailAsync(email) == null);
}
 

অসাধারণ! আপনার ফর্ম এখন আগের চেয়ে অনেক বেশি ইউজার-ফ্রেন্ডলি। পেজ রিলোডের বিরক্তি ছাড়াই ইউজার বুঝতে পারবে তার ইমেইলটি সঠিক কিনা। পরবর্তী লেকচারে আমরা Conventional Routing নিয়ে আলোচনা করবো!