0Pricing
C# Academy · درس

مجموعات المسارات والمعلمات والتحقق

نظّموا نقاط النهاية باستخدام MapGroup، واربطوا معلمات المسار والاستعلام والنص، وتحقّقوا من صحتها باستخدام سمات البيانات.

مجموعات المسارات والمعلمات والتحقق درس مجاني في C# Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C# Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C# Academy 4 دروس في المجموع.

مجموعات المسارات للتنظيم

تتيح لك MapGroup() (التي قُدّمت في .NET 7) تجميع نقاط النهاية ذات الصلة تحت بادئة مشتركة وتطبيق إعدادات مشتركة — مثل الوسيطات وسياسات المصادقة والعلامات — من دون تكرارها في كل نقطة نهاية.

إنشاء مجموعة مسارات

استدعِ app.MapGroup("/api/products")، ثم عرّف نقاط النهاية على المجموعة المعادة. تُضاف البادئة تلقائيًا إلى جميع المسارات.

var products = app.MapGroup("/api/products").WithTags("Products");

products.MapGet("/",     GetAll);
products.MapGet("/{id}", GetById);
products.MapPost("/",    Create);
products.MapPut("/{id}", Update);
products.MapDelete("/{id}", Delete);
// Routes: /api/products, /api/products/{id}

تطبيق المصادقة على مجموعة

استخدم RequireAuthorization() على المجموعة لحماية جميع نقاط النهاية دفعةً واحدة. ولا يزال بإمكان نقاط النهاية الفردية تجاوز ذلك باستخدام AllowAnonymous().

var adminGroup = app.MapGroup("/admin")
    .RequireAuthorization("AdminPolicy")
    .WithTags("Admin");

adminGroup.MapGet("/users",    GetAllUsers);
adminGroup.MapDelete("/users/{id}", DeleteUser);

// This one inside the group opts out
adminGroup.MapGet("/status", () => "OK").AllowAnonymous();

قيود معاملات المسار

قيّد معاملات المسار باستخدام أنماط الأنواع. يرفض موجّه المسارات الطلبات التي لا تطابق هذه الأنماط، ويعيد 404 تلقائيًا.

// Only matches numeric IDs
app.MapGet("/products/{id:int}", (int id) => id);

// GUID constraint
app.MapGet("/orders/{orderId:guid}", (Guid orderId) => orderId);

// Length constraint
app.MapGet("/codes/{code:length(6)}", (string code) => code);

// Min value
app.MapGet("/page/{page:min(1)}", (int page) => page);

الربط من مصادر مختلفة

تُربط المعاملات من مصادر مختلفة باستخدام السمات. وبصفة افتراضية، تأتي الأنواع البسيطة من المسار أو الاستعلام، بينما تأتي الأنواع المعقدة من الجسم.

app.MapPost("/search", (
    [FromQuery] string q,
    [FromQuery] int page,
    [FromHeader(Name = "X-Api-Version")] string version,
    [FromBody] SearchFilters filters,
    AppDbContext db) =>
{
    // q and page from query string
    // version from request header
    // filters from JSON body
    return Results.Ok();
});

ربط مخصص للمعاملات باستخدام TryParse

بالنسبة إلى الأنواع المخصصة المستخدمة كمعاملات للمسار أو الاستعلام، نفّذ أسلوبًا static باسم TryParse. يستدعيه الإطار تلقائيًا لتحليل قيمة السلسلة النصية.

public record ProductFilter(string? Category, decimal? MinPrice)
{
    public static bool TryParse(string value, out ProductFilter result)
    {
        var parts = value.Split(':');
        result = new ProductFilter(
            parts.Length > 0 ? parts[0] : null,
            parts.Length > 1 && decimal.TryParse(parts[1], out var p) ? p : null);
        return true;
    }
}

// Usage: GET /products?filter=Electronics:50
app.MapGet("/products", ([FromQuery] ProductFilter filter) => filter);

التحقق من صحة البيانات باستخدام Data Annotations

أضف سمات Data Annotations إلى DTOs الخاصة بالطلبات. في Minimal APIs، استخدم الواجهة IValidatableObject أو مرشح تحقق لتشغيل عملية التحقق.

using System.ComponentModel.DataAnnotations;

record CreateProductRequest
{
    [Required, MaxLength(200)]
    public string Name { get; init; } = "";

    [Range(0.01, 999999)]
    public decimal Price { get; init; }

    [Range(0, int.MaxValue)]
    public int Stock { get; init; }
}

