Bagikan melalui


Memigrasikan pengatur dan modul HTTP ke middleware ASP.NET Core

Artikel ini memperlihatkan cara memigrasikan modul dan handler HTTP ASP.NET yang ada dari system.webserver ke middleware ASP.NET Core.

Modul dan handler ditinjau kembali

Sebelum melanjutkan ke ASP.NET middleware Core, mari kita rekap terlebih dahulu cara kerja modul dan handler HTTP:

Handler Modul

Handler adalah:

  • Kelas yang mengimplementasikan IHttpHandler

  • Digunakan untuk menangani permintaan dengan nama file atau ekstensi tertentu, seperti .report

  • Dikonfigurasi di Web.config

Modulnya adalah:

  • Kelas yang mengimplementasikan IHttpModule

  • Dipanggil untuk setiap permintaan

  • Dapat melakukan sirkuit pendek (hentikan pemrosesan permintaan lebih lanjut)

  • Dapat menambahkan ke respons HTTP, atau membuat respons http mereka sendiri

  • Dikonfigurasi di Web.config

Urutan proses modul permintaan masuk ditentukan oleh:

  1. Serangkaian peristiwa yang dipicu oleh ASP.NET, seperti BeginRequest dan AuthenticateRequest. Untuk daftar lengkapnya, lihat System.Web.HttpApplication. Setiap modul dapat membuat handler untuk satu atau beberapa peristiwa.

  2. Untuk peristiwa yang sama, urutan konfigurasinya di Web.config.

Selain modul, Anda dapat menambahkan handler untuk peristiwa siklus hidup ke file Anda Global.asax.cs . Handler ini berjalan setelah handler dalam modul yang dikonfigurasi.

Dari handler dan modul hingga middleware

Middleware lebih sederhana daripada modul dan handler HTTP:

  • Modul, handler, Global.asax.cs, Web.config (kecuali untuk konfigurasi IIS) dan siklus hidup aplikasi hilang

  • Peran modul dan handler telah diambil alih oleh middleware

  • Middleware dikonfigurasi menggunakan kode daripada di Web.config

  • Pencabangan alur memungkinkan Anda mengirim permintaan ke middleware tertentu, berdasarkan tidak hanya URL tetapi juga pada header permintaan, string kueri, dll.
  • Pencabangan alur memungkinkan Anda mengirim permintaan ke middleware tertentu, berdasarkan tidak hanya URL tetapi juga pada header permintaan, string kueri, dll.

Middleware sangat mirip dengan modul:

Middleware dan modul diproses dalam urutan yang berbeda:

Sirkuit pendek Middleware otorisasi mengajukan permintaan untuk pengguna yang tidak diotorisasi. Permintaan untuk halaman Indeks diizinkan dan diproses oleh Middleware MVC. Permintaan untuk laporan penjualan diizinkan dan diproses oleh laporan kustom Middleware.

Perhatikan bagaimana pada gambar di atas, middleware autentikasi sirkuit pendek permintaan.

Memigrasikan kode modul ke middleware

Modul HTTP yang ada akan terlihat mirip dengan ini:

// ASP.NET 4 module

using System;
using System.Web;

namespace MyApp.Modules
{
    public class MyModule : IHttpModule
    {
        public void Dispose()
        {
        }

        public void Init(HttpApplication application)
        {
            application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
            application.EndRequest += (new EventHandler(this.Application_EndRequest));
        }

        private void Application_BeginRequest(Object source, EventArgs e)
        {
            HttpContext context = ((HttpApplication)source).Context;

            // Do something with context near the beginning of request processing.
        }

        private void Application_EndRequest(Object source, EventArgs e)
        {
            HttpContext context = ((HttpApplication)source).Context;

            // Do something with context near the end of request processing.
        }
    }
}

Seperti yang ditunjukkan di halaman Middleware , middleware ASP.NET Core adalah kelas yang mengekspos Invoke metode mengambil HttpContext dan mengembalikan Task. Middleware baru Anda akan terlihat seperti ini:

// ASP.NET Core middleware

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;

namespace MyApp.Middleware
{
    public class MyMiddleware
    {
        private readonly RequestDelegate _next;

        public MyMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            // Do something with context near the beginning of request processing.

            await _next.Invoke(context);

            // Clean up.
        }
    }

    public static class MyMiddlewareExtensions
    {
        public static IApplicationBuilder UseMyMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<MyMiddleware>();
        }
    }
}

