Sdílet prostřednictvím


Migrace modulů a obslužných rutin HTTP do middlewaru ASP.NET Core

Tento článek ukazuje, jak migrovat existující ASP.NET moduly HTTP a obslužné rutiny ze system.webserveru do middlewaru ASP.NET Core.

Moduly a obslužné rutiny se znovu zobrazí

Než se pustíme do ASP.NET middlewaru Core, pojďme nejprve zrekapitulovat, jak fungují moduly HTTP a obslužné rutiny:

Obslužná rutina modulů

Obslužné rutiny jsou:

  • Třídy, které implementují IHttpHandler

  • Používá se ke zpracování požadavků s daným názvem souboru nebo příponou, například .report.

  • Nakonfigurováno v souboru Web.config

Moduly jsou:

  • Třídy, které implementují IHttpModule

  • Vyvoláno pro každý požadavek

  • Možnost zkratování (zastavení dalšího zpracování žádosti)

  • Možnost přidat do odpovědi HTTP nebo vytvořit vlastní

  • Nakonfigurováno v souboru Web.config

Pořadí, ve kterém moduly zpracovávají příchozí požadavky, určuje:

  1. Události řady aktivované ASP.NET, například BeginRequest a AuthenticateRequest. Úplný seznam najdete v tématu System.Web.HttpApplication. Každý modul může vytvořit obslužnou rutinu pro jednu nebo více událostí.

  2. U stejné události je pořadí, ve kterém jsou nakonfigurované v souboru Web.config.

Kromě modulů můžete do Global.asax.cs souboru přidat obslužné rutiny pro události životního cyklu. Tyto obslužné rutiny se spouští po obslužných rutinách v nakonfigurovaných modulech.

Od obslužných rutin a modulů po middleware

Middleware je jednodušší než moduly a obslužné rutiny HTTP:

  • Moduly, obslužné rutiny, Global.asax.csWeb.config (s výjimkou konfigurace služby IIS) a životní cyklus aplikace jsou pryč.

  • Role modulů a obslužných rutin převzal middleware.

  • Middleware se konfiguruje pomocí kódu místo v souboru Web.config.

  • Větvení kanálů umožňuje odesílat požadavky do konkrétního middlewaru, a to na základě adresy URL, ale také hlaviček požadavků, řetězců dotazů atd.
  • Větvení kanálů umožňuje odesílat požadavky do konkrétního middlewaru, a to na základě adresy URL, ale také hlaviček požadavků, řetězců dotazů atd.

Middleware je velmi podobný modulům:

Middleware a moduly se zpracovávají v jiném pořadí:

Autorizační middleware zkratuje požadavek na uživatele, který nemá oprávnění. Požadavek na indexovou stránku je povolen a zpracován middlewarem MVC. Žádost o sestavu prodeje je povolena a zpracována vlastním middlewarem sestavy.

Všimněte si, jak na obrázku výše se požadavek zkrátil na ověřovacím middlewaru.

Migrace kódu modulu do middlewaru

Existující modul HTTP bude vypadat nějak takto:

// 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.
        }
    }
}

Jak je znázorněno na stránce Middleware, middleware ASP.NET Core je třída, která zveřejňuje metodu Invoke HttpContext Task, která přebírá a vrací . Váš nový middleware bude vypadat takto:

// 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>();
        }
    }
}

Předchozí šablona middlewaru byla převzata z části věnované psaní middlewaru.

Pomocná třída MyMiddlewareExtensions usnadňuje konfiguraci middlewaru ve třídě Startup . Metoda UseMyMiddleware přidá třídu middlewaru do kanálu požadavku. Služby vyžadované middlewarem se vloží do konstruktoru middlewaru.

Váš modul může žádost ukončit, například pokud uživatel nemá oprávnění:

// 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 to zpracovává tak, že nevolá Invoke další middleware v kanálu. Mějte na paměti, že se tím požadavek úplně neukončí, protože předchozí middlewary budou stále vyvolány, když odpověď provede cestu zpět v kanálu.

// 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.
}

Když migrujete funkce modulu do nového middlewaru, můžete zjistit, že se váš kód nekompiluje, protože HttpContext se třída výrazně změnila v ASP.NET Core. Později se dozvíte, jak migrovat na nový ASP.NET Core HttpContext.

Migrace modulu vložení do kanálu žádosti

Moduly HTTP se obvykle přidávají do kanálu požadavku pomocí 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>

Převeďte ho přidáním nového middlewaru do kanálu požadavku ve třídě 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?}");
    });
}

Přesné místo v kanálu, kam vkládáte nový middleware, závisí na události, kterou zpracovává jako modul (BeginRequestatd EndRequest.) a jeho pořadí v seznamu modulů v souboru Web.config.

