Skip to content

MS_OWINMigrationSteps

nishi_74322014 edited this page Aug 21, 2026 · 1 revision

OWIN化手順

概要

目的

セルフホストや OWIN ミドルウェアを使用するために、パイプラインを OWIN 化する。

手順

  • ホスティング ランタイムをインストールする。
  • 利用したい、OWIN ミドルウェアをインストールする。
  • Startup クラスを追加して、OWIN 関連の設定を行う。

補足(この作業の位置付けと現在の意味): 本ページは
.NET Framework 上の既存 ASP.NET アプリを OWIN 化する手順である。

【なぜ OWIN 化するのか(当時の動機)】
 ① 【ASP.NET Identity を使いたい】
      → OWIN ミドルウェアとして作られているため、OWIN 化が前提
 ② 【SignalR を使いたい】
 ③ 【セルフホストしたい】(IIS なしで動かす)
 ④ 将来の ASP.NET Core への布石

現在の意味は主に ④ である。

【移行の段階】
   ① System.Web 直結の ASP.NET
        ↓ 本ページの作業
   ② OWIN 化した ASP.NET(IIS 上、Microsoft.Owin.Host.SystemWeb)
        ↓ パイプラインの考え方が同じになる
   ③ ASP.NET Core(Kestrel、ミドルウェア パイプライン)

① → ③ を一気に行うのは難しいため、
② を経由すると、認証まわりの構造がほぼそのまま移せる——
という点で、現在も意味のある中間ステップである
ASP.NET Coreへの移行)。

Startup.Configuration(IAppBuilder app)
ASP.NET Core の Program.cs / Startup.Configure(IApplicationBuilder app)
ほぼ同じ形
をしている。

// OWIN(.NET Framework)
public void Configuration(IAppBuilder app)
{
    app.UseCookieAuthentication(new CookieAuthenticationOptions { ... });
}

// ASP.NET Core
var app = builder.Build();
app.UseAuthentication();

詳細

ホスティング ランタイム

既存の Web アプリケーションは、IIS(System.Web)を使用しているため、
IIS でホストするための Microsoft.Owin.Host.SystemWeb を使用することになる。

IIS

  • IIS でホストするには、Microsoft.Owin.Host.SystemWeb を使用する。

  • NuGet で「Microsoft.Owin.Host.SystemWeb」をインストール。

    Install-package Microsoft.Owin.Host.SystemWeb
  • 必要に応じて、以下もインストールする。

    Install-Package Microsoft.Owin.ja
    Install-Package Microsoft.Owin.Host.SystemWeb.ja
  • System.Web のパイプラインを OWIN のパイプラインに流すことができる。

  • これにより、OWIN のミドルウェアを ASP.NET Web Forms や、MVC 5 でも使用できる。

補足(Microsoft.Owin.Host.SystemWeb の仕組み): このパッケージが
何をしているのかを知っておくと、トラブル時に役立つ。

【仕組み】
   このパッケージは、実体としては
   【HttpModule を 1 つ登録している】だけである

     IIS のパイプライン
       ├ … 各種 HttpModule
       ├ 【OwinHttpModule】 ← ここで OWIN パイプラインに流す
       │     └ Startup.Configuration で組んだミドルウェアを実行
       └ … HttpHandler(.aspx / MVC)

つまり、OWIN 化しても IIS/System.Web の上に載ったままである。

【できるようになること】
   ・OWIN ミドルウェアが使える(ASP.NET Identity 等)

【できないこと】
   ・IIS からの脱却(Windows 依存は残る)
   ・System.Web の除去(HttpContext.Current はまだ存在する)
   ・.NET Core での実行

HttpApplication / HttpModule との共存については
HttpApplication(Global.asax)、HttpModule、HttpHandler
を参照。実行順が問題になることがある

.ja パッケージは**リソース(メッセージの日本語化)**である。
例外メッセージやログが日本語になるだけで、機能は変わらない。
なお、リソースファイル で述べた通り、
例外メッセージを日本語化すると検索性が落ちるため、
開発者向けのメッセージは英語のままの方が良い場合が多い。

OwinHost.exe

  • Katana の OwinHost.exe でホストするには、OwinHost を使用する。

  • NuGet で「OwinHost」をインストール。

    install-package OwinHost

補足(Katana とは): Katana
Microsoft による OWIN の実装(ホストとミドルウェア群)の
プロジェクト名である。