Templat middleware sebelumnya diambil dari bagian tentang menulis middleware.

Kelas pembantu MyMiddlewareExtensions memudahkan konfigurasi middleware Anda di kelas Anda Startup . Metode menambahkan UseMyMiddleware kelas middleware Anda ke alur permintaan. Layanan yang diperlukan oleh middleware disuntikkan ke konstruktor middleware.

Modul Anda mungkin mengakhiri permintaan, misalnya jika pengguna tidak diotorisasi:

// ASP.NET 4 module that may terminate the request

private void Application_BeginRequest(Object source, EventArgs e)
{
    HttpContext context = ((HttpApplication)source).Context;

    // Do something with context near the beginning of request processing.

    if (TerminateRequest())
    {
        context.Response.End();
        return;
    }
}

Middleware menangani ini dengan tidak memanggil Invoke middleware berikutnya di alur. Perlu diingat bahwa ini tidak sepenuhnya mengakhiri permintaan, karena middleware sebelumnya masih akan dipanggil ketika respons kembali melalui alur.

// ASP.NET Core middleware that may terminate the request

public async Task Invoke(HttpContext context)
{
    // Do something with context near the beginning of request processing.

    if (!TerminateRequest())
        await _next.Invoke(context);

    // Clean up.
}

Saat memigrasikan fungsionalitas modul ke middleware baru, Anda mungkin menemukan bahwa kode Anda tidak dikompilasi karena HttpContext kelas telah berubah secara signifikan di ASP.NET Core. Nantinya, Anda akan melihat cara bermigrasi ke ASP.NET Core HttpContext baru.

Memigrasikan penyisipan modul ke dalam alur permintaan

Modul HTTP biasanya ditambahkan ke alur permintaan menggunakan Web.config:

<?xml version="1.0" encoding="utf-8"?>
<!--ASP.NET 4 web.config-->
<configuration>
  <system.webServer>
    <modules>
      <add name="MyModule" type="MyApp.Modules.MyModule"/>
    </modules>
  </system.webServer>
</configuration>

Konversikan ini dengan menambahkan middleware baru Anda ke alur permintaan di kelas Anda Startup :

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseMyMiddleware();

    app.UseMyMiddlewareWithParams();

    var myMiddlewareOptions = Configuration.GetSection("MyMiddlewareOptionsSection").Get<MyMiddlewareOptions>();
    var myMiddlewareOptions2 = Configuration.GetSection("MyMiddlewareOptionsSection2").Get<MyMiddlewareOptions>();
    app.UseMyMiddlewareWithParams(myMiddlewareOptions);
    app.UseMyMiddlewareWithParams(myMiddlewareOptions2);

    app.UseMyTerminatingMiddleware();

    // Create branch to the MyHandlerMiddleware. 
    // All requests ending in .report will follow this branch.
    app.MapWhen(
        context => context.Request.Path.ToString().EndsWith(".report"),
        appBranch => {
            // ... optionally add more middleware to this branch
            appBranch.UseMyHandler();
        });

    app.MapWhen(
        context => context.Request.Path.ToString().EndsWith(".context"),
        appBranch => {
            appBranch.UseHttpContextDemoMiddleware();
        });

    app.UseStaticFiles();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

Tempat yang tepat dalam alur tempat Anda memasukkan middleware baru tergantung pada peristiwa yang ditanganinya sebagai modul (BeginRequest, , EndRequestdll.) dan urutannya dalam daftar modul Anda di Web.config.

Seperti yang dinyatakan sebelumnya, tidak ada siklus hidup aplikasi di ASP.NET Core dan urutan di mana respons diproses oleh middleware berbeda dari urutan yang digunakan oleh modul. Ini bisa membuat keputusan pemesanan Anda lebih menantang.

Jika pemesanan menjadi masalah, Anda dapat membagi modul Anda menjadi beberapa komponen middleware yang dapat dipesan secara independen.

Memigrasikan kode handler ke middleware

Handler HTTP terlihat seperti ini:

// ASP.NET 4 handler

using System.Web;

namespace MyApp.HttpHandlers
{
    public class MyHandler : IHttpHandler
    {
        public bool IsReusable { get { return true; } }

        public void ProcessRequest(HttpContext context)
        {
            string response = GenerateResponse(context);

            context.Response.ContentType = GetContentType();
            context.Response.Output.Write(response);
        }