Jak jsme uvedli dříve, v ASP.NET Core neexistuje žádný životní cyklus aplikace a pořadí, ve kterém se odpovědi zpracovávají middlewarem, se liší od pořadí používaného moduly. To by mohlo znamenat, že vaše rozhodnutí o objednávání bude náročnější.

Pokud se řazení stane problémem, můžete modul rozdělit na několik komponent middlewaru, které je možné objednat nezávisle.

Migrace kódu obslužné rutiny do middlewaru

Obslužná rutina HTTP vypadá přibližně takto:

// 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";
        }
    }
}

V projektu ASP.NET Core byste to přeložili do middlewaru podobnému tomuto:

// 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>();
        }
    }
}

Tento middleware je velmi podobný middlewaru odpovídajícím modulům. Jediným skutečným rozdílem je, že tady není žádné volání _next.Invoke(context). To dává smysl, protože obslužná rutina je na konci kanálu požadavku, takže nebude k dispozici žádný další middleware k vyvolání.

Migrace vložení obslužné rutiny do kanálu požadavku

Konfigurace obslužné rutiny HTTP se provádí v souboru Web.config a vypadá nějak takto:

<?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>

Můžete to převést přidáním nového middlewaru obslužné rutiny do kanálu požadavku ve vaší Startup třídě, podobně jako middleware převedený z modulů. Problém s tímto přístupem spočívá v tom, že by odeslal všechny požadavky do vašeho nového middlewaru obslužné rutiny. Chcete ale, aby se požadavky s daným rozšířením dostaly do vašeho middlewaru. To by vám poskytlo stejné funkce jako u obslužné rutiny HTTP.

Jedním z řešení je větvení kanálu pro požadavky s daným rozšířením pomocí MapWhen metody rozšíření. Provedete to ve stejné Configure metodě, ve které přidáte druhý middleware:

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 přebírá tyto parametry:

  1. Lambda, která vezme HttpContext a vrátí true , pokud má požadavek přejít dolů do větve. To znamená, že žádosti můžete rozvětvovat nejen na základě jejich rozšíření, ale také na hlavičkách požadavků, parametrech řetězce dotazu atd.

  2. Lambda, která vezme IApplicationBuilder a přidá veškerý middleware pro větev. To znamená, že do větve před middleware obslužné rutiny můžete přidat další middleware.

Middleware přidaný do kanálu před vyvolání větve pro všechny požadavky; větev nebude mít na ně žádný vliv.

Načítání možností middlewaru pomocí vzoru možností

Některé moduly a obslužné rutiny mají možnosti konfigurace uložené v souboru Web.config. V ASP.NET Core se ale místo Web.config používá nový konfigurační model.

Nový konfigurační systém nabízí tyto možnosti řešení:

  1. Vytvořte třídu pro uložení možností middlewaru, například:

    public class MyMiddlewareOptions
    {
        public string Param1 { get; set; }
        public string Param2 { get; set; }
    }
    
  2. Uložení hodnot možností

    Konfigurační systém umožňuje ukládat hodnoty možností kdekoli, kde chcete. Většina webů ale používá appsettings.jsontento přístup:

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

    MyMiddlewareOptionsSection je název oddílu. Nemusí se shodovat s názvem třídy možností.

  3. Přidružení hodnot možností ke třídě options

    Model možností používá architekturu injektáže závislostí ASP.NET Core k přidružení typu možností (například MyMiddlewareOptions) k MyMiddlewareOptions objektu, který má skutečné možnosti.

    Aktualizujte předmět Startup :

    1. Pokud používáte appsettings.json, přidejte ho do tvůrce konfigurace v konstruktoru Startup :

      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. Nakonfigurujte službu možností:

      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. Přidružte možnosti ke třídě možností:

      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. Vložte možnosti do konstruktoru middlewaru. Podobá se vkládání možností do kontroleru.

    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
        }
    }
    

    Metoda rozšíření UseMiddleware , která přidává váš middleware k IApplicationBuilder péči o injektáž závislostí.

    To není omezeno na IOptions objekty. Jakýkoli jiný objekt, který middleware vyžaduje, je možné tímto způsobem vloženého.

Načítání možností middlewaru prostřednictvím přímé injektáže

Vzor možností má výhodu, že vytváří volné spojení mezi hodnotami možností a jejich spotřebiteli. Jakmile přidružíte třídu možností se skutečnými hodnotami možností, může každá jiná třída získat přístup k možnostem prostřednictvím architektury injektáže závislostí. Není potřeba předávat hodnoty možností.

To se ale rozdělí, pokud chcete použít stejný middleware dvakrát, s různými možnostmi. Například autorizační middleware používaný v různých větvích, které umožňují různé role. Nelze přidružit dva různé objekty možností k jedné třídě možností.

