Cara bekerja dengan pengendali mesej di API Web

Pengendali pesan di Web API memberi anda kesempatan untuk memproses, mengedit, atau menolak permintaan masuk sebelum sampai ke HttpControllerDispatcher. Pengendali mesej dilaksanakan lebih awal dalam proses pemprosesan permintaan, oleh itu mereka adalah tempat yang bagus untuk melaksanakan permasalahan silang di API Web.

Melaksanakan pengendali pesanan tersuai

Semua pengendali mesej berasal dari kelas HttpMessageHandler. Untuk membina pengendali mesej anda sendiri, anda harus melanjutkan kelas DelegatingHandler. Perhatikan bahawa kelas DelegatingHandler seterusnya berasal dari kelas HttpMessageHandler.

Pertimbangkan pengawal API Web berikut.

public class DefaultController : ApiController

    {

        public HttpResponseMessage Get()

        {

            return Request.CreateResponse(HttpStatusCode.OK, "Inside the Default Web API Controller...");           

        }

    }

Untuk membuat pengendali mesej, anda perlu melanjutkan kelas DelegatingHandler dan menimpa kaedah SendAsync.

public class Handler : DelegatingHandler

    {

        protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

        {

           return base.SendAsync(request, cancellationToken);

        }

    }

Saluran pemprosesan permintaan API Web merangkumi beberapa pengendali mesej terbina dalam. Ini termasuk yang berikut:

  • HttpServer - ini digunakan untuk mengambil permintaan dari host
  • HttpRoutingDispatcher - ini digunakan untuk mengirimkan permintaan berdasarkan rute yang dikonfigurasi
  • HttpControllerDispatcher - ini digunakan untuk menghantar permintaan ke pengawal masing-masing

Anda boleh menambahkan pengendali mesej ke saluran paip untuk melakukan satu atau lebih operasi berikut.

  • Lakukan pengesahan dan kebenaran
  • Mencatat permintaan masuk dan respons keluar
  • Tambahkan tajuk respons pada objek tindak balas
  • Baca atau ubah tajuk permintaan

Coretan kod berikut menunjukkan bagaimana anda dapat melaksanakan pengendali pesanan ringkas di API Web.

public class Handler : DelegatingHandler

{

protected async override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

        {

            var response = new HttpResponseMessage(HttpStatusCode.OK)

            {

                Content = new StringContent("Inside the message handler...")

            };

            var task = new TaskCompletionSource();

            task.SetResult(response);

            return await task.Task;

        }

}

Pengendali mesej tidak memproses mesej permintaan - ia membuat mesej respons dan kemudian mengembalikannya. Anda juga boleh memanggil versi dasar kaedah SendAsync jika anda tidak ingin melakukan apa-apa dengan permintaan masuk seperti yang ditunjukkan dalam senarai kod di bawah.

public class Handler : DelegatingHandler

{

protected async override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

        {

            return await base.SendAsync(request, cancellationToken);

        }

}

Anda juga boleh menulis kod untuk mencatat permintaan Http dan respons yang keluar dalam kaedah SendAsync.

Untuk melaksanakan API Web, anda boleh menggunakan kaedah ujian seperti yang diberikan di bawah.

 [TestMethod]

        public void WebAPIControllerTest()

        {

            HttpClient client = new HttpClient();

            var result = client.GetAsync(new Uri("//localhost//api/default/")).Result;

            string responseMessage = result.Content.ReadAsStringAsync().Result;

            Assert.IsTrue(result.IsSuccessStatusCode);

        }

Apabila anda menjalankan kaedah ujian, pesan "Inside the Default Web API Controller ..." dikembalikan sebagai mesej respons dan ujian lulus. Oh! Kami memang membuat pengendali mesej, tetapi kami belum mendaftarkannya ke saluran pengendalian mesej.

Anda sekarang perlu memberitahu infrastruktur API Web untuk mengetahui di mana pengendali tersuai anda ada. Untuk melakukan ini, anda harus mendaftarkan pengendali tersuai anda dalam perancangan. Anda boleh mendaftarkan pengendali pesanan khusus yang baru kami buat dalam kaedah Daftar kelas WebApiConfig seperti yang ditunjukkan di bawah.

public static void Register(HttpConfiguration config)

{

    GlobalConfiguration.Configuration.MessageHandlers.Add(new Handler());

}

Apabila anda menjalankan kaedah ujian sekali lagi, mesej teks "Di dalam pengendali mesej pembalakan ..." dikembalikan sebagai mesej respons dan ujian lulus.

Perhatikan bahawa anda juga dapat mendaftarkan banyak pengendali mesej ke saluran pengendalian pesan seperti yang ditunjukkan dalam potongan kode di bawah.

public static void Register(HttpConfiguration config)

{

    GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageHandlerA());

    GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageHandlerB());

    GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageHandlerC());

}

Pengendali pesan akan dijalankan dalam urutan di mana mereka telah ditambahkan ke saluran pipa dan respons akan dikembalikan dalam urutan terbalik. Dengan kata lain, pada saat permintaan masuk, pengendali pesan dilaksanakan dalam urutan di mana mereka didaftarkan. Semasa tindak balas keluar, prosesnya hanya terbalik. Jadi, pengendali mesej dilaksanakan dalam urutan terbalik pendaftaran mereka ke saluran paip.

Anda juga dapat menerapkan pengendali pesan yang memeriksa permintaan masuk dan memeriksa apakah permintaan tersebut berisi kunci api yang valid. Sekiranya kunci api tidak ada atau tidak sah, ia mengembalikan mesej ralat yang sesuai. Penyenaraian kod berikut menunjukkan bagaimana anda dapat melakukan ini - Saya menyerahkan kepada anda untuk menulis kod untuk mengesahkan kunci api.

protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

        {

            string key = HttpUtility.ParseQueryString(request.RequestUri.Query).Get("key");

            string errorMessage = "You need to specify the api key to access the Web API.";

            try

            {

                if (!string.IsNullOrWhiteSpace(key))

                {

                    return base.SendAsync(request, cancellationToken);

                }

                else

                {

                    HttpResponseMessage response = request.CreateErrorResponse(HttpStatusCode.Forbidden, errorMessage);

                    throw new HttpResponseException(response);

                }

            }

            catch

            {

                HttpResponseMessage response = request.CreateErrorResponse(HttpStatusCode.InternalServerError, "An unexpected error occured...");

                throw new HttpResponseException(response);

            }

        }