normalian blog

Let's talk about Microsoft Azure, ASP.NET and Java!

ASP.NET MVC4 の Web API を学んでみる その5 〜Self Host編〜

その1〜その4 では、ASP.NET ランタイム上で ASP.NET Web API を動作するいくつかのTIPS方法を紹介した。今回は、Self-Host と呼ばれる機能を利用して、ASP.NET ランタイム上でなく .NET Framework 上で直に ASP.NET Web API を動作させる方法を紹介する。
様々な用途が存在すると思われるが、今回紹介する方法を利用すれば、Windows Azure 上で Web Role を利用せず、 Worker Role のみを利用して容易に公開 Web API を構築することが可能だと思われる(未検証)。

ASP.NET Web API の Self-Host アプリ作成の流れ

Self-Host の ASP.NET Web API アプリケーションを作成する手順は以下となる。

  1. 「コンソールアプリケーション」ソリューションの新規作成
  2. NuGet を利用し、「Microsoft ASP.NET Web API Self」をインストール
  3. 「System.Web」に対する参照の追加
  4. 「Web API コントローラークラス」の新規作成
  5. Program.cs に対し、ASP.NET Web API を公開する処理を記載

ASP.NET Web API の Self-Host アプリを作成する

まず、Visual Studio"管理者権限"で起動し、メニューから「コンソールアプリケーション」を新規に作成する(サンプルは WebApiConsoleApp をソリューション名とした)。

次に、「ソリューション エクスプローラ」を右クリックし、メニューから「NuGet パッケージの管理」を選択してパッケージ管理のウィザードを起動する。

左側のメニューから「オンライン」を選択し、右上の検索ボックスに「SelfHost」を入力し、検索結果から次の画像に従って「Microsoft ASP.NET Web API Self」をインストールする。

更に「ソリューションエクスプローラ」の「参照設定」を右クリックし、次の画像に従って「System.Web」の参照設定を追加する。

参照設定完了後、プロジェクトに「Controllers」フォルダを作成し、同フォルダ以下に「Web API コントローラークラス」を新規に作成する。特に生成内容からの変更はしていないが(using の整理のみ実施)、ソースコードは以下となる。

using System.Collections.Generic;
using System.Web.Http;

namespace WebApiConsoleApp.Controllers
{
    public class ValuesController : ApiController
    {
        // GET api/<controller>
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

        // GET api/<controller>/5
        public string Get(int id)
        {
            return "value";
        }

        // POST api/<controller>
        public void Post([FromBody]string value)
        {
        }

        // PUT api/<controller>/5
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE api/<controller>/5
        public void Delete(int id)
        {
        }
    }
}

最後に、Self-Host として公開する処理を Program.cs に記載する。System.Web.Http.SelfHost.HttpSelfHostServer クラスを利用することで、プログラム内で設定したルーティング情報に従って ASP.NET Web API 可能だ。

using System;
using System.Web.Http;
using System.Web.Http.SelfHost;

namespace WebApiConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var config = new HttpSelfHostConfiguration("http://localhost:8080");

            config.Routes.MapHttpRoute(
                "API Default", "api/{controller}/{id}",
                new { id = RouteParameter.Optional });

            using (HttpSelfHostServer server = new HttpSelfHostServer(config))
            {
                server.OpenAsync().Wait();
                Console.WriteLine("Press Enter to quit.");
                Console.ReadLine();
            }
        }
    }
}

サンプルアプリケーションの実行

最後にサンプルアプリケーションを実行する。Visual Studio 上から F5 を押下することで実行可能だが、冒頭で記載した通り 管理者権限 が必要な点に注意してほしい。アプリケーション起動後、Programs.cs 内に記載した URL である http://localhost:8080 にブラウザからアクセスすることで、以下のレスポンスを取得できる。

また、Visual Studio を管理者権限で実行しない場合、以下の例外が発生する。

System.AggregateException はハンドルされませんでした。
  StackTrace:
       場所 System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
       場所 System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
       場所 System.Threading.Tasks.Task.Wait()
       場所 WebApiConsoleApp.Program.Main(String[] args) 場所 c:\my_program\CSharp\WebApiConsoleApp\WebApiConsoleApp\Program.cs:行 19
       場所 System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       場所 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       場所 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       場所 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       場所 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       場所 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       場所 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       場所 System.Threading.ThreadHelper.ThreadStart()
  InnerException: System.ServiceModel.AddressAccessDeniedException
       HResult=-2146233087
       Message=HTTP が URL http://+:8080/ を登録できませんでした。プロセスにこの名前空間へのアクセス権がありません (詳細については、http://go.microsoft.com/fwlink/?LinkId=70353 (英語ページの可能性があります) を参照してください)。