C# Academy · درس

Middleware وFilters في Minimal APIs

أضيفوا المصادقة والتفويض ومعالجة الاستثناءات ومرشحات نقاط النهاية إلى مسارات Minimal API.

الدرس 3 من 413 خطوة

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

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

يحتوي ASP.NET Core على طبقتين للتوسعة: الوسيطات (تغلف مسار التنفيذ بأكمله وتعمل مع كل طلب) ومرشحات نقاط النهاية (تعمل فقط مع نقاط نهاية محددة). ويعمل كلاهما في Minimal APIs.

إضافة الوسيطات إلى Minimal APIs

تُضاف وسيطات ASP.NET Core القياسية باستخدام أساليب app.Use*. ويكتسب الترتيب أهمية، إذ تُشغَّل الوسيطات بالترتيب الذي سُجّلت به.

var app = builder.Build();

app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.UseRateLimiter();

app.MapGet("/secure", () => "Protected endpoint")
   .RequireAuthorization();

app.Run();

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

تشبه مرشحات نقاط النهاية الوسيطات، لكنها محصورة في نقطة نهاية واحدة. استخدم AddEndpointFilter لإضافة مرشح مضمن. ويمكن للمرشحات إيقاف المعالجة مبكرًا بإرجاع نتيجة من دون استدعاء next.

app.MapGet("/guarded", () => "Secret data")
   .AddEndpointFilter(async (ctx, next) =>
   {
       var header = ctx.HttpContext.Request.Headers["X-Api-Key"];
       if (header != "my-secret-key")
           return Results.Unauthorized();

       return await next(ctx); // proceed to handler
   });

مرشحات نقاط النهاية المعتمدة على الفئات

نفّذ IEndpointFilter لإنشاء مرشحات قابلة لإعادة الاستخدام. ويمكن تطبيقها على نقاط نهاية فردية أو على مجموعات مسارات كاملة.

public class LoggingFilter : IEndpointFilter
{
    private readonly ILogger<LoggingFilter> _logger;
    public LoggingFilter(ILogger<LoggingFilter> logger) => _logger = logger;

    public async ValueTask<object?> InvokeAsync(
        EndpointFilterInvocationContext ctx,
        EndpointFilterDelegate next)
    {
        _logger.LogInformation("Before: {Path}", ctx.HttpContext.Request.Path);
        var result = await next(ctx);
        _logger.LogInformation("After: {Path}",  ctx.HttpContext.Request.Path);
        return result;
    }
}

// Apply to a group
app.MapGroup("/api").AddEndpointFilter<LoggingFilter>();

وسيط معالجة الاستثناءات

استخدم app.UseExceptionHandler أو وسيط ProblemDetails المضمّن لالتقاط الاستثناءات غير المعالجة وإرجاع استجابات المشكلات وفق RFC 7807.

builder.Services.AddProblemDetails();

var app = builder.Build();

app.UseExceptionHandler();
// OR for custom logic:
app.UseExceptionHandler(errApp =>
    errApp.Run(async ctx =>
    {
        var ex = ctx.Features.Get<IExceptionHandlerFeature>()?.Error;
        ctx.Response.StatusCode = 500;
        await ctx.Response.WriteAsJsonAsync(new { error = ex?.Message });
    }));

الوسيطات ذات الإيقاف المبكر

استخدم app.MapShortCircuit() (في .NET 8 وما بعده) أو Results.StatusCode() في مرشح لإرجاع استجابة فورًا من دون تشغيل مسار التنفيذ بأكمله.

// Block known bad bots at the edge
app.MapGet("/robots.txt", () => "User-agent: *\nDisallow: /")
   .ShortCircuit(); // .NET 8: returns response immediately

// Or in a filter:
app.MapGet("/maintenance", () => "OK")
   .AddEndpointFilter((ctx, next) =>
       ValueTask.FromResult<object?>(Results.StatusCode(503)));

تحديد معدل الطلبات في .NET 7 وما بعده

يحمي وسيط تحديد معدل الطلبات المضمّن نقاط النهاية من إساءة الاستخدام. طبّق السياسات على مستوى عام أو لكل نقطة نهاية باستخدام RequireRateLimiting().

using System.Threading.RateLimiting;

builder.Services.AddRateLimiter(opt =>
{
    opt.AddFixedWindowLimiter("fixed", o =>
    {
        o.PermitLimit     = 10;
        o.Window          = TimeSpan.FromSeconds(10);
        o.QueueLimit      = 0;
        o.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
    });
    opt.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
});