        // ...

        private string GenerateResponse(HttpContext context)
        {
            string title = context.Request.QueryString["title"];
            return string.Format("Title of the report: {0}", title);
        }

        private string GetContentType()
        {
            return "text/plain";
        }
    }
}

Dalam proyek ASP.NET Core Anda, Anda akan menerjemahkan ini ke middleware yang mirip dengan ini:

// ASP.NET Core middleware migrated from a handler

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;

namespace MyApp.Middleware
{
    public class MyHandlerMiddleware
    {

        // Must have constructor with this signature, otherwise exception at run time
        public MyHandlerMiddleware(RequestDelegate next)
        {
            // This is an HTTP Handler, so no need to store next
        }

        public async Task Invoke(HttpContext context)
        {
            string response = GenerateResponse(context);

            context.Response.ContentType = GetContentType();
            await context.Response.WriteAsync(response);
        }

        // ...

        private string GenerateResponse(HttpContext context)
        {
            string title = context.Request.Query["title"];
            return string.Format("Title of the report: {0}", title);
        }

        private string GetContentType()
        {
            return "text/plain";
        }
    }

    public static class MyHandlerExtensions
    {
        public static IApplicationBuilder UseMyHandler(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<MyHandlerMiddleware>();
        }
    }
}

Middleware ini sangat mirip dengan middleware yang sesuai dengan modul. Satu-satunya perbedaan nyata adalah bahwa di sini tidak ada panggilan ke _next.Invoke(context). Itu masuk akal, karena handler berada di akhir alur permintaan, sehingga tidak akan ada middleware berikutnya untuk dipanggil.

Memigrasikan penyisipan handler ke dalam alur permintaan

Mengonfigurasi handler HTTP dilakukan di Web.config dan terlihat seperti ini:

<?xml version="1.0" encoding="utf-8"?>
<!--ASP.NET 4 web.config-->
<configuration>
  <system.webServer>
    <handlers>
      <add name="MyHandler" verb="*" path="*.report" type="MyApp.HttpHandlers.MyHandler" resourceType="Unspecified" preCondition="integratedMode"/>
    </handlers>
  </system.webServer>
</configuration>

Anda dapat mengonversi ini dengan menambahkan middleware handler baru Anda ke alur permintaan di kelas Anda Startup , mirip dengan middleware yang dikonversi dari modul. Masalah dengan pendekatan itu adalah bahwa itu akan mengirim semua permintaan ke middleware handler baru Anda. Namun, Anda hanya ingin permintaan dengan ekstensi tertentu mencapai middleware Anda. Itu akan memberi Anda fungsionalitas yang sama dengan handler HTTP Anda.

Salah satu solusinya adalah mencabangkan alur untuk permintaan dengan ekstensi tertentu, menggunakan MapWhen metode ekstensi. Anda melakukan ini dalam metode yang sama Configure di mana Anda menambahkan middleware lainnya:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseMyMiddleware();

    app.UseMyMiddlewareWithParams();

    var myMiddlewareOptions = Configuration.GetSection("MyMiddlewareOptionsSection").Get<MyMiddlewareOptions>();
    var myMiddlewareOptions2 = Configuration.GetSection("MyMiddlewareOptionsSection2").Get<MyMiddlewareOptions>();
    app.UseMyMiddlewareWithParams(myMiddlewareOptions);
    app.UseMyMiddlewareWithParams(myMiddlewareOptions2);

    app.UseMyTerminatingMiddleware();

    // Create branch to the MyHandlerMiddleware. 
    // All requests ending in .report will follow this branch.
    app.MapWhen(
        context => context.Request.Path.ToString().EndsWith(".report"),
        appBranch => {
            // ... optionally add more middleware to this branch
            appBranch.UseMyHandler();
        });

    app.MapWhen(
        context => context.Request.Path.ToString().EndsWith(".context"),
        appBranch => {
            appBranch.UseHttpContextDemoMiddleware();
        });

    app.UseStaticFiles();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

MapWhen mengambil parameter ini:

  1. Lambda yang mengambil HttpContext dan mengembalikan true jika permintaan harus turun ke cabang. Ini berarti Anda dapat mencabangkan permintaan tidak hanya berdasarkan ekstensinya, tetapi juga pada header permintaan, parameter string kueri, dll.

  2. Lambda yang mengambil IApplicationBuilder dan menambahkan semua middleware untuk cabang. Ini berarti Anda dapat menambahkan middleware tambahan ke cabang di depan middleware handler Anda.

