normalian blog

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

RoleEnvironment.IsAvailable と RoleEnvironment.IsEmulated を利用する

今年も C# Advent Calendar が開始された。今後、 C# Advent Calendar 2011 に内容がまとまる予定であるため、是非参照頂きたい。一番手である私は、Windows Azure開発で利用できる簡単なTIPSを紹介する。

RoleEnvironment.IsAvailable, RoleEnvironment.IsEmulated とは?

Windows AzureSDK内部には Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment というクラスが存在し、同クラスでは実行中インスタンスの設定/エンドポイント/状態に関する情報を提供する。RoleEnvironmentクラスに存在する RoleEnvironment.IsEmulated プロパティ と RoleEnvironment.IsAvailable プロパティの概要は以下となるが、今回はこちらについて紹介する。

  • RoleEnvironment.IsAvailable … Windows Azure 環境が利用可能か否かを取得(Compute Emulator、ホスティッドサービス上で動いてる場合は True。Testing Framework、オンプレミスIIS上ではFalse)
  • RoleEnvironment.IsEmulated … インスタンスが Compute Emulater 上で動いているか否かを取得

各環境でのプロパティ値取得結果は以下となる。

プロパティ名 コンソールアプリ/Testing Framework/オンプレミスIIS Compute Emulator ホスティッドサービス
RoleEnvironment.IsAvailable false true true
RoleEnvironment.IsEmulated SEHException例外が発生 true false

Windows Azure 環境が有効でない場合に RoleEnvironment.IsEmulated を参照すると、なぜかSEHException例外が発生する仕様になっている(どうせならここでも false を返して欲しかった)。。。

ASP.NET MVCを利用したサンプルコード

ASP.NET MVC をWebロールとしてもつWindows Azure アプリケーションを利用して、今回紹介した2プロパティ値を参照する。まず、当該Windows Azureアプリケーションを作成し、以下のサンプルコードを参考にして作成したアプリケーションを修正する。
コントローラ側で ViewBag に値を設定し、ビュー側で値を表示している。Testing Framework等で利用する場合を考慮し、RoleEnvironment.IsEmulated プロパティは RoleEnvironment.IsAvailable プロパティがTrueの場合だけ参照している。

  • HomeController.cs
using System.Web.Mvc;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace MvcWebRole1.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Modify this template to kick-start your ASP.NET MVC application.";
            ViewBag.IsAvailable = RoleEnvironment.IsAvailable;

            if (RoleEnvironment.IsAvailable == true)
            {
                //RoleEnvironment.IsAvailable == true の状況で呼び出さないとSEHExceptionが発生する
                ViewBag.IsEmulated = RoleEnvironment.IsEmulated;
            }

            return View();
        }
        //(中略)
    }
  • Index.cshtml
@{
    ViewBag.Title = "Home Page";
}

@section featured {
<section class="featured">
    <div class="content-wrapper">
        <hgroup class="title">
            <h1>@ViewBag.Title.</h1>
            <h2>@ViewBag.Message</h2>
        </hgroup>
        <p>
            To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>. 
            The page features <span class="highlight">videos, tutorials, and samples</span> to help you get the most from 
            ASP.NET MVC. If you have any questions about ASP.NET MVC visit 
            <a href="http://forums.asp.net/1146.aspx/1?MVC" title="ASP.NET MVC Forum">our forums</a>.
        </p>
    </div>
</section>
}

<h2>IsAvailable = @ViewBag.IsAvailable</h2>
<h2>IsEmulated = @ViewBag.IsEmulated</h2>

以下、省略

こちらのサンプルコードの実行結果は以下となる。「Compute Emulator上で実行する場合」と「ホスティッドサービス上で実行する場合」で RoleEnvironment.IsEmulated プロパティ値が異なるのが理解できるだろう。

Testing Framework を利用したサンプルコード

次に、作成したサンプルコードを Testing Frameworkから参照する(TDD的には順番が逆なのだが、今回はプロパティの用途紹介なのでご容赦願いたい)。次の画像例を参考に、HomeController.cs ファイル上で右クリックを押下して「単体テスト作成(C)...」を選択し、単体テストプロジェクトを作成する。

次に、以下の様に単体テストのコードを修正する。テスト環境では RoleEnvironment.IsAvailable が false となることを確認する。HomeController.Index()は、RoleEnvironment.IsAvailable = false の場合に RoleEnvironment.IsEmulated が参照されないため、必要ならば別途テストメソッドを作成して頂きたい(SEHException例外が発生するため、テストメソッドを分けるべきだと考えられる)。

  • HomeControllerTest.cs
    [TestClass()]
    public class HomeControllerTest
    {
        //(中略)
        
        /// <summary>
        ///Index のテスト
        ///</summary>
        [TestMethod()]
        public void IndexTest()
        {
            //初期値の設定
            HomeController target = new HomeController();
            ViewResult actual;
            ViewResult expected = new ViewResult();
            expected.ViewBag.IsAvailable = false;

            //テスト対象メソッドを実行
            actual = target.Index() as ViewResult;

            //テスト環境では RoleEnvironment.IsAvailable == false
            Assert.AreEqual(expected.ViewBag.IsAvailable, actual.ViewBag.IsAvailable);
        }
    }

上記のテストメソッドの実行結果は以下となる。