Compartir a través de


Migración de estado de sesión incremental IHttpModule de ASP.NET a ASP.NET Core

Los módulos son tipos que implementan IHttpModule y se usan en ASP.NET Framework para enlazar a la canalización de solicitudes en varios eventos. En una aplicación ASP.NET Core, lo ideal es que se migren al middleware. Sin embargo, hay ocasiones en las que esto no se puede hacer. Para admitir escenarios de migración en los que se requieren módulos y no se pueden mover al middleware, los adaptadores System.Web admiten agregarlos a ASP.NET Core.

Ejemplo de IHttpModule

Para admitir módulos, debe estar disponible una instancia de HttpApplication. Si no se usa ningún HttpApplication personalizado, se usará uno predeterminado para agregar los módulos. Los eventos declarados en una aplicación personalizada (incluido Application_Start) se registrarán y se ejecutarán en consecuencia.

using System.Web;
using Microsoft.AspNetCore.OutputCaching;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSystemWebAdapters()
    .AddHttpApplication<MyApp>(options =>
    {
        // Size of pool for HttpApplication instances. Should be what the expected concurrent requests will be
        options.PoolSize = 10;

        // Register a module (optionally) by name
        options.RegisterModule<MyModule>("MyModule");
    });

// Only available in .NET 7+
builder.Services.AddOutputCache(options =>
{
    options.AddHttpApplicationBasePolicy(_ => new[] { "browser" });
});

var app = builder.Build();

app.UseAuthentication();
app.UseAuthenticationEvents();

app.UseAuthorization();
app.UseAuthorizationEvents();

app.UseSystemWebAdapters();
app.UseOutputCache();

app.MapGet("/", () => "Hello World!")
    .CacheOutput();

app.Run();

class MyApp : HttpApplication
{
    protected void Application_Start()
    {
    }

    public override string? GetVaryByCustomString(System.Web.HttpContext context, string custom)
    {
        // Any custom vary-by string needed

        return base.GetVaryByCustomString(context, custom);
    }
}

class MyModule : IHttpModule
{
  public void Dispose()
  {
  }

  public void Init(HttpApplication application)
  {
    application.BeginRequest += (s, e) =>
    {
      // Handle events at the beginning of a request
    }

    application.AuthorizeRequest += (s, e) =>
    {
      // Handle events that need to be authorized
    }
  }
}

Migración global.asax

Esta infraestructura se puede usar para migrar el uso de Global.asax si es necesario. El origen de Global.asax es un HttpApplication personalizado y el archivo se puede incluir en una aplicación ASP.NET Core. Dado que se denomina Global, se puede usar el código siguiente para registrarlo:

builder.Services.AddSystemWebAdapters()
    .AddHttpApplication<Global>()

Siempre que la lógica dentro del mismo esté disponible en ASP.NET Core, este enfoque se puede usar para migrar incrementalmente la dependencia de Global.asax a ASP.NET Core.

Eventos de autenticación y autorización

Para que los eventos de autenticación y autorización se ejecuten en el momento deseado, se debe usar el siguiente patrón:

app.UseAuthentication();
app.UseAuthenticationEvents();

app.UseAuthorization();
app.UseAuthorizationEvents();

Si esto no se hace, los eventos se seguirán ejecutando. Sin embargo, se hará durante la llamada de .UseSystemWebAdapters().

Agrupación de módulos HTTP

Dado que los módulos y las aplicaciones de ASP.NET Framework se asignaron a una solicitud, se necesita una nueva instancia para cada solicitud. Sin embargo, dado que pueden ser costosos de crear, se agrupan mediante ObjectPool<T>. Para personalizar la duración real de las instancias HttpApplication, se puede usar un grupo personalizado:

services.TryAddSingleton<ObjectPool<HttpApplication>>(sp =>
{
  // Recommended to use the in-built policy as that will ensure everything is initialized correctly and is not intended to be replaced
  var policy = sp.GetRequiredService<IPooledOjbectPolicy<HttpApplication>>()

  // Can use any provider needed
  var provider = new DefaultObjectPoolProvider();

  // Use the provider to create a custom pool that will then be used for the application.
  return provider.Create(policy);
});

Recursos adicionales