Middleware ditambahkan ke alur sebelum cabang akan dipanggil pada semua permintaan; cabang tidak akan berdampak pada mereka.

Memuat opsi middleware menggunakan pola opsi

Beberapa modul dan handler memiliki opsi konfigurasi yang disimpan di Web.config. Namun, di ASP.NET Core, model konfigurasi baru digunakan sebagai pengganti Web.config.

Sistem konfigurasi baru memberi Anda opsi ini untuk menyelesaikan ini:

  • Langsung masukkan opsi ke middleware, seperti yang ditunjukkan di bagian berikutnya.

  • Gunakan pola opsi:

  1. Buat kelas untuk menyimpan opsi middleware Anda, misalnya:

    public class MyMiddlewareOptions
    {
        public string Param1 { get; set; }
        public string Param2 { get; set; }
    }
    
  2. Menyimpan nilai opsi

    Sistem konfigurasi memungkinkan Anda menyimpan nilai opsi di mana pun Anda inginkan. Namun, sebagian besar situs menggunakan appsettings.json, jadi kita akan mengambil pendekatan itu:

    {
      "MyMiddlewareOptionsSection": {
        "Param1": "Param1Value",
        "Param2": "Param2Value"
      }
    }
    

    MyMiddlewareOptionsSection di sini adalah nama bagian. Tidak harus sama dengan nama kelas opsi Anda.

  3. Mengaitkan nilai opsi dengan kelas opsi

    Pola opsi menggunakan ASP.NET kerangka kerja injeksi dependensi Core untuk mengaitkan jenis opsi (seperti MyMiddlewareOptions) dengan MyMiddlewareOptions objek yang memiliki opsi aktual.

    Perbarui kelas Anda Startup :

    1. Jika Anda menggunakan appsettings.json, tambahkan ke penyusun konfigurasi di Startup konstruktor:

      public Startup(IHostingEnvironment env)
      {
          var builder = new ConfigurationBuilder()
              .SetBasePath(env.ContentRootPath)
              .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
              .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
              .AddEnvironmentVariables();
          Configuration = builder.Build();
      }
      
    2. Konfigurasikan layanan opsi:

      public void ConfigureServices(IServiceCollection services)
      {
          // Setup options service
          services.AddOptions();
      
          // Load options from section "MyMiddlewareOptionsSection"
          services.Configure<MyMiddlewareOptions>(
              Configuration.GetSection("MyMiddlewareOptionsSection"));
      
          // Add framework services.
          services.AddMvc();
      }
      
    3. Kaitkan opsi Anda dengan kelas opsi Anda:

      public void ConfigureServices(IServiceCollection services)
      {
          // Setup options service
          services.AddOptions();
      
          // Load options from section "MyMiddlewareOptionsSection"
          services.Configure<MyMiddlewareOptions>(
              Configuration.GetSection("MyMiddlewareOptionsSection"));
      
          // Add framework services.
          services.AddMvc();
      }
      
  4. Masukkan opsi ke konstruktor middleware Anda. Ini mirip dengan menyuntikkan opsi ke pengontrol.

    public class MyMiddlewareWithParams
    {
        private readonly RequestDelegate _next;
        private readonly MyMiddlewareOptions _myMiddlewareOptions;
    
        public MyMiddlewareWithParams(RequestDelegate next,
            IOptions<MyMiddlewareOptions> optionsAccessor)
        {
            _next = next;
            _myMiddlewareOptions = optionsAccessor.Value;
        }
    
        public async Task Invoke(HttpContext context)
        {
            // Do something with context near the beginning of request processing
            // using configuration in _myMiddlewareOptions
    
            await _next.Invoke(context);
    
            // Do something with context near the end of request processing
            // using configuration in _myMiddlewareOptions
        }
    }
    

    Metode ekstensi UseMiddleware yang menambahkan middleware Anda ke IApplicationBuilder mengurus injeksi dependensi.

    Ini tidak terbatas pada IOptions objek. Objek lain yang diperlukan middleware Anda dapat disuntikkan dengan cara ini.

Memuat opsi middleware melalui injeksi langsung

