次の方法で共有


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: このパッケージは、サポート ライブラリで使用され、 HttpContext などの依存関係を取得した可能性がある System.Web API を提供します。 このパッケージは、.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 以降のみを対象としており、System.Web API の動作を構成したり、増分移行の動作を選択したりするために、ASP.NET Core アプリケーションにサービスを提供することを目的としています。 通常、これはライブラリからではなく、アプリケーション自体から参照されることが想定されています。
  • Microsoft.AspNetCore.SystemWebAdapters.Abstractions: このパッケージは、ASP.NET Core とセッション状態のシリアル化などの ASP.NET Framework アプリケーションの両方で使用されるサービスの抽象化を提供するサポート パッケージです。

System.Web.HttpContext への変換

HttpContext の 2 つの表現間で変換するには、次の操作を行います。

HttpContextからHttpContext

  • 暗黙的キャスト
  • HttpContext.AsSystemWeb()

HttpContextからHttpContextまで

  • 暗黙的キャスト
  • HttpContext.AsAspNetCore()

どちらの方法でも、要求の期間中、キャッシュされた HttpContext 表現が使用されます。 これにより、必要に応じて、HttpContext の書き換えを対象にすることができます。

ASP.NET フレームワーク

次のような処理を行うコントローラーを考えてみましょう。

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

テストは並列ではなく順番に実行する必要があります。 前の例では、true に設定してこれを実現する方法を示します。 この設定により、特定のテスト コレクションに対する並列実行が無効になります。これにより、そのコレクション内のテストがコンカレンシーなしで 1 つずつ実行されるようになります。