0Pricing
C# Academy · บทเรียน

ภาพรวมสายงาน ASP.NET Core

ทำความเข้าใจว่าคำขอไหลผ่านสายงานมิดเดิลแวร์และ HttpContext อย่างไร รวมถึงวิธีประกอบการตอบกลับ

ภาพรวมสายงาน ASP.NET Core เป็นบทเรียน C# Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C# Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน

ไปป์ไลน์คำขอ

คำขอ HTTP ทุกคำขอใน ASP.NET Core จะไหลผ่าน ไปป์ไลน์มิดเดิลแวร์ มิดเดิลแวร์แต่ละส่วนสามารถตรวจสอบ แก้ไข หยุดการทำงานก่อนถึงส่วนถัดไป หรือส่งต่อคำขอไปยังองค์ประกอบถัดไปได้ การทำความเข้าใจไปป์ไลน์นี้เป็นพื้นฐานสำคัญในการสร้างแอป ASP.NET Core

HttpContext: ซองคำขอ

HttpContext บรรจุข้อมูลทุกอย่างเกี่ยวกับคำขอและการตอบกลับ ได้แก่ ส่วนหัว คุกกี้ เนื้อหา ข้อมูลการอ้างสิทธิ์ของผู้ใช้ ข้อมูลการเชื่อมต่อ และโทเคนยกเลิก มิดเดิลแวร์ทั้งหมดทำงานกับข้อมูลนี้

app.Use(async (context, next) =>
{
    // Read request info
    var method  = context.Request.Method;
    var path    = context.Request.Path;
    var headers = context.Request.Headers;
    var user    = context.User.Identity?.Name;

    // Write to response
    context.Response.Headers.Append("X-Processed-By", "MyMiddleware");

    await next(context); // forward to next middleware
});

ลำดับการลงทะเบียนมิดเดิลแวร์

มิดเดิลแวร์จะทำงานตามลำดับที่ลงทะเบียนไว้ ส่วนการตอบกลับจะคลายย้อนกลับตามลำดับตรงข้าม เช่นเดียวกับกองซ้อน ลำดับมีความสำคัญอย่างยิ่ง: การยืนยันตัวตนต้องทำงานก่อนการอนุญาตสิทธิ์ และการกำหนดเส้นทางต้องทำงานก่อนการจับคู่จุดปลายทาง

// Typical order for an ASP.NET Core app:
app.UseExceptionHandler("/error"); // outermost — catches everything
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors("policy");
app.UseAuthentication();  // must be before Authorization
app.UseAuthorization();
app.UseRateLimiter();
app.UseOutputCache();
// MapHub, MapControllers, MapGet etc.
app.Run();

Use, Run และ Map

มีเมธอดสามแบบสำหรับเพิ่มมิดเดิลแวร์: Use (เรียกส่วนถัดไป), Run (สิ้นสุดและไม่เรียกส่วนถัดไป) และ Map (แยกแขนงตามเส้นทาง)

// Use: passes to next
app.Use(async (ctx, next) =>
{
    Console.WriteLine("Before");
    await next(ctx);
    Console.WriteLine("After");
});

// Run: terminal — no next
app.Run(async ctx =>
    await ctx.Response.WriteAsync("Terminal"));

// Map: branch on path prefix
app.Map("/api", apiApp =>
    apiApp.Run(async ctx =>
        await ctx.Response.WriteAsync("API branch")));

เนื้อหาคำขอและการตอบกลับ

เนื้อหาคำขอและการตอบกลับเป็นสตรีม การอ่านเนื้อหาคำขอทำได้เพียงครั้งเดียว หากต้องการอ่านหลายครั้ง เช่น ในมิดเดิลแวร์หลายส่วน ให้เปิดใช้งานการบัฟเฟอร์เนื้อหาคำขอ

app.Use(async (ctx, next) =>
{
    // Enable buffering so body can be read multiple times
    ctx.Request.EnableBuffering();

    using var reader = new StreamReader(
        ctx.Request.Body,
        leaveOpen: true);
    var body = await reader.ReadToEndAsync();
    ctx.Request.Body.Position = 0; // rewind for next middleware

    Console.WriteLine($"Body: {body}");
    await next(ctx);
});

การหยุดไปป์ไลน์ก่อนถึงส่วนถัดไป

มิดเดิลแวร์สามารถหยุดไปป์ไลน์ก่อนถึงส่วนถัดไปได้ด้วยการเขียนการตอบกลับและไม่เรียกใช้ next วิธีนี้มีประโยชน์สำหรับด่านการยืนยันตัวตน การตรวจสอบสุขภาพ หรือหน้าโหมดบำรุงรักษา

app.Use(async (ctx, next) =>
{
    if (ctx.Request.Path == "/maintenance")
    {
        ctx.Response.StatusCode = 503;
        await ctx.Response.WriteAsync("Service under maintenance");
        return; // short-circuit — next is NOT called
    }
    await next(ctx);
});

อินเทอร์เฟซ IMiddleware

สำหรับมิดเดิลแวร์แบบคลาสที่ต้องใช้ DI ให้ใช้อินเทอร์เฟซ IMiddleware ลงทะเบียนการใช้งานใน DI แล้วใช้ app.UseMiddleware<T>()

public class RequestTimingMiddleware : IMiddleware
{
    private readonly ILogger<RequestTimingMiddleware> _logger;
    public RequestTimingMiddleware(ILogger<RequestTimingMiddleware> l) => _logger = l;

