0Pricing
C# Academy · درس

الإيقاف المبكر والتفرّع

استخدموا MapWhen وUseWhen وmiddleware النهائي لتفريع المسار أو إنهائه استنادًا إلى شروط الطلب.

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

التفرّع والإيقاف المبكر

لا ينبغي لكل طلب أن يجتاز مسار البرمجيات الوسيطة بالكامل. يوفر ASP.NET Core أدوات للتفرّع، أي توجيه مجموعات فرعية إلى مسارات مختلفة، وللإيقاف المبكر، أي إيقاف المعالجة وإعادة الاستجابة فورًا.

Map: تفرّع دائم حسب المسار

ينشئ Map تفرّعًا دائمًا؛ إذ تدخل الطلبات المطابقة للبادئة إلى الفرع ولا تعود مطلقًا إلى مسار التنفيذ الرئيسي.

app.Map("/api", apiApp =>
{
    apiApp.UseAuthentication();
    apiApp.UseAuthorization();
    apiApp.Run(async ctx =>
        await ctx.Response.WriteAsync("API branch"));
});

// Requests to /api/... enter the branch above.
// Requests to /public/... skip the branch entirely.
app.Run(async ctx =>
    await ctx.Response.WriteAsync("Main pipeline"));

MapWhen: التفرّع بناءً على دالة شرطية

يُجري MapWhen التفرّع بناءً على أي شرط، مثل الرؤوس أو معاملات الاستعلام أو منطق مخصّص. وكما هي الحال مع Map، يكون الفرع دائمًا ولا يعاود الانضمام إلى مسار التنفيذ الرئيسي.

// Branch when a specific header is present
app.MapWhen(
    ctx => ctx.Request.Headers.ContainsKey("X-Internal"),
    internalApp =>
    {
        internalApp.UseMiddleware<InternalApiMiddleware>();
        internalApp.Run(async ctx =>
            await ctx.Response.WriteAsync("Internal route"));
    });

// Branch on query parameter
app.MapWhen(
    ctx => ctx.Request.Query.ContainsKey("legacy"),
    legacyApp => legacyApp.UseMiddleware<LegacyHandlerMiddleware>());

UseWhen: تفرّع شرطي يعاود الانضمام

يشبه UseWhen ‏MapWhen، لكن الفرع يعاود الانضمام إلى مسار التنفيذ الرئيسي بعد اكتماله. ويتيح لك ذلك إضافة برمجية وسيطة بشكل شرطي من دون إنشاء مسار منفصل.

// Log only for authenticated API calls; public routes not logged
app.UseWhen(
    ctx => ctx.Request.Path.StartsWithSegments("/api")
           && ctx.User.Identity?.IsAuthenticated == true,
    loggedApp =>
    {
        loggedApp.UseMiddleware<AuditMiddleware>();
    });

// All requests continue here after the branch
app.UseRouting();
app.MapControllers();

الإيقاف المبكر بعدم استدعاء Next

يمكن لأي برمجية وسيطة إيقاف المسار مبكرًا من خلال كتابة الاستجابة وعدم استدعاء next. ويتوقف المسار عند تلك النقطة، ثم تُعاد الاستجابة إلى العميل.

app.Use(async (ctx, next) =>
{
    // IP allowlist check
    var ip = ctx.Connection.RemoteIpAddress?.ToString();
    var allowed = new[] { "127.0.0.1", "::1", "10.0.0.0/8" };

    if (!IsAllowed(ip, allowed))
    {
        ctx.Response.StatusCode = 403;
        await ctx.Response.WriteAsJsonAsync(
            new { error = "Access denied from this IP" });
        return; // short-circuit
    }

    await next(ctx); // proceed
});

ShortCircuit() في .NET 8

في .NET 8، يوفر كل من MapShortCircuit وامتداد ShortCircuit() لنقاط النهاية مسارًا تصريحيًا ومحسّنًا بدرجة كبيرة للإيقاف المبكر.

// Reject known bad paths immediately — skip entire pipeline
app.MapShortCircuit(404, "robots.txt", "favicon.ico");

// Or on a specific endpoint:
app.MapGet("/health", () => "OK")
   .ShortCircuit(); // skips auth, rate limiting, etc.

// 'Run' middleware also short-circuits:
app.Map("/old-api", old =>
    old.Run(ctx =>
    {
        ctx.Response.StatusCode = 301;
        ctx.Response.Headers.Location = "/api/v2";
        return Task.CompletedTask;
    }));