مرشحات نقاط النهاية للتحقق

تعمل مرشحات نقاط النهاية قبل المعالج أو بعده. استخدمها لإضافة التحقق من صحة النموذج، ورفض الطلبات غير الصالحة قبل وصولها إلى منطق الأعمال.

app.MapPost("/products", CreateProduct)
   .AddEndpointFilter(async (ctx, next) =>
   {
       var req = ctx.GetArgument<CreateProductRequest>(0);
       var errors = new List<ValidationResult>();
       if (!Validator.TryValidateObject(req,
               new ValidationContext(req), errors, true))
       {
           return Results.ValidationProblem(
               errors.ToDictionary(e => e.MemberNames.First(),
                                   e => new[] { e.ErrorMessage! }));
       }
       return await next(ctx);
   });

التكامل مع FluentValidation

لقواعد التحقق المعقدة، استخدم FluentValidation مع الحزمة SharpGrip.FluentValidation.AutoValidation.Endpoints لإجراء التحقق تلقائيًا في Minimal APIs.

public class CreateProductValidator : AbstractValidator<CreateProductRequest>
{
    public CreateProductValidator()
    {
        RuleFor(x => x.Name).NotEmpty().MaximumLength(200);
        RuleFor(x => x.Price).GreaterThan(0);
        RuleFor(x => x.Stock).GreaterThanOrEqualTo(0);
    }
}

builder.Services.AddFluentValidationAutoValidation();
builder.Services.AddValidatorsFromAssemblyContaining<CreateProductValidator>();

مجموعات المسارات المتداخلة

يمكن تداخل مجموعات المسارات لنمذجة الموارد الهرمية، مثل الطلبات التي تحتوي على عناصر تفصيلية.

var api = app.MapGroup("/api").RequireAuthorization();

var orders = api.MapGroup("/orders");
orders.MapGet("/", GetAllOrders);
orders.MapGet("/{id:int}", GetOrder);

// Nested: /api/orders/{orderId}/lines
var lines = orders.MapGroup("/{orderId:int}/lines");
lines.MapGet("/",        GetOrderLines);
lines.MapPost("/",       AddOrderLine);
lines.MapDelete("/{id}", RemoveOrderLine);

من الواقع العملي: مجموعة API بإصدارات

جمّع نقاط النهاية حسب إصدار API لدعم الإصدارات المتجاورة من دون تكرار إعدادات المصادقة أو العلامات.

var v1 = app.MapGroup("/api/v1")
    .RequireAuthorization()
    .WithTags("v1");

var v2 = app.MapGroup("/api/v2")
    .RequireAuthorization()
    .WithTags("v2");

v1.MapGet("/products", GetProductsV1);
v2.MapGet("/products", GetProductsV2); // richer response

اختبار سريع

ما الغرض من MapGroup() في Minimal APIs؟

مراجعة: مجموعات المسارات والمعاملات والتحقق

أهم النقاط:

  • MapGroup(): مشاركة البادئة والإعدادات بين عدة نقاط نهاية
  • تؤدي قيود المسارات (:int و:guid و:min) إلى رفض المسارات غير المطابقة تلقائيًا
  • استخدم [FromQuery] و[FromHeader] و[FromBody] لتحديد مصدر الربط صراحةً
  • نفّذ TryParse على الأنواع المخصصة لتمكين الربط التلقائي من المسار أو الاستعلام
  • تتيح مرشحات نقاط النهاية معالجة الاهتمامات المشتركة مثل التحقق

الأسئلة الشائعة

هل درس «مجموعات المسارات والمعلمات والتحقق» مجاني؟

نعم — نص درس «مجموعات المسارات والمعلمات والتحقق» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C# Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C# Academy 4 دروس في المجموع.

ماذا ستتعلم في «مجموعات المسارات والمعلمات والتحقق»؟

نظّموا نقاط النهاية باستخدام MapGroup، واربطوا معلمات المسار والاستعلام والنص، وتحقّقوا من صحتها باستخدام سمات البيانات. تتمرن على C# Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ C# Academy؟

لا تُشترط خبرة سابقة. C# Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «مجموعات المسارات والمعلمات والتحقق»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس C# Academy هذا؟

نعم. كل درس في C# Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. إنشاء أول Minimal API لكم
  2. مجموعات المسارات والمعلمات والتحقق
  3. Middleware وFilters في Minimal APIs
  4. OpenAPI وإصدار الواجهات والنشر
← العودة إلى C# Academy