Řešením je získat objekty možností se skutečnými hodnotami možností ve vaší Startup třídě a předat je přímo do každé instance middlewaru.

  1. Přidání druhého klíče do appsettings.json

    Pokud chcete do appsettings.json souboru přidat druhou sadu možností, použijte k jedinečné identifikaci nový klíč:

    {
      "MyMiddlewareOptionsSection2": {
        "Param1": "Param1Value2",
        "Param2": "Param2Value2"
      },
      "MyMiddlewareOptionsSection": {
        "Param1": "Param1Value",
        "Param2": "Param2Value"
      }
    }
    
  2. Načtěte hodnoty možností a předejte je middlewaru. Metoda Use... rozšíření (která přidává váš middleware do kanálu) je logické místo pro předávání hodnot možností:

    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. Povolte middleware, abyste mohli použít parametr možností. Zadejte přetížení Use... rozšiřující metody (která přebírá parametr možností a předává ho UseMiddleware). Při UseMiddleware zavolání s parametry předá parametry konstruktoru middlewaru při vytvoření instance middlewarového objektu.

    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));
        }
    }
    

    Všimněte si, jak se tím zalomí objekt možností v objektu OptionsWrapper . Tím se implementuje IOptions, podle očekávání middlewarový konstruktor.

Migrace na nový httpContext

Viděli jste dříve, že Invoke metoda v middlewaru přebírá parametr typu HttpContext:

public async Task Invoke(HttpContext context)

HttpContext výrazně se změnila v ASP.NET Core. Tato část ukazuje, jak přeložit nejčastěji používané vlastnosti System.Web.HttpContext na nový Microsoft.AspNetCore.Http.HttpContext.

HttpContext

HttpContext.Items se překládá na:

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

Jedinečné ID požadavku (bez system.Web.HttpContext protějšek)

Poskytuje jedinečné ID pro každý požadavek. Velmi užitečné zahrnout do protokolů.

string requestId = httpContext.TraceIdentifier;

HttpContext.Request

HttpContext.Request.HttpMethod se překládá na:

string httpMethod = httpContext.Request.Method;

HttpContext.Request.QueryString se překládá na:

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 a HttpContext.Request.RawUrl přeloží na:

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

HttpContext.Request.IsSecureConnection se překládá na:

var isSecureConnection = httpContext.Request.IsHttps;

HttpContext.Request.UserHostAddress se překládá na:

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

HttpContext.Request.Cookies se překládá na:

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 se překládá na:

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

HttpContext.Request.Headers se překládá na:

// 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 se překládá na:

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

HttpContext.Request.UrlReferrer se překládá na:

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

HttpContext.Request.ContentType se překládá na:

// 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 se překládá na:

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"];
}

Upozorňující

Hodnoty formuláře se čtou jenom v případě, že je podtyp obsahu x-www-form-urlencoded nebo form-data.

HttpContext.Request.InputStream se překládá na:

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

Upozorňující

Tento kód použijte pouze v middlewaru typu obslužné rutiny na konci kanálu.

Nezpracovaný text si můžete přečíst, jak je znázorněno výše, jenom jednou na požadavek. Middleware, který se pokusí přečíst tělo po prvním přečtení, přečte prázdné tělo.

To neplatí pro čtení formuláře, jak je znázorněno výše, protože to se provádí z vyrovnávací paměti.

HttpContext.Response

HttpContext.Response.Status a HttpContext.Response.StatusDescription se přeloží na:

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

HttpContext.Response.ContentEncoding a HttpContext.Response.ContentType se přeloží na:

// 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 samostatně také překládá na:

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

HttpContext.Response.Output se překládá na:

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

HttpContext.Response.TransmitFile

Obsluha souboru je popsána v části Funkce žádosti v ASP.NET Core.

HttpContext.Response.Headers

Odesílání hlaviček odpovědí je složité tím, že pokud je nastavíte po napsání čehokoli do textu odpovědi, neodesílají se.

Řešením je nastavit metodu zpětného volání, která bude volána přímo před zápisem do odpovědi. To se nejlépe provádí na začátku metody v middlewaru Invoke . Je to tato metoda zpětného volání, která nastavuje hlavičky odpovědi.

Následující kód nastaví metodu zpětného volání s názvem SetHeaders:

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

SetHeaders Metoda zpětného volání by vypadala takto:

// 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

Soubory cookie putují do prohlížeče v hlavičce set-responseCookie . V důsledku toho odesílání souborů cookie vyžaduje stejné zpětné volání jako při odesílání hlaviček odpovědi:

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

SetCookies Metoda zpětného volání by vypadala takto:

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); 
}

Další materiály