البرمجية الوسيطة النهائية مقابل توجيه نقاط النهاية

قبل .NET 3، كان app.Run() الخيار النهائي الوحيد. أما الآن، فيُفضَّل توجيه نقاط النهاية، مثل MapGet وMapControllers، لأنه يشارك في التخويل وتحديد معدل الطلبات والبيانات الوصفية.

// OLD: terminal middleware
app.Run(async ctx => {
    if (ctx.Request.Path == "/ping")
        await ctx.Response.WriteAsync("pong");
});

// PREFERRED: endpoint routing
app.MapGet("/ping", () => "pong")
   .WithTags("Health")
   .AllowAnonymous()
   .RequireRateLimiting("basic");

دقائق مطابقة المسارات

يطابق Map("/api") المسارَين /api و/api/anything. ويُزال المسار المطابق من Request.Path داخل الفرع، ويوضع في Request.PathBase.

app.Map("/api", apiApp =>
{
    apiApp.Use(async (ctx, next) =>
    {
        // Path in branch: /users/42 (prefix removed)
        Console.WriteLine(ctx.Request.Path);     // /users/42
        Console.WriteLine(ctx.Request.PathBase); // /api
        await next(ctx);
    });
    apiApp.MapGet("/users/{id}", (int id) => id);
});

دمج أنماط التفرّع

تجمع التطبيقات الواقعية بين Map وUseWhen والإيقاف المبكر لإنشاء مسارات متعددة الطبقات: تكون المسارات العامة خفيفة، وتحتوي مسارات API على المصادقة، بينما تتضمن مسارات الإدارة فحوصات إضافية.

// Public area — no auth
app.Map("/public", pub =>
{
    pub.MapGet("/health", () => "OK");
    pub.MapGet("/docs",   () => "Documentation");
});

// API area — full auth + rate limiting
app.Map("/api", api =>
{
    api.UseAuthentication();
    api.UseAuthorization();
    api.UseRateLimiter();
    api.MapControllers();
});

// Admin area — require admin role
app.Map("/admin", admin =>
{
    admin.UseAuthentication();
    admin.UseAuthorization();
    admin.MapControllers().RequireAuthorization("AdminPolicy");
});

من واقع عملي: برمجية وسيطة لاختبار A/B

تفرّع برمجية وسيطة لاختبار A/B الطلبات إلى معالجات مختلفة استنادًا إلى ملف تعريف ارتباط أو رأس، من دون تعديل شيفرة نقطة النهاية.

app.UseWhen(
    ctx => ctx.Request.Cookies.TryGetValue("ab-group", out var g) && g == "B",
    betaApp =>
    {
        betaApp.Use(async (ctx, next) =>
        {
            ctx.Items["IsGroupB"] = true;
            await next(ctx);
        });
    });

// Endpoint reads the flag:
app.MapGet("/products", (HttpContext ctx, ProductService svc) =>
{
    bool isB = ctx.Items.ContainsKey("IsGroupB");
    return isB ? svc.GetNewLayoutAsync() : svc.GetOldLayoutAsync();
});

تحقق سريع

ما الفرق الأساسي بين MapWhen وUseWhen؟

مراجعة: الإيقاف المبكر والتفرّع

أهم النقاط:

  • Map: تفرّع دائم يعتمد على المسار، ولا يعاود الانضمام
  • MapWhen: تفرّع دائم يعتمد على دالة شرطية
  • UseWhen: تفرّع شرطي يعاود الانضمام إلى مسار التنفيذ الرئيسي
  • الإيقاف المبكر: لا تستدعِ next، بل اكتب الاستجابة وأعدها
  • ShortCircuit() ‏(.NET 8): نقاط نهاية نهائية تصريحية ومحسّنة
  • ادمج التفرعات لبناء مسارات متعددة الطبقات: عامة / API / إدارية

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

هل درس «الإيقاف المبكر والتفرّع» مجاني؟

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

ماذا ستتعلم في «الإيقاف المبكر والتفرّع»؟

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

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

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

كم من الوقت يستغرق درس «الإيقاف المبكر والتفرّع»؟

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

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

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

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

  1. نظرة عامة على مسار ASP.NET Core
  2. كتابة Middleware مخصّص
  3. الإيقاف المبكر والتفرّع
  4. ترتيب Middleware وMiddleware المضمّن
← العودة إلى C# Academy