ASP.NET Core / المتوسط: البيانات والهوية والعمل غير المتزامن / الدرس 8
التحقق من المدخلات وتفاصيل المشكلات
صنّف أخطاء الصياغة والبنية والمجال والتعارض والفشل غير المتوقع، مع إعادة عقود أخطاء ثابتة لا تكشف أسرارا.
في هذه الصفحة
أهداف الدرس
- تحقق من كائنات نقل بيانات الطلب قبل تنفيذ الآثار.
- ميّز إعداد التحقق في MVC عن إعداده في Minimal API.
- صف الأخطاء المنظمة دون كشف تفاصيل التنفيذ الداخلية.
ليست كل أخطاء العميل من النوع نفسه
JSON مشوهة، ومدخل مطلوب غائب، وكمية خارج المدى، وعملية غير مصرح بها، وتعارض تزامن: كلها إخفاقات مختلفة. حدد الطبقة التي تكتشف كل منها، وعقد الحالة والجسم الذي تعيده. قد تعبّر سمة من DataAnnotations عن قاعدة لحقل، لكنها لا تثبت وحدها الملكية الحالية، أو التفرد في قاعدة البيانات، أو قيدا يجب أن تحافظ عليه المعاملة.
تحقق قبل تثبيت الآثار، واحتفظ بالحالة الصحيحة السابقة عند الرفض حيث تعد الواجهة بذلك. تجنب استخدام الاستثناءات لكل قيمة غير صالحة عادية عندما تلائمها نتيجة واضحة. لا تحوّل كل إخفاق إلى 400؛ فقد يخفي ذلك عيوب الخادم ويضلل العملاء إلى إعادة المحاولة أو تعديل المدخل دون حاجة.
اختبر قاعدة واحدة لكائن نقل البيانات بصورة مستقلة
يستدعي البرنامج الأول تحقق DataAnnotations مباشرة على كائن DTO اصطناعي. يرفض كمية تساوي 0 تحت قاعدة من 1 إلى 10، ويحصي خطأ تحقق واحدا. لا يثبت ذلك أن MVC أو خط أنابيب Minimal API استدعى القاعدة لطلب عام. اختبار القاعدة واختبار تكامل الإطار دليلان متكاملان.
اختر سمات الحقول والقواعد المشتركة بينها عن قصد. تعبّر توصيفات الأنواع المرجعية القابلة للقيمة الفارغة عن نية على مستوى التحليل الثابت؛ وقد يحتاج اشتراط الوجود إلى قاعدة وقت تشغيل أو نموذج يميز وجود الحقل. يمكن أن يتحول حقل عددي غائب إلى صفر عند فك التسلسل، لذا قد يلزم تمثيلان مختلفان للصفر والغياب إذا اختلف معناهما.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
var input = new OrderInput { Quantity = 0 };
var errors = new List<ValidationResult>();
bool valid = Validator.TryValidateObject(input, new ValidationContext(input), errors, validateAllProperties: true);
Console.WriteLine($"valid={valid} errors={errors.Count}");
internal sealed class OrderInput
{
[Range(1, 10)] public int Quantity { get; set; }
}
valid=False errors=1
ترفض قاعدة الحقل القيمة 0 وتنتج خطأ واحدا؛ ولا يُنفّذ ربط HTTP أو مسار 400 تلقائي.
يتوقف السلوك التلقائي على إعداد التطبيق
يمكن لاتفاقيات ApiController رفض ModelState غير الصالحة قبل تنفيذ إجراء المتحكم. أما تحقق Minimal API في .NET 10 فله إعداد تفعيل صريح وخط أنابيب خاص بالمرشحات والتحقق. لا تنقل سلوك أحدهما إلى الآخر لمجرد استخدام كائن DTO في كليهما؛ فالوثائق المحددة بالإصدار والتسجيل الفعلي هما ما يحددان ما يعمل.
تعمل مرشحات نقاط النهاية ومرشحات الإجراءات والبرمجيات الوسيطة ومحققات التطبيق عند حدود مختلفة. لا يستدعيها تلقائيا استدعاء خدمة أو إجراء مباشرة. اجعل تكرار التحقق مقصودا بدلا من نسخ قواعد غير متسقة في كل طبقة. ينبغي لاختبارات التكامل إثبات شكل الرفض العام، وعدم وقوع أثر غير مقصود.
كائن الخطأ المنظم عقد يمكن فحصه
يمكن أن تحمل ProblemDetails وValidationProblemDetails حقول أخطاء معيارية ومعلومات على مستوى الحقل. ينشئ البرنامج الثاني تفاصيل تحقق ويفحص الحالة ومفاتيح الأخطاء دون تنفيذ نتيجة HTTP. على الواجهة الفعلية تهيئة مسار كتابة الخطأ، والحفاظ على مخطط عام ثابت عبر الإخفاقات المتوقعة.
استخدم معرف تتبع أو ارتباط آمنا لربط الإخفاق العام بتشخيص داخلي مضبوط. لا تضع مكدسات الاستدعاء أو الرموز أو سلاسل الاتصال أو SQL الخام في التفاصيل. يمكن أن يظل العنوان العام ثابتا بينما تحتفظ السجلات الداخلية بالسبب والسياق المفيدين. افصل الترجمة اللغوية عن الفئات المقروءة آليا عندما يتفرع سلوك العملاء بحسب الخطأ.
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
var problem = new ValidationProblemDetails(new Dictionary<string, string[]>
{
["quantity"] = new[] { "must be between 1 and 10" }
}) { Status = 400, Title = "Invalid order input" };
Console.WriteLine($"status={problem.Status} fields={problem.Errors.Count} title={problem.Title}");
status=400 fields=1 title=Invalid order input
يحمل الكائن الحالة 400 وخطأ حقل واحدا؛ ولا يُختبر التفاوض على تمثيل الاستجابة أو تسلسلها.
تحقق من الاستجابة ومن الأثر المرفوض معا
ينبغي لاختبار التحقق فحص الحالة والجسم، وفئة الخطأ، وأسماء الحقول المعنية، وبقاء الحالة المثبتة دون تغيير. أدرج الغياب وnull والصياغة المشوهة والحدود والحجم الزائد والعلاقات بين الحقول والمنع والتعارض حيث يلائم ذلك. لا تصلح استجابة 200 تحمل نص خطأ، أو استجابة 500 تكشف الداخل، بمجرد تغيير الرسالة الظاهرة.
أبق ترجمة الأخطاء لدى مالك الحد المعني، وتجنب تكرار التسجيل، واحفظ دلالات الإلغاء. يحتاج الفشل غير المتوقع إلى تشخيص مضبوط واستجابة صادقة لفشل الخادم عندما يمكن ذلك؛ وتحتاج التعارضات المتوقعة إلى سياسة تسوية موثقة. تفيد فحوص الكائنات المحلية، لكنها لا تتحقق من خط معالجة الأخطاء كاملا.
الأخطاء الشائعة وإصلاحها
يُفترض فرض حقل مطلوب بترميز القابلية للقيمة الفارغة وحده.
- لماذا يحدث؟
- اختلطت التوصيفات الثابتة بالتحقق من وجود المدخل وقت التشغيل.
- كيف تصلحه؟
- حدد قاعدة الحد الفعلية واختبرها.
- كيف تتجنب تكراره؟
- اختبر المدخل الغائب وnull الصريحة كلّا على حدة.
يتحول كل استثناء إلى 400.
- لماذا يحدث؟
- تُصنّف إخفاقات الخادم غير المتوقعة خطأ على أنها أخطاء عميل.
- كيف تصلحه؟
- حوّل الفئات الموثقة إلى استجابات عند الحد الصحيح.
- كيف تتجنب تكراره؟
- اختبر الفشل الداخلي والإلغاء بصورة منفصلة.
تكشف تفاصيل المشكلة SQL داخلية أو أسرارا.
- لماذا يحدث؟
- يعبر سياق التشخيص حد الثقة العام.
- كيف تصلحه؟
- أعد فئات ومعرفات تتبع آمنة، واحتفظ بسجلات مقيدة الوصول.
- كيف تتجنب تكراره؟
- راجع تسلسل مسارات الخطأ.
اختبر فهمك
1. لماذا ينبغي لنموذج الطلب التمييز بين كمية غائبة وصفر صريح عندما يعامل المجال الحالتين بصورة مختلفة؟
اعرض الحل المشروح
قد تحمل خاصية int بسيطة صفرا بعد فك تسلسل حقل غائب، فتضيع معلومة الوجود. استخدم نموذجا مناسبا قابلا للقيمة الفارغة أو مدركا لوجود الحقل، أو عقدا صريحا للأعضاء المطلوبة وربط المدخلات، ثم تحقق من الصفر بقاعدة مجاله. اختبر الغياب وnull والصفر والقيم الصحيحة عبر مسار التكامل العام. لا تستنتج من نجاح إنشاء الكائن أن العميل قدّم كل قيمة مطلوبة.
2. ما الذي يجب فحصه إلى جانب الحالة 400 في اختبار التحقق؟
اعرض الحل المشروح
تحقق من مخطط الخطأ وفئته الثابتين، وأخطاء الحقول المقصودة، وأمان ما يكشفه التشخيص، وعدم تثبيت العملية المرفوضة حالة غير مقصودة. مرر الحالة نفسها عبر خط الربط أو المرشحات المعني، لأن استدعاءات Validator المباشرة تختبر قاعدة فقط. قد يفوت التحقق من الحالة وحدها سببا خاطئا، أو تفاصيل مكشوفة، أو أثرا نُفّذ قبل الرفض.
أهم ما تعلمته
- تحتاج أخطاء التمثيل والمجال والصلاحية والتعارض وفشل الخادم إلى معالجة متميزة.
- يحتاج التحقق التلقائي إلى إعداد الإطار الصحيح.
- يجب أن تبقى الأخطاء المنظمة مفيدة وثابتة ولا تكشف أسرارا.