في هذه المقالة سوف نقوم بشرح توابع Details و Delete المولدة تلقائياً، حيث تختص هذه التوابع في إنشاء صفحة خاصة لعرض تفاصيل السجل من قاعدة البيانات، وحذف سجل من قاعدة بيانات عن طريق إنشاء صفحة لتأكيد قرار الحذف.
هذه المقالة جزء من سلسلة لتعلم أساسيات ASP.NET MVC للمبتدئين:
- المقالة الأولى: أول موقع ويب لك باستخدام ASP.NET MVC
- المقالة الثانية: إضافة متحكمات Controllers لموقع ASP.NET MVC
- المقالة الثالثة: إضافة واجهة View لموقع ASP.NET MVC
- المقالة الرابعة: إضافة Model لموقع ASP.NET MVC
- المقالة الخامسة: إضافة Connection String والعمل مع قواعد البيانات LocalDB
- المقالة السادسة: الوصول إلى البيانات عن طريق المتحكم Controller
- المقالة السابعة: شرح وتجريب تابع التعديل Edit Method
- المقالة الثامنة: إضافة ميزة البحث إلى موقع ASP.NET MVC
- المقالة التاسعة: إضافة حقل جديد لقاعدة البيانات انطلاقاً من كود سي شارب Code First Method
- المقالة العاشرة: إضافة التحقق Validation إلى MVC Model وتطبيق مبدأ DRY
- المقالة الحادية عشر: اختبار وشرح توابع Details و Delete
للبدأ قم بفتح المتحكم Books وانتقل إلى التابع Details
public ActionResult Details(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Book book = db.Books.Find(id); if (book == null) { return HttpNotFound(); } return View(book); }
إن محرك MVC قام بتوليد هذا التابع ونلاحظ وجود تعليق قبل التابع يعرض طلب HTTP الذي يستدعي هذا التابع
وهذا الطلب هو GET حيث أن الرابط مؤلف من ثلاث أجزاء : المتحكم Books والتابع Details وقيمة البارمتر Id
إن تقنية Code First تجعل من السهل البحث عن البيانات باستخدام التابع Find
حيث أن هناك ميزة حماية مهمة في تابع Details وهي أنه يتم التحقق من أن التابع Find قد وجد الكتاب قبل تنفيذ أي شيء آخر في الكود
على سبيل المثال قد يقوم الهاكر بعمل أخطاء في الموقع من خلال تغيير الرابط من http://localhost:xxxx/Books/Details/1 إلى http://localhost:xxxx/Books/Details/12345
أو أي قيمة أخرى لا تمثل أي كتاب
فإذا لم نقم بعمل فحص لقيم null فإن ذلك سيؤدي إلى أخطاء في قاعدة البيانات
شرح توابع Delete و DeleteConfirmed
// GET: Books/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Book book = db.Books.Find(id);
if (book == null)
{
return HttpNotFound();
}
return View(book);
}
// POST: Books/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Book book = db.Books.Find(id);
db.Books.Remove(book);
db.SaveChanges();
return RedirectToAction("Index");
}
نلاحظ أن تابع HTTP Get Delete لايحذف الكتاب المحدد حيث أنه يعيد View تحتوي الكتاب حيث يمكن من خلالها استدعاء التابع HttpPost Delete من أجل حذف الكتاب
إن تنفيذ عملية الحذف أو الإضافة أو التعديل في طلب Get يؤدي إلى تغرة أمنية
للمزيد من المعلومات في الرابط التالي ASP.NET MVC Tip #46 — Don’t use Delete Links because they create Security Holes.
إن تابع HttpPost Delete يحذف الكتاب حيث أن هذا التابع له الأسم DeleteConfirmed
إن الشكل العام لتابعي الحذف هو كما يلي
// GET: Books/Delete/5 public ActionResult Delete(int? id) // POST: Books/Delete/5 [HttpPost, ActionName("Delete")] [ValidateAntiForgeryToken] public ActionResult DeleteConfirmed(int id)
لعمل تحميل زائد للتوابع فإن (common language runtime (CLR تفرض أن يكون للتوابع نفس الأسم ولكن مختلفة في البارمترات
ولكن هنا نحتاج لتابعي حذف (تابع GET و تابع POST ) وكلاهما لهما نفس البارمترات(بارمتر واحد من النوع int)
وللتغلب على هذه المشكلة يوجد حلين
الأول: إعطاء التوابع أسماء مختلفة وهذا ما قام به محرك MVC في المثال السابق ولكن هذا سيؤدي إلى مشكلة صغيرة
إن ASP.NET تقوم بتحويل أجزاء الرابط إلى التوابع من خلال الأسم وإذا قمنا بإعادة تسمية التابع فإن التوجيه سيكون غير قادر على إيجاد التابع والحل هو كمارأينا في المثال وهو إضافة الخاصية (“ActionName(“Delete إلى تابع DeleteConfirmed وهذا يؤدي إلى أن نظام التوجيه يقوم بالتحويل بشكل فعال حيث أن الرابط الذي يتضمن Delete/
من أجل طلب POST request سيستدعي التابع DeleteConfirmed
الحل الثاني: هو استخدام التوابع التي لها أسماء متماثلة حيث أن لائحة البارمترات تتغير من أجل تابع POST حيث يتم تضمين بارمتر غير مستخدم
على سبيل المثال بعض المطورين يضيفون بارمتر من النوع FormCollection الذي يمرر إلى تابع POST حيث أن هذا البارمتر لايتم استخدامه في التابع
public ActionResult Delete(FormCollection fcNotUsed,int id=0) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Book book = db.Books.Find(id); if (book == null) { return HttpNotFound(); } return View(book); }
الآن قمنا بإكمال تطبيق ASP.NET MVC الذي يخزن الكتب وأنواعها في قاعدة البيانات local DB
حيث أصبح بإمكاننا إضافة وحذف وتعديل و البحث عن الكتب
تغذية راجعة
اتمنى عدم التردد في الاستفسار عن أي مفهوم تم ذكره في هذا التدوينة، وأرجو تجربة ماورد في التدوينة بشكل فعلي وعدم الاكتفاء بالقراءة لتحقيق أكبر فائدة ممكنة، وكالعادة سأكون سعيد إن شاركتموني تجربتكم وتصويباتكم في حال وجود أخطاء كتابية.
هذه المقالة مستندة إلى سلسلة دروس مايكروسوفت الرسمية للـ ASP.NET MVC، وذلك لترتيب الدروس المناسب واعتقادي بسلاستها وأهمية نقلها إلى العربية بأسلوب مناسب وتجربة تتوافق مع الأدوات المتاحة لنا والمتوفرة في منطقتنا.