Dela via


Migrera HTTP-hanterare till ASP.NET Core-mellanprogram

Den här artikeln visar hur du migrerar befintliga ASP.NET HTTP-hanterare från system.webserver till ASP.NET Core-mellanprogram.

Handlers granskats på nytt

Innan vi fortsätter till ASP.NET Core-mellanprogram ska vi först sammanfatta hur HTTP-hanterare fungerar:

Modulhanterare

Hanterarna är:

  • Klasser som implementerar IHttpHandler

  • Används för att hantera begäranden med ett visst filnamn eller filnamnstillägg, till exempel .report

  • Konfigurerad i Web.config

Från hanterare till mellanprogram

Mellanprogram är enklare än HTTP-hanterare:

  • Hanterare ,Web.config (förutom IIS-konfiguration) och programmets livscykel är borta

  • Rollerna för hanterare har tagits över av mellanprogram

  • Mellanprogram konfigureras med hjälp av kod snarare än i Web.config

  • Med pipelineförgrening kan du skicka begäranden till specifika mellanprogram, baserat på inte bara URL:en utan även på begärandehuvuden, frågesträngar osv.
  • Med pipelineförgrening kan du skicka begäranden till specifika mellanprogram, baserat på inte bara URL:en utan även på begärandehuvuden, frågesträngar osv.

Mellanprogram är mycket lika hanterare:

  • Kunna skapa ett eget HTTP-svar

Authorization Middleware avbryter en begäran för en användare som inte har behörighet. En begäran för sidan Index tillåts och bearbetas av MVC Middleware. En begäran efter en försäljningsrapport tillåts och bearbetas av ett anpassat rapportmellanprogram.

Migrera hanterarkod till mellanprogram

En HTTP-hanterare ser ut ungefär så här:

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

I ditt ASP.NET Core-projekt skulle du översätta detta till ett mellanprogram som liknar detta:

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

Det här mellanprogrammet liknar det mellanprogram som motsvarar moduler. Den enda verkliga skillnaden är att det här inte finns något anrop till _next.Invoke(context). Det är vettigt eftersom hanteraren är i slutet av begärandepipelinen, så det kommer inte att finnas något nästa mellanprogram att anropa.

Migrera infogning av hanterare till begärandepipelinen

Konfigurationen av en HTTP-hanterare görs i Web.config och ser ut ungefär så här:

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

Du kan konvertera detta genom att lägga till ditt nya mellanprogram för hanterare i pipelinen för begäran i klassen Startup , ungefär som mellanprogram som konverterats från moduler. Problemet med den metoden är att det skulle skicka alla begäranden till ditt nya mellanprogram för hanterare. Du vill dock bara att begäranden med ett visst tillägg ska nå mellanprogrammet. Det skulle ge dig samma funktioner som du hade med DIN HTTP-hanterare.

En lösning är att förgrena pipelinen för begäranden med ett visst tillägg med hjälp av MapWhen tilläggsmetoden. Du gör detta i samma Configure metod där du lägger till det andra mellanprogrammet:

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 tar dessa parametrar:

  1. En lambda som tar HttpContext och returnerar true om begäran ska gå ned för grenen. Det innebär att du kan förgrena begäranden inte bara baserat på deras tillägg, utan även på begärandehuvuden, frågesträngsparametrar osv.

  2. En lambda som tar en IApplicationBuilder och lägger till alla mellanprogram för grenen. Det innebär att du kan lägga till ytterligare mellanprogram i grenen framför mellanprogrammet för hanteraren.

Mellanprogram som läggs till i pipelinen innan grenen kommer att anropas på alla begäranden; grenen kommer inte att påverka dem.

Mer information finns i dokumentationen om mellanprogram för ytterligare sätt att använda mellanprogram för att ersätta din användning av hanterare.

Migrera till den nya HttpContext

Metoden Invoke i mellanprogrammet tar en parameter av typen HttpContext:

public async Task Invoke(HttpContext context)

HttpContext har ändrats avsevärt i ASP.NET Core. Detaljerad information om hur du översätter de vanligaste egenskaperna System.Web.HttpContext för till den nya Microsoft.AspNetCore.Http.HttpContextfinns i Migrera från ASP.NET Framework HttpContext till ASP.NET Core.

Ytterligare resurser