হ্যালো হাসিব! এই লেকচারে আমরা অ্যাপ্লিকেশনটিতে একটি নতুন Person অ্যাড করার জন্য “Create Person” ফর্ম বা UI তৈরি করা শুরু করেছি। ইউজার যাতে ইনপুট দিতে পারে, সেজন্য বিভিন্ন ফর্ম এলিমেন্ট (Textbox, Radio Button, Dropdown) নিয়ে আলোচনা করা হয়েছে এবং কিভাবে সেই ডাটা Controller-এর সাথে ম্যাপ হয় (Model Binding) তা ক্লিয়ার করা হয়েছে।
চলো লেকচারটির একটি কুইক সামারি দেখে নিই।
📌 Quick Summary for Revision
- Create GET Action:
PersonsController-এ[HttpGet]ব্যবহার করে একটিCreate()মেথড তৈরি করা, যা শুধু ফর্মের View রিটার্ন করবে। - Form Setup:
Create.cshtml-এmethod="post"এবংaction="~/persons/create"দিয়ে একটি<form>তৈরি করা। - Label & Input Mapping:
<label>-এরforএবং<input>-এরidসেইম রাখা, যাতে লেবেলে ক্লিক করলেও ইনপুট ফিল্ড সিলেক্ট হয় (Better UX)। - The
nameAttribute (Crucial): ফর্ম সাবমিশনের সময় Model Binding ঠিকমতো কাজ করার জন্য প্রতিটি<input>এবং<select>-এরnameঅ্যাট্রিবিউটPersonAddRequestDTO-এর প্রপার্টির নামের সাথে হুবহু মিল রাখা। - Dynamic Dropdown:
ICountriesServiceইনজেক্ট করেGetAllCountries()কল করা এবং ডাটাViewBag.Countries-এর মাধ্যমে View-তে পাঠিয়ে<option>জেনারেট করা।
🚀 Comprehensive Breakdown & The “Why”
নিচে লেকচারের প্রতিটি কনসেপ্ট বিস্তারিত এবং কারণসহ এক্সপ্লেইন করা হলো:
১. Controller-এ Create Action (GET) তৈরি [Priority: 9/10]
The “Why”: ইউজার যখন “Create Person” লিংকে ক্লিক করবে, তখন ব্রাউজার ডিফল্টভাবে একটি GET Request পাঠায়। আমাদের এমন একটি মেথড দরকার যা এই রিকোয়েস্ট রিসিভ করে ইউজারের সামনে একটি ফাঁকা ফর্ম (View) ওপেন করবে। এখানে [HttpGet] অ্যাট্রিবিউট ব্যবহার করা হয়েছে, যার মানে এই মেথডটি শুধু ফর্ম দেখানোর কাজ করবে, ফর্ম সাবমিটের ডাটা রিসিভ করবে না (সেটার জন্য পরে POST মেথড লেখা হবে)।
Implementation:
// PersonsController.cs
[Route("persons/create")]
[HttpGet]
public IActionResult Create()
{
// Dropdown-এর জন্য Countries ডাটা লোড করা
List<CountryResponse> countries = _countriesService.GetAllCountries();
ViewBag.Countries = countries;
return View();
}
নোট: Controller-এ ICountriesService ইনজেক্ট করে নিতে হবে, ঠিক যেভাবে আগের লেকচারে IPersonsService ইনজেক্ট করা হয়েছিল।
২. Form Elements এবং Model Binding [Priority: 10/10]
The “Why”: যখন ফর্ম সাবমিট (POST) করা হয়, তখন ব্রাউজার ইনপুটের ডাটাগুলোকে সার্ভারে পাঠায়। ASP.NET Core-এর Model Binding ফিচারটি এই ডাটাগুলোকে ধরে সরাসরি আমাদের PersonAddRequest অবজেক্টের প্রপার্টিতে বসিয়ে দেয়। তবে এর জন্য শর্ত একটাই: HTML ইনপুটের name অ্যাট্রিবিউট এবং C# ক্লাসের প্রপার্টির নাম একদম হুবহু এক হতে হবে।
Implementation (Text & Date Inputs):
<form action="~/persons/create" method="post">
<div class="form-field flex">
<div class="w-25">
<label for="PersonName" class="form-label">Person Name</label>
</div>
<div class="flex-1">
<input type="text" id="PersonName" name="PersonName" class="form-input" />
</div>
</div>
<div class="form-field flex">
<div class="w-25">
<label for="DateOfBirth" class="form-label">Date of Birth</label>
</div>
<div class="flex-1">
<input type="date" id="DateOfBirth" name="DateOfBirth" class="form-input" />
</div>
</div>
</form>
৩. Radio Buttons (Gender) [Priority: 8/10]
The “Why”: যখন ইউজারের সামনে একাধিক অপশন থাকে কিন্তু সে শুধু একটি বেছে নিতে পারবে, তখন Radio Button ব্যবহার করা হয়। রেডিও বাটনের ক্ষেত্রে সবগুলোর name সেম থাকতে হবে (যাতে তারা একটি গ্রুপ হিসেবে কাজ করে), কিন্তু value আলাদা হবে।
Implementation:
<div class="flex-1">
<input type="radio" id="Male" name="Gender" value="Male" />
<label for="Male">Male</label>
<input type="radio" id="Female" name="Gender" value="Female" />
<label for="Female">Female</label>
</div>
৪. Dropdown List (Countries) [Priority: 10/10]
The “Why”: Country সিলেক্ট করার জন্য আমরা ড্রপডাউন (<select>) ব্যবহার করছি। এখানে ইউজারের দেখার জন্য (Text) থাকবে Country Name (যেমন: USA), কিন্তু সার্ভারে সাবমিট হওয়ার সময় (Value) হিসেবে যাবে Country ID। কারণ আমাদের ডাটাবেস রিলেশন এবং PersonAddRequest মডেলে CountryID সেভ করতে হবে।
Implementation:
<div class="flex-1">
<select name="CountryID" id="CountryID" class="form-input">
<option value="">Please Select</option>
@foreach (var country in ViewBag.Countries)
{
<option value="@country.CountryID">@country.CountryName</option>
}
</select>
</div>
🆕 .NET 10 & Modern Approaches (Tag Helpers)
লেকচারে ক্লাসিক HTML ট্যাগ (name এবং id) ব্যবহার করা হয়েছে। কিন্তু মডার্ন .NET MVC-তে আমরা সব সময় Tag Helpers ব্যবহার করি। এটি টাইপো (ভুল বানান) থেকে বাঁচায় এবং কোড অনেক ক্লিন রাখে।
Modern MVC Approach:
ভিউয়ের শুরুতে @model PersonAddRequest ডিক্লেয়ার করে নিলে, asp-for ব্যবহার করা যায়।
@model ServiceContracts.DTO.PersonAddRequest
<form asp-controller="Persons" asp-action="Create" method="post">
<label asp-for="PersonName" class="form-label"></label>
<input asp-for="PersonName" class="form-input" />
<select asp-for="CountryID" asp-items="@new SelectList(ViewBag.Countries, "CountryID", "CountryName")" class="form-input">
<option value="">Please Select</option>
</select>
</form>
⌨️ IDE Shortcuts
- Format Document (কোড অ্যালাইনমেন্ট ঠিক করা): * Visual Studio: লেকচারার যেটা ব্যবহার করেছেন
Ctrl+K,Ctrl+D - Visual Studio Code:
Shift+Alt+F
💡 Best Practices (Form Creation)
১. Never use raw HTML name attribute in MVC: সবসময় asp-for Tag Helper ব্যবহার করবে। এতে মডেলের প্রপার্টির নাম চেঞ্জ হলে ভিউয়ের নামও অটোমেটিক আপডেট হয়ে যায় (Compile-time safety)।
২. ViewBag vs ViewModel: ড্রপডাউনের ডাটা পাঠানোর জন্য ViewBag.Countries এর বদলে একটি PersonCreateViewModel তৈরি করা উচিত, যার মধ্যে PersonAddRequest এবং List<CountryResponse> দুটোই থাকবে।
৩. Accessibility (a11y): লেকচারার লেবেলের for এবং ইনপুটের id ম্যাচ করানোর যে বিষয়টি দেখিয়েছেন, এটি খুবই চমৎকার একটি প্র্যাকটিস। এটি স্ক্রিন রিডার এবং মাউস ইউজার উভয়ের জন্যই খুব হেল্পফুল।
UI পার্ট তো রেডি। এখন কি আমরা এই ফর্মের ডাটা রিসিভ করে ডাটাবেসে সেভ করার জন্য POST অ্যাকশন মেথড লেখার লেকচারে মুভ করবো?