種類 パッケージ 内容
IIS 上でホスト Microsoft.Owin.Host.SystemWeb 既存アプリの OWIN 化(本ページの主題)
セルフホスト(実行ファイル) Microsoft.Owin.SelfHost HttpListener で自前でホスト
OwinHost.exe OwinHost コマンドから起動する汎用ホスト
【セルフホストの意味】
   IIS を立てずに、コンソール アプリや Windows サービスとして
   Web API を動かせる
     → 開発時の起動が速い
     → テストが容易(プロセス内で立てて叩ける)
     → 【ASP.NET Core の Kestrel の先駆け】★

移行メモ(Katana の現況): Katana は開発停止しており、
ASP.NET Core に統合された
新規に「セルフホストしたい」なら、
ASP.NET Core を素直に使うのが正しい。

// ASP.NET Core:これだけでセルフホストになる(Kestrel)
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello");
app.Run();

OWIN ミドルウェアのインストール

NuGet で「AspNet.Identity」をインストール。

Install-Package Microsoft.AspNet.Identity.Owin
Install-Package Microsoft.AspNet.Identity.EntityFramework
Update-Package

Microsoft.AspNet.Identity.EntityFramework は、
UserStore クラスを自前で実装する場合、不要になる。

補足(UserStore を自前で実装する意味): 原文の
この一文は重要な設計上の選択を指している。

【ASP.NET Identity の構造】

   UserManager<TUser>          … 業務ロジック(パスワード検証、ロック等)
        │ 依存
        ▼
   IUserStore<TUser>           … 【永続化の抽象】★
        │ 実装
        ├ UserStore(EF 版)    … Microsoft.AspNet.Identity.EntityFramework
        └ 自前の UserStore      … Dapper、ADO.NET、既存の認証 DB

依存性反転原則
綺麗に適用されている例
であり、

・EF を使いたくない場合([Entity Framework の懸念] 参照)
・【既存の会員テーブルをそのまま使いたい】場合 ★ 実務ではこれが多い
・パスワードのハッシュ形式を既存に合わせたい場合

  → IUserStore(と必要な派生インターフェイス)を実装すれば済む
// 必要なものだけ実装すればよい(機能ごとにインターフェイスが分かれている)
public class MyUserStore :
    IUserStore<MyUser>,
    IUserPasswordStore<MyUser>,      // パスワード認証を使うなら
    IUserLockoutStore<MyUser, string>,   // ロックアウトを使うなら
    IUserTwoFactorStore<MyUser, string>  // 2 要素を使うなら
{ ... }

インターフェイス分離の原則の実例でもある
(使わない機能は実装しなくてよい)。

NuGet で「SignalR」をインストール。

Install-Package Microsoft.AspNet.SignalR
Update-Package

NuGet で「WebApi.OwinSelfHost」をインストール。
※ セルフホストの場合

Install-Package Microsoft.AspNet.WebApi.OwinSelfHost
Update-Package

OWIN Startupクラスの追加・登録

OWIN パイプラインでミドルウェアをつなげ全体を処理する。

Startup クラスは、

  • ホスティング ランタイムと
  • ミドルウェア

を指定して使用できるようにする。

補足(Startup クラスの検出方法): どうやって OWIN が
Startup を見つけるのか
は、はまりやすい点なので補っておく。

【検出の優先順位】
 ① Web.config / app.config の appSettings
      <add key="owin:AppStartup" value="MyApp.MyStartup" />
 ② OwinStartup 属性
      [assembly: OwinStartup(typeof(MyApp.MyStartup))]
 ③ 【規約による検出】
      名前空間 "Startup" または 型名 "Startup" のクラスで、
      void Configuration(IAppBuilder app) を持つもの
// ② の書き方(Startup.cs の先頭に置く)
[assembly: OwinStartup(typeof(MyApp.Startup))]
namespace MyApp
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app) { ... }
    }
}

典型的な障害:

・「アセンブリに OwinStartup 属性が見つかりません」
    → 規約にも合っていない。属性を付けるか、名前を Startup にする
・Startup が【2 つ見つかる】
    → 参照している別アセンブリにも Startup がある
    → appSettings の owin:AppStartup で明示する ★
・OWIN 自体を無効化したい
    → <add key="owin:AutomaticAppStartup" value="false" />

ASP.NET Core では、この検出の仕組みはなくなった
Program.cs で明示的に組み立てるため)。

共通

既存の Bundle、Routing 等を Global.asax.cs から OWIN Startup.cs に移動してもイイが、
必要性は無い。

補足(「移動しても良いが必要性はない」の理由): 原文の判断は
妥当である。理由を補う。

【Global.asax.cs(Application_Start)】
   ・System.Web が起動時に 1 回呼ぶ
   ・RouteConfig / BundleConfig / FilterConfig など
     【System.Web に属する設定】の置き場

【Startup.Configuration】
   ・OWIN パイプラインの構築
   ・【OWIN ミドルウェア】の登録

 → 責務が違う。無理に片方へ寄せる必要はない

