Freigeben über


System.Web-Adapter

Der Hauptanwendungsfall der Adapter im Repository "dotnet/systemweb-adapters " besteht darin, Entwicklern zu helfen, die sich auf System.Web Typen innerhalb ihrer Klassenbibliotheken verlassen haben, da sie zu ASP.NET Core wechseln möchten.

Ein wichtiges Merkmal der Adapter ist, dass sie die Verwendung der Bibliothek sowohl in ASP.NET Framework- als auch in ASP.NET Core-Projekten ermöglichen. Das Aktualisieren mehrerer ASP.NET Framework-Apps auf ASP.NET Core umfasst häufig Zwischenzustände, in denen nicht alle Apps vollständig aktualisiert wurden. Mithilfe der System.Web Adapter kann die Bibliothek sowohl von ASP.NET Core-Aufrufern als auch von ASP.NET Framework-Aufrufern verwendet werden, die nicht aktualisiert wurden.

Sehen wir uns ein Beispiel an, in dem die Adapter verwendet werden, die von .NET Framework zu ASP.NET Core wechseln.

Pakete

  • Microsoft.AspNetCore.SystemWebAdapters: Dieses Paket wird in unterstützender Bibliotheken verwendet und stellt die System.Web-APIs bereit, von denen Sie möglicherweise abhängig sind, wie z. B. HttpContext und andere. Dieses Paket zielt auf .NET Standard 2.0, .NET Framework 4.5+ und .NET 5+.
  • Microsoft.AspNetCore.SystemWebAdapters.FrameworkServices: Dieses Paket zielt nur auf .NET Framework ab und soll Dienste für ASP.NET Framework-Anwendungen bereitstellen, die möglicherweise inkrementelle Migrationen bereitstellen müssen. Es wird in der Regel nicht erwartet, dass von Bibliotheken darauf verwiesen wird, sondern von den Anwendungen selbst.
  • Microsoft.AspNetCore.SystemWebAdapters.CoreServices: Dieses Paket zielt nur auf .NET 6+ ab und soll Dienste für ASP.NET Core-Anwendungen bereitstellen, um das Verhalten System.Web APIs zu konfigurieren und alle Verhaltensweisen für die inkrementelle Migration zu aktivieren. Es wird in der Regel nicht erwartet, dass von Bibliotheken darauf verwiesen wird, sondern von den Anwendungen selbst.
  • Microsoft.AspNetCore.SystemWebAdapters.Abstractions: Dieses Paket ist ein unterstützendes Paket, das Abstraktionen für Dienste bereitstellt, die sowohl von der ASP.NET Core- als auch ASP.NET Framework-Anwendung wie der Serialisierung des Sitzungszustands verwendet werden.

Konvertieren in System.Web.HttpContext

Wenn Sie zwischen den beiden Darstellungen von HttpContext konvertieren möchten, gehen Sie möglicherweise wie folgt vor:

For HttpContext bis HttpContext:

  • Implizite Umwandlung
  • HttpContext.AsSystemWeb()

Von HttpContext bis HttpContext

  • Implizite Umwandlung
  • HttpContext.AsAspNetCore()

Beide Methoden verwenden eine zwischengespeicherte HttpContext Darstellung für die Dauer einer Anforderung. Dies ermöglicht gezielte Umschreibungen, um HttpContext nach Bedarf ein.

Beispiel

ASP.NET Framework

Erwägen Sie einen Controller, der beispielsweise Folgendes ausführt:

public class SomeController : Controller
{
  public ActionResult Index()
  {
    SomeOtherClass.SomeMethod(HttpContext.Current);
  }
}

der dann Logik in einer separaten Assembly aufweist, die den HttpContext übergibt, bis schließlich eine innere Methode Logik darauf ausführt, z. B.:

public class Class2
{
  public bool PerformSomeCheck(HttpContext context)
  {
    return context.Request.Headers["SomeHeader"] == "ExpectedValue";
  }
}

ASP.NET Kern