    public async Task InvokeAsync(HttpContext ctx, RequestDelegate next)
    {
        var sw = System.Diagnostics.Stopwatch.StartNew();
        await next(ctx);
        _logger.LogInformation("{Method} {Path}: {Ms}ms",
            ctx.Request.Method, ctx.Request.Path, sw.ElapsedMilliseconds);
    }
}

// Register:
builder.Services.AddTransient<RequestTimingMiddleware>();
app.UseMiddleware<RequestTimingMiddleware>();

คลาสมิดเดิลแวร์ตามแบบแผน

อีกทางเลือกหนึ่งคือสร้างคลาสที่มีเมธอด InvokeAsync(HttpContext, RequestDelegate) เฟรมเวิร์กจะฉีดการพึ่งพา รวมถึงผู้รับมอบหมายถัดไป ผ่านตัวสร้าง

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

    // RequestDelegate injected by framework
    public ApiKeyMiddleware(RequestDelegate next, IConfiguration cfg)
    {
        _next = next;
        _key = cfg["ApiKey"] ?? "";
    }

    public async Task InvokeAsync(HttpContext ctx)
    {
        if (ctx.Request.Headers["X-Api-Key"] != _key)
        {
            ctx.Response.StatusCode = 401;
            return;
        }
        await _next(ctx);
    }
}

การแก้ไขการตอบกลับหลังจากส่วนถัดไป

โค้ดหลังจาก await next(ctx) จะทำงานหลังจากเริ่มเขียนการตอบกลับแล้ว คุณสามารถเพิ่มส่วนหัวการตอบกลับก่อนเรียก next ได้ แต่ไม่สามารถแก้ไขรหัสสถานะหรือเนื้อหาได้หลังจากนั้น

app.Use(async (ctx, next) =>
{
    // Before: add response headers (safe)
    ctx.Response.OnStarting(() =>
    {
        ctx.Response.Headers.Append("X-Request-Id",
            Guid.NewGuid().ToString("N"));
        return Task.CompletedTask;
    });

    await next(ctx);

    // After: response may already be sent
    // SAFE: logging, metrics
    // UNSAFE: changing status code or writing body
    Console.WriteLine($"Response status: {ctx.Response.StatusCode}");
});

กรณีใช้งานจริง: มิดเดิลแวร์รหัสความสัมพันธ์

มิดเดิลแวร์รหัสความสัมพันธ์ในระบบจริงจะเพิ่ม ID สำหรับการติดตามให้กับทุกคำขอ เพื่อใช้ในการติดตามการทำงานแบบกระจายและการบันทึก

public class CorrelationIdMiddleware
{
    private readonly RequestDelegate _next;
    private const string Header = "X-Correlation-Id";

    public CorrelationIdMiddleware(RequestDelegate next) => _next = next;

    public async Task InvokeAsync(HttpContext ctx)
    {
        var correlationId = ctx.Request.Headers[Header].FirstOrDefault()
            ?? Guid.NewGuid().ToString("N");

        ctx.Items["CorrelationId"] = correlationId;

        ctx.Response.OnStarting(() =>
        {
            ctx.Response.Headers.Append(Header, correlationId);
            return Task.CompletedTask;
        });

        using (Serilog.Context.LogContext.PushProperty("CorrelationId", correlationId))
            await _next(ctx);
    }
}

ตรวจสอบความเข้าใจ

เมื่อเพิ่มมิดเดิลแวร์ app.Use() และ app.Run() แตกต่างกันอย่างไร

สรุป: ภาพรวมไปป์ไลน์ ASP.NET Core

ประเด็นสำคัญ:

  • มิดเดิลแวร์ทำงานตามลำดับการลงทะเบียน ส่วนการตอบกลับจะย้อนกลับตามลำดับตรงข้าม
  • Use → เรียกส่วนถัดไป; Run → สิ้นสุด; Map → แยกแขนงตามเส้นทาง
  • HttpContext มีคำขอ การตอบกลับ ผู้ใช้ และโทเคนยกเลิก
  • เปิดใช้งานการบัฟเฟอร์เพื่ออ่านเนื้อหาคำขอหลายครั้ง
  • อินเทอร์เฟซ IMiddleware ช่วยให้มิดเดิลแวร์แบบคลาสทำงานร่วมกับ DI ได้สะดวก
  • เพิ่มส่วนหัวการตอบกลับผ่าน OnStarting(); อย่าเปลี่ยนสถานะหลังจากเรียกส่วนถัดไป

คำถามที่พบบ่อย

บทเรียน “ภาพรวมสายงาน ASP.NET Core” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ภาพรวมสายงาน ASP.NET Core” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C# Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ภาพรวมสายงาน ASP.NET Core”

ทำความเข้าใจว่าคำขอไหลผ่านสายงานมิดเดิลแวร์และ HttpContext อย่างไร รวมถึงวิธีประกอบการตอบกลับ คุณปฏิบัติ C# Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C# Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C# Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “ภาพรวมสายงาน ASP.NET Core” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C# Academy นี้ได้ไหม

ได้ บทเรียน C# Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. ภาพรวมสายงาน ASP.NET Core
  2. การเขียนมิดเดิลแวร์แบบกำหนดเอง
  3. การตัดการทำงานระยะสั้นและการแตกแขนง
  4. ลำดับมิดเดิลแวร์และมิดเดิลแวร์ในตัว
← กลับไปที่ C# Academy