先日グレープシティでは、以下の製品の運用環境のサポート対象に「Windows Server 2016 Server Core オプション」(以下Server Core)を追加しました。
- ActiveReports for .NET 12.0J
- SPREAD for ASP.NET 10.0J
- InuputManPlus for ASP.NET 10.0J
- ComponentOne ASP.NET Web Forms/MVC
本記事ではServer Coreの環境をAzure VM上に作成して、Visual Studio 2017で作成したASP.NET MVCアプリを配布および動作させる方法について紹介してみたいと思います。
このアプリではComponentOneのFlexGrid for ASP.NET MVCを使っています。
Server Coreとは?
Server Coreについてわかりやすく簡潔に説明されているのがこちらの記事です。
「Server Core」とは、Windows Server OSからGUI関連のコンポーネントを省いて軽量化したWindows OSのインストール形態であり、Windows Server 2008から導入された機能である。不要なコンポーネントのインストールを省略することにより、必要なメモリやディスク領域を節約できるだけでなく(「フルインストール」と比較すると、必要なディスク領域は4Gbytes程度少なくなる)、脆弱性や管理ツールなどを狙ったシステムへの侵入の危険性を抑制できる。また機能が限定されている分、Windowsコンポーネントの更新(Windows Update)の必要性も少なくなるし、更新作業に伴う再起動などのダウンタイムも縮めることができる。
Server Coreに関するマイクロソフトの公式ドキュメントはこちらです。
要するにクラウドやコンテナで利用するのにピッタリなインストール方法ってことですね!
Azure VMの作成
ではさっそくAzure VMにServer Coreのイメージを準備していきます。[smalldisk] Windows Server 2016 Datacenter - Server Core
を選択して作成します。
リモートデスクトップ接続でサーバーの機能を追加するので[パブリック受信ポート]にRDP (3389)
を追加しておきます。
作成後にリモートデスクトップ接続して確認してみます。ログイン出来たら成功です!
Server Coreの機能追加
作成したServer CoreにASP.NET Webアプリを配布して動作させるのに必要な機能をインストールします。起動しているコマンドプロンプトからPowerShellを実行して以下を参考に、IIS、ASP.NET 4.6、Web Management Service、WebDeploy 3.6をインストールします。
IIS
ASP.NET4.6
Web Management Service
Web Deploy 3.6
Azure VMの設定追加
以下を参考にAzure VMのネットワークとDNS名を設定します。
Configure firewall rules in Azure
HTTPとWebDeployのポート設定
DNS名の設定
これでServer Coreの準備は完了です!
ASP.NET MVCアプリの作成
以下を参考にFlexGridでデータを表示するASP.NET MVCアプリを作成します。
まず、ModelsフォルダにSale
クラスを追加します。
Sale.cs
public class Sale { public int ID { get; set; } public DateTime 開始日 { get; set; } public DateTime 終了日 { get; set; } public string 国名 { get; set; } public string 製品名 { get; set; } public string 色 { get; set; } public double 金額 { get; set; } public double 金額2 { get; set; } public double 割引 { get; set; } public bool アクティブ { get; set; } public MonthData[] 傾向 { get; set; } public int ランク { get; set; } /// <summary> /// データを取得 /// </summary> /// <param name="total"></param> /// <returns></returns> public static IEnumerable<Sale> GetData(int total) { var countries = new[] { "米国", "イギリス", "カナダ", "日本", "中国", "フランス", "ドイツ", "イタリア", "韓国", "オーストラリア" }; var products = new[] { "Widget", "Gadget", "Doohickey" }; var colors = new[] { "黒色", "白色", "赤色", "緑色", "青い色" }; var rand = new Random(0); var dt = DateTime.Now; var list = Enumerable.Range(0, total).Select(i => { var country = countries[rand.Next(0, countries.Length - 1)]; var product = products[rand.Next(0, products.Length - 1)]; var color = colors[rand.Next(0, colors.Length - 1)]; var date = new DateTime(dt.Year, i % 12 + 1, 25, i % 24, i % 60, i % 60); return new Sale { ID = i + 1, 開始日 = date, 終了日 = date, 国名 = country, 製品名 = product, 色 = color, 金額 = rand.NextDouble() * 10000 - 5000, 金額2 = rand.NextDouble() * 10000 - 5000, 割引 = rand.NextDouble() / 4, アクティブ = (i % 4 == 0), 傾向 = Enumerable.Range(0, 12).Select(x => new MonthData { Month = x + 1, Data = rand.Next(0, 100) }).ToArray(), ランク = rand.Next(1, 6) }; }); return list; } internal static dynamic GetCountries() { throw new NotImplementedException(); } internal static dynamic GetProducts() { throw new NotImplementedException(); } } public class MonthData { public int Month { get; set; } public double Data { get; set; } }
次にControllersフォルダにFlexGridController
コントローラーを追加します。
FlexGridController.cs
using System.Web.Mvc; using C1MvcWebApplication1.Models; public class FlexGridController : Controller { // GET: FlexGrid public ActionResult Index() { return View(Sale.GetData(15)); } }
最後にViewsフォルダにIndex.cshtml
ビューを追加します。
Index.cshtml
@using C1.Web.Mvc; @using C1MvcWebApplication1.Models; @using C1.Web.Mvc.Serializition; @using C1.Web.Mvc.Grid; @using C1.Web.Mvc.Fluent; @using C1.Web.Mvc.CollectionView; @model IEnumerable<Sale> @(Html.C1().FlexGrid<Sale>() .AutoGenerateColumns(false) .Height(450) .Width(700) .AllowAddNew(true) .SelectionMode(C1.Web.Mvc.Grid.SelectionMode.Cell) .CssClass("grid") .Bind(Model) // FlexGridに列データを連結します .Columns(bl => { bl.Add(cb => cb.Binding("ID")); bl.Add(cb => cb.Binding("開始日").Format("yyyy年/MM月/dd日")); bl.Add(cb => cb.Binding("製品名")); bl.Add(cb => cb.Binding("金額").Format("c")); bl.Add(cb => cb.Binding("割引").Format("p0")); bl.Add(cb => cb.Binding("アクティブ")); }) )
ローカルでデバッグ実行してみます。FlexGridでデータを表示出来ていればOKです。
Visual Studioから配布
Visual Studio 2017からAzure VMに作成したアプリを配布します。
[Azure Virtual Machines]を選択し、作成しておいたAzure VMのServer Corew2016servercore
を設定して[プロファイルの作成]をクリックします。
[構成]をクリックして、
Azure VMのServer Coreにアクセスするための[ユーザー名]と[パスワード]を入力します。
[接続の検証]をクリックすると証明書のダイアログが表示されるので[承諾]をクリックします。
検証がOKなのを確認したら[保存]をクリックします。
[発行]をクリックしてアプリを配布します。
ブラウザで確認(エラー表示)
ブラウザが起動されアプリが立ち上がる…ハズなのですが「Runtime Error」が発生しますね。
詳細なエラーを確認するためにWeb.config
に<customeErrors mode="Off">
を追加して再度発行してみます。今度は「Configuration Error」が発生します。エラーメッセージをみるとWeb.config
で設定しているtargetFramework
に問題があるようです。
Web.configの修正
このエラーの原因はアプリのターゲットフレームワークを.NET Framework 4.7.2に設定しているためです。
Server CoreにインストールしたASP.NETのバージョンは4.6なので、.NET Framworkのバージョンは4.6.2がインストールされています。以下の方法でServer Coreのレジストリを確認することができます。
方法: インストールされている .NET Framework バージョンを確認する | Microsoft Docs
プロジェクトのプロパティでターゲットフレームワークを.NET Framework 4.6に変更しておきます。Web.config
に反映されたことを確認して、再度発行してみましょう。
※.NET Framework 4.7.2など別のバージョンを使うには?
本記事では割愛させていただきましたが、wgetやInvoke-WebRequestで対象のオフラインインストーラーをServer Coreにダウンロードしてサイレントインストールする必要があります。
ブラウザで確認(成功)
今度はアプリが立ち上がっていますね。URLに/flexgrid
を追加してみます。
FlexGridでデータ表示できていますね!
最後に
運用環境のサポート対象としては、本記事で紹介したServer Coreの他にGoogle Cloud PlatformのIaaSであるGoogle Compute Engineもサポートするようになりました。対応している運用環境の詳細はこちらをご覧ください。
開発者におすすめのフォーラム
7月10日(火)に弊社の開発支援ツール販売30周年記念フォーラム「Toolsの杜(ツールのもり)」を開催します。
弊社の.NET開発支援コンポーネントの最新動向や、実際の開発事例についてのセッションも行います。ぜひご参加ください。