Pola opsi memiliki keuntungan karena menciptakan kopling longgar antara nilai opsi dan konsumennya. Setelah Anda mengaitkan kelas opsi dengan nilai opsi aktual, kelas lain apa pun bisa mendapatkan akses ke opsi melalui kerangka kerja injeksi dependensi. Tidak perlu meneruskan nilai opsi.

Ini memecah meskipun jika Anda ingin menggunakan middleware yang sama dua kali, dengan opsi yang berbeda. Misalnya middleware otorisasi yang digunakan di cabang yang berbeda yang memungkinkan peran yang berbeda. Anda tidak dapat mengaitkan dua objek opsi yang berbeda dengan satu kelas opsi.

Solusinya adalah mendapatkan objek opsi dengan nilai opsi aktual di kelas Anda Startup dan meneruskan objek tersebut langsung ke setiap instans middleware Anda.

  1. Menambahkan kunci kedua ke appsettings.json

    Untuk menambahkan sekumpulan opsi kedua ke appsettings.json file, gunakan kunci baru untuk mengidentifikasinya secara unik:

    {
      "MyMiddlewareOptionsSection2": {
        "Param1": "Param1Value2",
        "Param2": "Param2Value2"
      },
      "MyMiddlewareOptionsSection": {
        "Param1": "Param1Value",
        "Param2": "Param2Value"
      }
    }
    
  2. Ambil nilai opsi dan teruskan ke middleware. Metode Use... ekstensi (yang menambahkan middleware Anda ke alur) adalah tempat logis untuk meneruskan nilai opsi:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();
    
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseBrowserLink();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }
    
        app.UseMyMiddleware();
    
        app.UseMyMiddlewareWithParams();
    
        var myMiddlewareOptions = Configuration.GetSection("MyMiddlewareOptionsSection").Get<MyMiddlewareOptions>();
        var myMiddlewareOptions2 = Configuration.GetSection("MyMiddlewareOptionsSection2").Get<MyMiddlewareOptions>();
        app.UseMyMiddlewareWithParams(myMiddlewareOptions);
        app.UseMyMiddlewareWithParams(myMiddlewareOptions2);
    
        app.UseMyTerminatingMiddleware();
    
        // Create branch to the MyHandlerMiddleware. 
        // All requests ending in .report will follow this branch.
        app.MapWhen(
            context => context.Request.Path.ToString().EndsWith(".report"),
            appBranch => {
                // ... optionally add more middleware to this branch
                appBranch.UseMyHandler();
            });
    
        app.MapWhen(
            context => context.Request.Path.ToString().EndsWith(".context"),
            appBranch => {
                appBranch.UseHttpContextDemoMiddleware();
            });
    
        app.UseStaticFiles();
    
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
    
  3. Aktifkan middleware untuk mengambil parameter opsi. Berikan kelebihan beban Use... metode ekstensi (yang mengambil parameter opsi dan meneruskannya ke UseMiddleware). Ketika UseMiddleware dipanggil dengan parameter, ia meneruskan parameter ke konstruktor middleware Anda saat membuat instans objek middleware.

    public static class MyMiddlewareWithParamsExtensions
    {
        public static IApplicationBuilder UseMyMiddlewareWithParams(
            this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<MyMiddlewareWithParams>();
        }
    
        public static IApplicationBuilder UseMyMiddlewareWithParams(
            this IApplicationBuilder builder, MyMiddlewareOptions myMiddlewareOptions)
        {
            return builder.UseMiddleware<MyMiddlewareWithParams>(
                new OptionsWrapper<MyMiddlewareOptions>(myMiddlewareOptions));
        }
    }
    

    Perhatikan bagaimana ini membungkus objek opsi dalam OptionsWrapper objek. Ini mengimplementasikan IOptions, seperti yang diharapkan oleh konstruktor middleware.

Bermigrasi ke HttpContext baru

Anda melihat sebelumnya bahwa Invoke metode di middleware Anda mengambil parameter jenis HttpContext:

public async Task Invoke(HttpContext context)

HttpContext secara signifikan berubah dalam ASP.NET Core. Bagian ini menunjukkan cara menerjemahkan properti yang paling umum digunakan ke System.Web.HttpContext yang baru Microsoft.AspNetCore.Http.HttpContext.

HttpContext

HttpContext.Items diterjemahkan ke:

IDictionary<object, object> items = httpContext.Items;

ID permintaan unik (tidak ada mitra System.Web.HttpContext)

Memberi Anda id unik untuk setiap permintaan. Sangat berguna untuk disertakan dalam log Anda.