Um die oben genannte Logik in ASP.NET Core auszuführen, muss ein Entwickler das Microsoft.AspNetCore.SystemWebAdapters Paket hinzufügen, das die Projekte auf beiden Plattformen funktionieren lässt.

Die Bibliotheken müssen aktualisiert werden, um die Adapter zu verstehen, aber es ist so einfach wie das Hinzufügen des Pakets und das erneute Kompilieren. Wenn dies die einzigen Abhängigkeiten sind, die ein System in System.Web.dll aufweist, können die Bibliotheken auf NET Standard 2.0 abzielen, um einen einfacheren Erstellungsprozess während der Migration zu ermöglichen.

Der Controller in ASP.NET Core sieht nun wie folgt aus:

public class SomeController : Controller
{
  [Route("/")]
  public IActionResult Index()
  {
    SomeOtherClass.SomeMethod(HttpContext);
  }
}

Beachten Sie, dass sie, da es eine HttpContext-Eigenschaft gibt, diese übergeben können, aber es sieht im Allgemeinen gleich aus. Mithilfe impliziter Konvertierungen kann der HttpContext in den Adapter konvertiert werden, der dann über die Ebenen übergeben werden kann, die den Code auf die gleiche Weise verwenden.

Komponententests

Bei Komponententests von Code, der die System.Web-Adapter verwendet, sind einige besondere Überlegungen zu beachten.

In den meisten Fällen ist es nicht erforderlich, zusätzliche Komponenten für die Ausführung von Tests einzurichten. Wenn die getestete Komponente jedoch HttpRuntime verwendet, kann es erforderlich sein, den SystemWebAdapters Dienst zu starten, wie im folgenden Beispiel gezeigt.

namespace TestProject1;

/// <summary>
/// This demonstrates an xUnit feature that ensures all tests
/// in classes marked with this collection are run sequentially.
/// </summary>
[CollectionDefinition(nameof(SystemWebAdaptersHostedTests),
    DisableParallelization = true)]
public class SystemWebAdaptersHostedTests
{
}
[Collection(nameof(SystemWebAdaptersHostedTests))]
public class RuntimeTests
{
    /// <summary>
    /// This method starts up a host in the background that
    /// makes it possible to initialize <see cref="HttpRuntime"/>
    /// and <see cref="HostingEnvironment"/> with values needed 
    /// for testing with the <paramref name="configure"/> option.
    /// </summary>
    /// <param name="configure">
    /// Configuration for the hosting and runtime options.
    /// </param>
    public static async Task<IDisposable> EnableRuntimeAsync(
        Action<SystemWebAdaptersOptions>? configure = null,
        CancellationToken token = default)
        => await new HostBuilder()
           .ConfigureWebHost(webBuilder =>
           {
               webBuilder
                   .UseTestServer()
                   .ConfigureServices(services =>
                   {
                       services.AddSystemWebAdapters();
                       if (configure is not null)
                       {
                           services.AddOptions
                               <SystemWebAdaptersOptions>()
                               .Configure(configure);
                       }
                   })
                   .Configure(app =>
                   {
                       // No need to configure pipeline for tests
                   });
           })
           .StartAsync(token);
    [Fact]
    public async Task RuntimeEnabled()
    {
        using (await EnableRuntimeAsync(options =>
            options.AppDomainAppPath = "path"))
        {
            Assert.True(HostingEnvironment.IsHosted);
            Assert.Equal("path", HttpRuntime.AppDomainAppPath);
        }
        Assert.False(HostingEnvironment.IsHosted);
    }
}

Die Tests müssen sequenziert und nicht parallel ausgeführt werden. Im vorherigen Beispiel wird veranschaulicht, wie Dies erreicht werden kann, indem die DisableParallelization Option XUnit auf true" festgelegt wird. Diese Einstellung deaktiviert die parallele Ausführung für eine bestimmte Testauflistung und stellt sicher, dass die Tests innerhalb dieser Auflistung nacheinander ausgeführt werden, ohne Parallelität.