다음을 통해 공유


System.Web 어댑터

dotnet/systemweb-adapters 리포지토리에 있는 어댑터의 주요 사용 사례는 ASP.NET Core로 이동하려는 클래스 라이브러리 내의 형식에 System.Web 의존해 온 개발자를 돕는 것입니다.

어댑터의 중요한 기능은 어댑터를 통해 ASP.NET Framework 및 ASP.NET Core 프로젝트에서 라이브러리를 사용할 수 있다는 것입니다. 여러 ASP.NET Framework 앱을 ASP.NET Core로 업데이트하는 경우 일부 앱이 완전히 업데이트되지 않은 중간 상태가 포함되는 경우가 많습니다. 어댑터를 사용하면 System.Web ASP.NET Core 호출자와 업그레이드되지 않은 ASP.NET Framework 호출자 모두에서 라이브러리를 사용할 수 있습니다.

.NET Framework에서 ASP.NET Core로 이동하는 어댑터를 사용하는 예제를 살펴보겠습니다.

패키지

  • Microsoft.AspNetCore.SystemWebAdapters: 이 패키지는 라이브러리를 지원하는 데 사용되며 종속성을 가질 수 있는 System.Web API(예: HttpContext 기타)를 제공합니다. 이 패키지는 .NET Standard 2.0, .NET Framework 4.5 이상 및 .NET 5+를 대상으로 합니다.
  • Microsoft.AspNetCore.SystemWebAdapters.FrameworkServices: 이 패키지는 .NET Framework만 대상으로 하며 증분 마이그레이션을 제공해야 할 수 있는 ASP.NET Framework 애플리케이션에 서비스를 제공하기 위한 것입니다. 이는 일반적으로 라이브러리에서 참조되는 것이 아니라 애플리케이션 자체에서 참조될 것으로 예상됩니다.
  • Microsoft.AspNetCore.SystemWebAdapters.CoreServices: 이 패키지는 .NET 6 이상만 대상으로 하며 ASP.NET Core 애플리케이션에 서비스를 제공하여 증분 마이그레이션에 대한 동작을 선택할 뿐만 아니라 System.Web API의 동작을 구성하기 위한 것입니다. 이는 일반적으로 라이브러리에서 참조되는 것이 아니라 애플리케이션 자체에서 참조될 것으로 예상됩니다.
  • Microsoft.AspNetCore.SystemWebAdapters.Abstractions: 이 패키지는 세션 상태 serialization과 같은 ASP.NET Core 및 ASP.NET Framework 애플리케이션에서 사용하는 서비스에 대한 추상화를 제공하는 지원 패키지입니다.

System.Web.HttpContext로 변환

HttpContext의 두 표현 간에 변환하려면 다음을 수행할 수 있습니다.

HttpContext에서 HttpContext

  • 암시적 캐스팅
  • HttpContext.AsSystemWeb()

HttpContext에서 HttpContext까지

  • 암시적 캐스팅
  • HttpContext.AsAspNetCore()

이러한 두 메서드는 모두 요청 기간 동안 캐시된 HttpContext 표현을 사용합니다. 이렇게 하면 필요에 따라 HttpContext 대상 재작성을 수행할 수 있습니다.

예시

ASP.NET Framework

다음과 같은 작업을 수행하는 컨트롤러를 고려합니다.

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

다음으로, 별도의 어셈블리에 포함된 논리가 HttpContext을(를) 주위로 전달하여, 마침내 일부 내부 메서드가 다음과 같은 몇 가지 논리를 수행합니다.

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

ASP.NET Core

ASP.NET Core에서 위의 논리를 실행하려면 개발자가 패키지를 추가 Microsoft.AspNetCore.SystemWebAdapters 해야 합니다. 그러면 프로젝트가 두 플랫폼에서 모두 작동할 수 있습니다.

어댑터를 이해하려면 라이브러리를 업데이트해야 하지만 패키지를 추가하고 다시 컴파일하는 것만큼 간단합니다. 이러한 종속성이 시스템에 System.Web.dll있는 유일한 종속성인 경우 라이브러리는 마이그레이션하는 동안 더 간단한 빌드 프로세스를 용이하게 하기 위해 .NET Standard 2.0 을 대상으로 할 수 있습니다.

이제 ASP.NET Core의 컨트롤러는 다음과 같이 표시됩니다.

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

속성이 있기 때문에 HttpContext 이를 통과할 수 있지만, 대체로 동일하게 보입니다. 암시적 변환을 HttpContext 사용하여 어댑터로 변환할 수 있으며, 이 어댑터는 동일한 방식으로 코드를 활용하는 수준을 통해 전달될 수 있습니다.

단위 테스트

System.Web 어댑터를 사용하는 코드를 단위 테스트할 때 유의해야 할 몇 가지 특별한 고려 사항이 있습니다.

대부분의 경우 테스트를 실행하기 위해 추가 구성 요소를 설정할 필요가 없습니다. 테스트 중인 구성 요소가 HttpRuntime을 사용하는 경우, 다음 예제와 같이 SystemWebAdapters 서비스를 시작해야 할 수도 있습니다.

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

테스트는 병렬이 아닌 순서대로 실행해야 합니다. 앞의 예제에서는 XUnit의 DisableParallelization 옵션을true으로 설정하여 이를 달성하는 방법을 보여 줍니다. 이 설정은 특정 테스트 컬렉션에 대해 병렬 실행을 사용하지 않도록 설정하여 해당 컬렉션 내의 테스트가 동시성 없이 하나씩 실행되도록 합니다.