ただし、寄せる利点もある

・起動時の処理が【1 箇所に集まる】ので読みやすい
・ASP.NET Core への移行時に、Startup に寄せておくと移しやすい ★
  (Core では Global.asax がないため、いずれ移すことになる)

ASP.NET MVC の Modernization では
実際に Startup へ寄せた例
が示されている
RouteConfig.RegisterRoutes 等を Configuration から呼んでいる)。
移行を見据えるなら、こちらの方が良い

Startup クラスで ConfigureAuth(app) メソッドを実行する。

public partial class Startup
{
  public void Configuration(IAppBuilder app)
  {
    ConfigureAuth(app);
    app.MapSignalR();
  }
}

ConfigureAuth メソッドはテンプレート上、Partial クラスに定義されている。

結構大きめの実装なので割愛

必要に応じて、実際に[認証の変更]→[個人のユーザアカウント]のオプションで
プロジェクトテンプレートを使用してプロジェクトを生成して確認すること。

補足(ConfigureAuth の中身の要点): 「割愛」とされている部分の
骨格だけ押さえておくと、ASP.NET Core との対応が見える。

// App_Start/Startup.Auth.cs(テンプレートが生成する)
public partial class Startup
{
    public void ConfigureAuth(IAppBuilder app)
    {
        // ① DI 的な登録(リクエストごとに 1 インスタンス)
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

        // ② Cookie 認証ミドルウェア
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            ExpireTimeSpan = TimeSpan.FromMinutes(30),
        });

        // ③ 二要素・外部ログイン用の一時 Cookie
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        // ④ 外部プロバイダー
        // app.UseGoogleAuthentication(...);
        // app.UseMicrosoftAccountAuthentication(...);
    }
}

ASP.NET Core との対応:

OWIN(.NET Framework) ASP.NET Core
app.CreatePerOwinContext<T> services.AddScoped<T>()(標準の DI)★
app.UseCookieAuthentication services.AddAuthentication().AddCookie() + app.UseAuthentication()
app.UseExternalSignInCookie AddCookie(IdentityConstants.ExternalScheme)
app.UseGoogleAuthentication .AddGoogle(options => ...)

CreatePerOwinContext は「OWIN 版の DI」であり、
Core では標準の DI コンテナに置き換わった
.NET Core における DI)。
ここが移行時に最も書き換えが必要な箇所
である。

Startup クラスで app.MapSignalR() メソッドを実行する。

public partial class Startup
{
  public void Configuration(IAppBuilder app)
  {
    ConfigureAuth(app);
    app.MapSignalR();
  }
}

Startup クラスで Routing 定義を行い app.UseWebApi() メソッドを実行する。
※ セルフホストの場合

public static class Startup
 {
   public static void ConfigureApp(IAppBuilder app)
   {
     // Configure Web API for self-host. 
     HttpConfiguration config = new HttpConfiguration();

     config.Routes.MapHttpRoute(
      name: "DefaultApi",
      routeTemplate: "api/{controller}/{id}",
      defaults: new { id = RouteParameter.Optional }
    );

    app.UseWebApi(config);
  }
}

.NET Framework のテンプレートでは、Routing 定義は、
Global.aspx の Application_Start から呼びだされる
RouteConfig クラスの RegisterRoutes メソッドで実行されれている。

移行メモ(原文の記述の細部): 最終段落の
Global.aspx」は Global.asax が正しい
.aspx はページ、.asax がアプリケーション ファイル)。

また、Web API の場合、Routing 定義を行うのは
RouteConfig.RegisterRoutes ではなく
WebApiConfig.Register である
App_Start/WebApiConfig.cs)。

// .NET Framework のテンプレート(IIS ホスト時)
public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional });
    }
}
// Global.asax.cs から
GlobalConfiguration.Configure(WebApiConfig.Register);

ASP.NET MVC の Modernization
Startup の例では、これを Configuration から呼んでいる

WebApiConfig.Register(GlobalConfiguration.Configuration))。

補足(サンプルの ConfigureApp という名前): OWIN の規約で
検出されるメソッド名は Configuration である。
このサンプルが ConfigureApp なのは、
セルフホスト時に WebApp.Start<Startup>() から
明示的に呼ぶ
形を想定しているためと読める。

// セルフホストの起動
using (WebApp.Start<Startup>("http://localhost:8080/"))
{
    Console.WriteLine("started");
    Console.ReadLine();
}

この形ならメソッド名は Configuration である必要がある。
名前を変えるなら、起動側で明示的に呼ぶ。

参考

OWIN ミドルウェア

手順

Microsoft Learn


Tags: 移行, .NET開発, OWIN

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally