Sdílet prostřednictvím


System.Web adaptéry

Hlavním případem použití adaptérů v úložišti dotnet/systemweb-adapters je pomoct vývojářům, kteří se spoléhali na System.Web typy v knihovnách tříd, když chtějí přejít na ASP.NET Core.

Důležitou funkcí adaptérů jsou adaptéry, které umožňují knihovnu používat z projektů ASP.NET Framework i ASP.NET Core. Aktualizace více aplikací ASP.NET Framework na ASP.NET Core často zahrnuje přechodné stavy, kdy nebyly všechny aplikace plně aktualizovány. Pomocí System.Web adaptérů lze knihovnu použít jak pro volající z ASP.NET Core, tak pro volající, kteří používají rozhraní ASP.NET Framework a kteří nebyli upgradováni.

Podívejme se na příklad s použitím adaptérů, které se přesouvají z rozhraní .NET Framework na ASP.NET Core.

Balíčky

  • Microsoft.AspNetCore.SystemWebAdapters: Tento balíček je používán v podpůrných knihovnách a poskytuje rozhraní System.Web API, na které jste mohli být závislí, jako HttpContext a další. Tento balíček cílí na .NET Standard 2.0, .NET Framework 4.5 nebo novější a .NET 5+.
  • Microsoft.AspNetCore.SystemWebAdapters.FrameworkServices: Tento balíček cílí pouze na rozhraní .NET Framework a je určen k poskytování služeb aplikacím ASP.NET Framework, které mohou potřebovat poskytovat přírůstkové migrace. Obecně se neočekává, že se na ně odkazuje z knihoven, ale spíše z samotných aplikací.
  • Microsoft.AspNetCore.SystemWebAdapters.CoreServices: Tento balíček cílí pouze na .NET 6 nebo novější a je určený k poskytování služeb pro ASP.NET Core aplikace, aby nakonfigurovala chování rozhraní API System.Web a umožnila zapnout jakékoli chování pro přírůstkovou migraci. Obecně se neočekává, že se na ně odkazuje z knihoven, ale spíše z samotných aplikací.
  • Microsoft.AspNetCore.SystemWebAdapters.Abstractions: Tento balíček je podpůrný balíček, který poskytuje abstrakce pro služby používané aplikací ASP.NET Core i ASP.NET Framework, jako je serializace stavu relace.

Převod na System.Web.HttpContext

Chcete-li převést mezi dvěma reprezentacemi HttpContext, můžete provést následující:

Pro HttpContextHttpContext

  • Implicitní přetypování
  • HttpContext.AsSystemWeb()

Pro HttpContextHttpContext

  • Implicitní přetypování
  • HttpContext.AsAspNetCore()

Obě tyto metody po dobu trvání požadavku použijí reprezentaci uloženou HttpContext v mezipaměti. To umožňuje cílené přepsání HttpContext podle potřeby.

Příklad

ASP.NET Framework

Vezměte v úvahu kontroler, který dělá něco jako:

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

která pak má logiku v samostatném sestavení, které HttpContext se předává, a nakonec na něm některé vnitřní metody provádějí operace, například:

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

ASP.NET Core

Aby bylo možné spustit výše uvedenou logiku v ASP.NET Core, vývojář bude muset přidat Microsoft.AspNetCore.SystemWebAdapters balíček, který umožní projektům pracovat na obou platformách.

Knihovny je potřeba aktualizovat, aby porozuměly adaptérům, ale bude to jednoduché, jako je přidání balíčku a rekompilování. Pokud jsou to jediné závislosti, které systém má na System.Web.dll, pak knihovny budou moci cílit na .NET Standard 2.0 a usnadnit proces sestavování během migrace.

Kontroler v ASP.NET Core teď bude vypadat takto:

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

Všimněte si, že jelikož existuje vlastnost HttpContext, mohou ji procházet, ale obecně vypadá stejně. Pomocí implicitních převodů je možné ho HttpContext převést na adaptér, který se pak dá předat přes úrovně využívající kód stejným způsobem.

Jednotkové testování

Při testování jednotek, který používá adaptéry System.Web, je potřeba vzít v úvahu některé zvláštní aspekty.

Ve většině případů není nutné pro spouštění testů nastavovat další komponenty. Pokud ale testovaná komponenta používá HttpRuntime, může být nutné spustit SystemWebAdapters službu, jak je znázorněno v následujícím příkladu:

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

Testy se musí spouštět postupně, ne paralelně. Předchozí příklad ukazuje, jak toho dosáhnout nastavením možnosti XUnit DisableParallelization na true. Toto nastavení zakáže paralelní spouštění pro konkrétní kolekci testů a zajišťuje, aby testy v této kolekci běžely jeden po druhém bez souběžnosti.