app.UseRateLimiter();
app.MapGet("/search", Search).RequireRateLimiting("fixed");

إعداد CORS

اضبط سياسات CORS في الخدمات وطبّقها على مستوى عام أو لكل نقطة نهاية للتحكم في الأصول التي يمكنها الوصول إلى API.

builder.Services.AddCors(opt =>
    opt.AddPolicy("AllowFrontend", policy =>
        policy.WithOrigins("https://myapp.com")
              .AllowAnyHeader()
              .AllowAnyMethod()));

app.UseCors("AllowFrontend");

// Or per endpoint:
app.MapGet("/public-data", () => "data")
   .RequireCors("AllowFrontend");

وسيط التخزين المؤقت للإخراج

تخزّن AddOutputCache الاستجابات مؤقتًا على الخادم. طبّقها على نقاط نهاية محددة لتقديم الاستجابات المخزنة مؤقتًا من دون الوصول إلى قاعدة البيانات مع كل طلب.

builder.Services.AddOutputCache();

app.UseOutputCache();

app.MapGet("/products", async (AppDbContext db) =>
    Results.Ok(await db.Products.AsNoTracking().ToListAsync()))
   .CacheOutput(p => p.Expire(TimeSpan.FromMinutes(5)));

ترتيب المرشحات وتسلسلها

تُنفّذ المرشحات بالترتيب الذي أُضيفت به (الأكثر خارجية أولًا والأكثر داخلية أخيرًا، مثل الوسيطات). ويمكنك تسلسل عدة مرشحات على نقطة النهاية أو المجموعة نفسها.

app.MapPost("/orders", CreateOrder)
   .AddEndpointFilter<LoggingFilter>()      // runs first
   .AddEndpointFilter<ValidationFilter>()   // runs second
   .AddEndpointFilter<AuthFilter>()         // runs third
   .RequireAuthorization();                 // JWT checked by middleware

من الواقع العملي: وسيط مفتاح API

وسيط مفتاح API قابل لإعادة الاستخدام، يقرأ المفتاح من ترويسة ويوقف المعالجة مبكرًا مع إرجاع 401 إذا كان المفتاح غير صالح.

public class ApiKeyMiddleware
{
    private readonly RequestDelegate _next;
    private readonly string _expectedKey;

    public ApiKeyMiddleware(RequestDelegate next, IConfiguration cfg)
    {
        _next = next;
        _expectedKey = cfg["ApiKey"] ?? throw new Exception("ApiKey not configured");
    }

    public async Task InvokeAsync(HttpContext ctx)
    {
        if (!ctx.Request.Headers.TryGetValue("X-Api-Key", out var key)
            || key != _expectedKey)
        {
            ctx.Response.StatusCode = 401;
            await ctx.Response.WriteAsync("Invalid API key");
            return;
        }
        await _next(ctx);
    }
}

app.UseMiddleware<ApiKeyMiddleware>();

اختبار سريع

ما الفرق الأساسي بين الوسيطات ومرشحات نقاط النهاية في Minimal APIs؟

مراجعة: الوسيطات والمرشحات

أهم النقاط:

  • تعمل الوسيطات (UseX) على مستوى عام وبترتيب مسار التنفيذ مع كل طلب
  • تقتصر مرشحات نقاط النهاية (AddEndpointFilter) على نقاط نهاية أو مجموعات محددة
  • نفّذ IEndpointFilter لإنشاء فئات مرشحات قابلة لإعادة الاستخدام ومتوافقة مع DI
  • تشمل الوسيطات المضمّنة: تحديد معدل الطلبات وCORS والتخزين المؤقت للإخراج ومعالجة الاستثناءات
  • يهم ترتيب المرشحات، إذ تتداخل مثل الوسيطات (أول مرشح يُضاف يكون الأكثر خارجية)
البدء مجانًا

تعلم C# مع معلم ذكاء اصطناعي — مجانًا

اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.

الدورات
93
الدروس
346

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

هل درس «Middleware وFilters في Minimal APIs» مجاني؟

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

ماذا ستتعلم في «Middleware وFilters في Minimal APIs»؟

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

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

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

كم من الوقت يستغرق درس «Middleware وFilters في Minimal APIs»؟

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

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

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

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

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