VB.NETでのWebアプリケーション開発で、「依存性の注入(DI)」を実現するためにAutofacを導入しようとして、MVCとWeb APIの両方で動かすのに苦労した経験を元に、調べて実践した内容をまとめました。
1. Autofacとは何か? なぜDIが必要なのか?
Autofacは、.NETで非常に人気のある「DIコンテナ」ライブラリの一つです。
DI(Dependency Injection / 依存性の注入)とは、クラスが必要とする別のクラス(依存オブジェクト)を、自分自身で生成するのではなく、外部から与えてもらう(注入してもらう)という設計原則です。
DIがない世界の問題点
Public Class MyController
Private ReadOnly _myService As MyService
Public Sub New()
' コントローラーが自分でサービスを生成している(密結合)
_myService = New MyService()
End Sub
End Class
上記の方法だと、MyServiceの仕様が変わるたびにMyControllerも修正が必要になり、テストもしにくくなります。
DIがある世界(Autofac利用)のメリット
Public Class MyController
Private ReadOnly _myService As IMyService
' コンストラクタで外部から注入してもらう(疎結合)
Public Sub New(ByVal service As IMyService)
_myService = service
End Sub
End Class
AutofacのようなDIコンテナが、IMyServiceというインターフェースに対して、どのクラス(例: MyService)のインスタンスを渡すかを管理してくれます。
これにより、クラス間の結びつきが緩やか(疎結合)になり、変更に強く、テストしやすいコードを書くことができます。
2. MVCとWeb APIでAutofacを共存させる
ASP.NET MVCプロジェクトでAPIも使いたい場合、ControllerとApiControllerの両方でDIを機能させる必要があります。そのために必要なのが、以下の2つのパッケージです。
- Autofac.Mvc5: MVCコントローラー用
- Autofac.WebApi2: Web APIコントローラー用
「WebApi5じゃなくてWebApi2でいいの?」と不安になりますが、これで正解です。
これはASP.NET Web APIのバージョンに基づいた命名規則であり、現在の環境でも問題なく動作します。
3. OWIN環境とは? なぜAutofac設定に必要なのか?
当初、私はGlobal.asaxのApplication_StartにAutofacの設定を書いていました。しかし、これだとWeb APIの設定でキャストエラーが発生します。この問題を解決する鍵がOWINでした。
OWIN (Open Web Interface for .NET) とは、一言でいうと.NETのWebサーバーとWebアプリケーションを分離するための「標準ルール」です。
OWIN環境では、リクエストからレスポンスまでの一連の処理を「パイプライン」として構築し、その処理一つ一つを「ミドルウェア」として追加していきます。
MVCとWeb APIは元々、独立した仕組みで動いていました。OWINパイプラインを使うことで、それらの処理が始まるより前の段階でAutofacのミドルウェアを組み込むことができます。これにより、両者でDIの管理方法が統一され、スムーズな連携が実現できるのです。
4. OWIN連携によるAutofacの設定手順
ここからは具体的な実装手順です。Global.asaxでの設定はやめ、OWINのStartupクラスにDI設定を集約します。
Step 1: 必要なNuGetパッケージをインストール
OWIN連携に必要なパッケージをすべてインストールします。Microsoft.Owin.Host.SystemWebは、IIS上でOWINを動かすための重要な「アダプター」です。
Install-Package Autofac.Mvc5.Owin
Install-Package Autofac.WebApi2.Owin
Install-Package Microsoft.Owin.Host.SystemWeb
Step 2: DIコンテナの構築処理を分離 (AutofacConfig.vb)
App_Startフォルダに、DIコンテナの登録ルールを記述するモジュールを作成します。
' App_Start/AutofacConfig.vb
Imports Autofac
Imports System.Web.Http
Imports System.Reflection
Imports Autofac.Integration.Mvc
Imports Autofac.Integration.WebApi
Public Module AutofacConfig
Public Function Initialize(ByVal config As HttpConfiguration) As IContainer
Dim builder = New ContainerBuilder()
Dim executingAssembly = Assembly.GetExecutingAssembly()
'MVCコントローラーを登録
builder.RegisterControllers(executingAssembly)
'Web APIコントローラーを登録
builder.RegisterApiControllers(executingAssembly)
'Web APIのフィルタープロバイダーを登録
builder.RegisterWebApiFilterProvider(config)
' ... (DbContext、リポジトリ、サービスの登録) ...
builder.RegisterType(Of ApplicationDbContext)().InstancePerRequest()
builder.RegisterType(Of MyRepository)().As(Of IMyRepository)().InstancePerRequest()
builder.RegisterType(Of MyService)().As(Of IMyService)().InstancePerRequest()
' ...
'コンテナをビルドして返す
Return builder.Build()
End Function
End Module
Step 3: OWINパイプラインを構築 (Startup.vb)
App_StartフォルダにStartup.vbを作成し、アプリケーション起動時の処理を記述します。
' App_Start/Startup.vb
Imports Microsoft.Owin
Imports Microsoft.Owin
Imports Owin
Imports System.Web.Mvc
Imports System.Web.Http
Imports Autofac
Imports Autofac.Integration.Mvc
Imports Autofac.Integration.WebApi
' このアセンブリ属性は必須です。OWINがこのクラスを起動時に呼び出すための目印になります。
<Assembly: OwinStartup(GetType(YourNamespace.Startup))>
Namespace YourNamespace ' ← ご自身のプロジェクトの名前空間に必ず変更してください
Public Class Startup
Public Sub Configuration(ByVal app As IAppBuilder)
' 1. Web API用のHttpConfigurationを新規作成
Dim config = New HttpConfiguration()
' 2. AutofacConfigを呼び出してDIコンテナを構築・取得
Dim container = AutofacConfig.Initialize(config)
' 3. OWINパイプラインにAutofacのコア機能を登録(最重要)
' リクエストごとにDIの生存期間(スコープ)が作られるようになります。
app.UseAutofacMiddleware(container)
' 4. MVC用の設定
' MVCの依存関係解決をAutofacに委譲します。
DependencyResolver.SetResolver(New AutofacDependencyResolver(container))
' MVCの処理をOWINパイプラインに統合します。
app.UseAutofacMvc()
' 5. Web API用の設定
' Web APIの依存関係解決をAutofacに委譲します。
config.DependencyResolver = New AutofacWebApiDependencyResolver(container)
' Web APIのルート設定などを読み込みます。
WebApiConfig.Register(config)
' Web APIの処理をOWINパイプラインに統合します。
app.UseAutofacWebApi(config)
app.UseWebApi(config)
End Sub
End Class
End Namespace
5. ハマりどころとエラー解消法
エラー1:「引数なしコンストラクターは定義されていません」
このエラーが出たら、OWINの起動プロセスが失敗していることを疑ってください。
- 解決策① パッケージの確認 : Microsoft.Owin.Host.SystemWeb パッケージはインストールされていますか? これがないとStartup.vbが呼び出されません。
- 解決策② 属性の確認 : Startup.vb の先頭にある 属性の名前空間は正しいですか? クラスの名前空間と完全に一致している必要があります。
- 解決策③ デバッグ実行 : Startup.Configuration メソッドにブレークポイントを置き、起動時に処理が止まるか確認しましょう。もし止まらなければ、原因は①か②です。
エラー2:カスタムエラーページに飛ばされて真の原因がわからない
DIの設定ミスで実行時エラーが発生しているのに、カスタムエラーページが表示されて詳細がわからないケースです。
- 解決策 : Web.config の タグの mode を一時的に "Off" に変更します。これで開発者向けの詳しいエラー画面(通称:Yellow Screen of Death)が表示され、「どのサービスの登録が漏れているか」といった根本原因を特定できます。エラーが解決したら、modeは忘れずに元に戻しましょう。
まとめ
VB.NET MVCとWeb APIが共存するプロジェクトでAutofacを導入する際は、OWIN連携が成功の鍵となることが分かりました。上記の方法で構築すれば、クリーンで保守性の高いコードを書くことができるようになります。