string requestId = httpContext.TraceIdentifier;

HttpContext.Request

HttpContext.Request.HttpMethod diterjemahkan ke:

string httpMethod = httpContext.Request.Method;

HttpContext.Request.QueryString diterjemahkan ke:

IQueryCollection queryParameters = httpContext.Request.Query;

// If no query parameter "key" used, values will have 0 items
// If single value used for a key (...?key=v1), values will have 1 item ("v1")
// If key has multiple values (...?key=v1&key=v2), values will have 2 items ("v1" and "v2")
IList<string> values = queryParameters["key"];

// If no query parameter "key" used, value will be ""
// If single value used for a key (...?key=v1), value will be "v1"
// If key has multiple values (...?key=v1&key=v2), value will be "v1,v2"
string value = queryParameters["key"].ToString();

HttpContext.Request.Url dan HttpContext.Request.RawUrl menerjemahkan ke:

// using Microsoft.AspNetCore.Http.Extensions;
var url = httpContext.Request.GetDisplayUrl();

HttpContext.Request.IsSecure Koneksi ion diterjemahkan ke:

var isSecureConnection = httpContext.Request.IsHttps;

HttpContext.Request.UserHostAddress diterjemahkan ke:

var userHostAddress = httpContext.Connection.RemoteIpAddress?.ToString();

HttpContext.Request.Cookies diterjemahkan ke:

IRequestCookieCollection cookies = httpContext.Request.Cookies;
string unknownCookieValue = cookies["unknownCookie"]; // will be null (no exception)
string knownCookieValue = cookies["cookie1name"];     // will be actual value

HttpContext.Request.RequestContext.RouteData diterjemahkan ke:

var routeValue = httpContext.GetRouteValue("key");

HttpContext.Request.Headers diterjemahkan ke:

// using Microsoft.AspNetCore.Http.Headers;
// using Microsoft.Net.Http.Headers;

IHeaderDictionary headersDictionary = httpContext.Request.Headers;

// GetTypedHeaders extension method provides strongly typed access to many headers
var requestHeaders = httpContext.Request.GetTypedHeaders();
CacheControlHeaderValue cacheControlHeaderValue = requestHeaders.CacheControl;

// For unknown header, unknownheaderValues has zero items and unknownheaderValue is ""
IList<string> unknownheaderValues = headersDictionary["unknownheader"];
string unknownheaderValue = headersDictionary["unknownheader"].ToString();

// For known header, knownheaderValues has 1 item and knownheaderValue is the value
IList<string> knownheaderValues = headersDictionary[HeaderNames.AcceptLanguage];
string knownheaderValue = headersDictionary[HeaderNames.AcceptLanguage].ToString();

HttpContext.Request.UserAgent diterjemahkan ke:

string userAgent = headersDictionary[HeaderNames.UserAgent].ToString();

HttpContext.Request.UrlReferrer diterjemahkan ke:

string urlReferrer = headersDictionary[HeaderNames.Referer].ToString();

HttpContext.Request.ContentType diterjemahkan ke:

// using Microsoft.Net.Http.Headers;

MediaTypeHeaderValue mediaHeaderValue = requestHeaders.ContentType;
string contentType = mediaHeaderValue?.MediaType.ToString();   // ex. application/x-www-form-urlencoded
string contentMainType = mediaHeaderValue?.Type.ToString();    // ex. application
string contentSubType = mediaHeaderValue?.SubType.ToString();  // ex. x-www-form-urlencoded

System.Text.Encoding requestEncoding = mediaHeaderValue?.Encoding;

HttpContext.Request.Form diterjemahkan ke:

if (httpContext.Request.HasFormContentType)
{
    IFormCollection form;

    form = httpContext.Request.Form; // sync
    // Or
    form = await httpContext.Request.ReadFormAsync(); // async

    string firstName = form["firstname"];
    string lastName = form["lastname"];
}

Peringatan

Baca nilai formulir hanya jika sub jenis konten adalah x-www-form-urlencoded atau form-data.

HttpContext.Request.InputStream diterjemahkan ke:

string inputBody;
using (var reader = new System.IO.StreamReader(
    httpContext.Request.Body, System.Text.Encoding.UTF8))
{
    inputBody = reader.ReadToEnd();
}

Peringatan

Gunakan kode ini hanya dalam middleware jenis handler, di akhir alur.

Anda dapat membaca tubuh mentah seperti yang ditunjukkan di atas hanya sekali per permintaan. Middleware yang mencoba membaca isi setelah bacaan pertama akan membaca isi kosong.

Ini tidak berlaku untuk membaca formulir seperti yang ditunjukkan sebelumnya, karena itu dilakukan dari buffer.

HttpContext.Response

HttpContext.Response.Status dan HttpContext.Response.StatusDescription diterjemahkan ke:

// using Microsoft.AspNetCore.Http;
httpContext.Response.StatusCode = StatusCodes.Status200OK;

HttpContext.Response.ContentEncoding dan HttpContext.Response.ContentType diterjemahkan ke:

// using Microsoft.Net.Http.Headers;
var mediaType = new MediaTypeHeaderValue("application/json");
mediaType.Encoding = System.Text.Encoding.UTF8;
httpContext.Response.ContentType = mediaType.ToString();

HttpContext.Response.ContentType sendiri juga diterjemahkan ke:

httpContext.Response.ContentType = "text/html";

HttpContext.Response.Output diterjemahkan ke:

string responseContent = GetResponseContent();
await httpContext.Response.WriteAsync(responseContent);

HttpContext.Response.TransmitFile

Menyajikan file dibahas dalam Fitur Permintaan di ASP.NET Core.

HttpContext.Response.Headers

Mengirim header respons rumit oleh fakta bahwa jika Anda mengaturnya setelah apa pun ditulis ke isi respons, header tersebut tidak akan dikirim.

Solusinya adalah mengatur metode panggilan balik yang akan dipanggil tepat sebelum menulis ke respons dimulai. Ini paling baik dilakukan pada awal Invoke metode di middleware Anda. Metode panggilan balik inilah yang mengatur header respons Anda.

Kode berikut menetapkan metode panggilan balik yang disebut SetHeaders:

public async Task Invoke(HttpContext httpContext)
{
    // ...
    httpContext.Response.OnStarting(SetHeaders, state: httpContext);

Metode SetHeaders panggilan balik akan terlihat seperti ini:

// using Microsoft.AspNet.Http.Headers;
// using Microsoft.Net.Http.Headers;

private Task SetHeaders(object context)
{
    var httpContext = (HttpContext)context;

    // Set header with single value
    httpContext.Response.Headers["ResponseHeaderName"] = "headerValue";

    // Set header with multiple values
    string[] responseHeaderValues = new string[] { "headerValue1", "headerValue1" };
    httpContext.Response.Headers["ResponseHeaderName"] = responseHeaderValues;

    // Translating ASP.NET 4's HttpContext.Response.RedirectLocation  
    httpContext.Response.Headers[HeaderNames.Location] = "http://www.example.com";
    // Or
    httpContext.Response.Redirect("http://www.example.com");

    // GetTypedHeaders extension method provides strongly typed access to many headers
    var responseHeaders = httpContext.Response.GetTypedHeaders();

    // Translating ASP.NET 4's HttpContext.Response.CacheControl 
    responseHeaders.CacheControl = new CacheControlHeaderValue
    {
        MaxAge = new System.TimeSpan(365, 0, 0, 0)
        // Many more properties available 
    };

    // If you use .NET Framework 4.6+, Task.CompletedTask will be a bit faster
    return Task.FromResult(0);
}

HttpContext.Response.CookieS

Cookies bepergian ke browser di header Set-Cookie respons. Akibatnya, pengiriman cookiememerlukan panggilan balik yang sama seperti yang digunakan untuk mengirim header respons:

public async Task Invoke(HttpContext httpContext)
{
    // ...
    httpContext.Response.OnStarting(SetCookies, state: httpContext);
    httpContext.Response.OnStarting(SetHeaders, state: httpContext);

Metode SetCookies panggilan balik akan terlihat seperti berikut:

private Task SetCookies(object context)
{
    var httpContext = (HttpContext)context;

    IResponseCookies responseCookies = httpContext.Response.Cookies;

    responseCookies.Append("cookie1name", "cookie1value");
    responseCookies.Append("cookie2name", "cookie2value",
        new CookieOptions { Expires = System.DateTime.Now.AddDays(5), HttpOnly = true });

    // If you use .NET Framework 4.6+, Task.CompletedTask will be a bit faster
    return Task.FromResult(0); 
}

Sumber Daya Tambahan: