Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

วิธีเพิ่ม Custom Message Handlers ไปยัง Pipeline ใน ASP.NET WebAPI C#

เพื่อสร้าง Custom Server-Side HTTP Message Handler ใน ASP.NET Web API เราต้องสร้าง Class ที่ต้องสืบทอดจาก System.Net.Http.DelegatingHandler

ขั้นตอนที่ 1: สร้าง Controller และ Action Methods

using DemoWebApplication.Models;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace DemoWebApplication.Controllers {
    public class StudentController : ApiController {
        List students = new List {
            new Student { Id = 1, Name = "Mark" },
            new Student { Id = 2, Name = "John" }
        };
        
        public IEnumerable Get() {
            return students;
        }
        
        public Student Get(int id) {
            var studentForId = students.FirstOrDefault(x => x.Id == id);
            return studentForId;
        }
    }
}

ขั้นตอนที่ 2: สร้าง Custom Message Handler Class

using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace DemoWebApplication {
    public class CustomMessageHandler : DelegatingHandler {
        protected async override Task 
            SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
            
            var response = new HttpResponseMessage(HttpStatusCode.OK) {
                Content = new StringContent("Result through custom message handler..")
            };
            
            var taskCompletionSource = new TaskCompletionSource();
            taskCompletionSource.SetResult(response);
            return await taskCompletionSource.Task;
        }
    }
}

เราได้ประกาศ CustomMessageHandler Class สืบทอดจาก DelegatingHandler และ Override ฟังก์ชัน SendAsync()

เมื่อ HTTP Request มาถึง CustomMessageHandler จะ Execute และส่งคืน HTTP Message เอง โดยไม่ Process Request ต่อไป นั่นหมายความว่าเรากำลังป้องกันไม่ให้ HTTP Request ไปถึง Controller

ขั้นตอนที่ 3: ลงทะเบียน CustomMessageHandler ใน Global.asax

public class WebApiApplication : System.Web.HttpApplication {
    protected void Application_Start() {
        GlobalConfiguration.Configure(WebApiConfig.Register);
        GlobalConfiguration.Configuration.MessageHandlers.Add(new CustomMessageHandler());
    }
}

ขั้นตอนที่ 4: ทดสอบ

Run Application และเรียก URL จะได้ Response จาก CustomMessageHandler แทนที่จะไปถึง Controller

รูปแบบ Message Handler ที่สมบูรณ์กว่า (Chaining)

public class LoggingMessageHandler : DelegatingHandler {
    protected async override Task SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken) {
        
        // Before request goes to inner handler
        Debug.WriteLine($"Request: {request.Method} {request.RequestUri}");
        
        // Call inner handler (next in pipeline)
        var response = await base.SendAsync(request, cancellationToken);
        
        // After response comes back
        Debug.WriteLine($"Response: {response.StatusCode}");
        
        return response;
    }
}

public class ApiKeyValidationHandler : DelegatingHandler {
    protected async override Task SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken) {
        
        // Validate API Key
        if (!request.Headers.Contains("X-Api-Key")) {
            var response = new HttpResponseMessage(HttpStatusCode.Unauthorized) {
                Content = new StringContent("API Key required")
            };
            return response; // Short-circuit - ไม่ไป Inner Handler
        }
        
        return await base.SendAsync(request, cancellationToken);
    }
}

// ลงทะเบียนในลำดับ (First added = Outermost)
config.MessageHandlers.Add(new LoggingMessageHandler());
config.MessageHandlers.Add(new ApiKeyValidationHandler());
config.MessageHandlers.Add(new CustomMessageHandler());

Client-Side Message Handler

ฝั่ง Client ใช้กับ HttpClient:

var handler = new HttpClientHandler();
var customHandler = new CustomClientHandler(handler);
var client = new HttpClient(customHandler);

public class CustomClientHandler : DelegatingHandler {
    protected override async Task SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken) {
        
        // Add custom header
        request.Headers.Add("X-Custom-Header", "MyValue");
        
        var response = await base.SendAsync(request, cancellationToken);
        
        // Log response
        Debug.WriteLine($"Response: {response.StatusCode}");
        return response;
    }
}