echo("備忘録");

IT技術やプログラミング関連など、技術系の事を備忘録的にまとめています。

【.net Core】Blazorアプリを作成する&Azureで公開する

概要

先日9/23に、ついに.net core(ver3.0)がメジャーリリースされました。(LTSはver3.1だそうですが)

そして、9/26(木)にマイクロソフトで開催された、下記イベントに参加してきました。

この中で、マイクロソフトの井上さん(チャックさん)が話された、.net Coreの概要について、下記が魅力的だな、と思いました。

  • .net CoreがWPF、及びWinFormsに対応
  • .net Coreメジャーリリースに合わせて、Blazorも正式対応

上記のうちBlazorについて簡単に触って、ついでにAzureに公開するところまでやりましたので、紹介がてら。

Blazorとは?

Blazorの概要&詳細については、マイクロソフト公式ページに書いてありますので、そちらを参照。

個人的に、上記イベントでのBlazorの印象は、

「Vue.jsの"単一ファイルコンポーネント"を、C#で実現した感じ」

でした。(「Vue.jsの単一ファイルコンポーネント」についてはググって下さい)

実際、一言で表現するなら、こんな感じになると思います。

プロジェクトを作成する

とりあえず、Visual Studioで、下記手順でBlazorプロジェクトを作成します。

  • Visual Studioで[新規作成] - [ファイル]を選択し、テンプレートから[Blazorアプリ]を選択
  • プロジェクト名などを設定し「作成」をクリック

プロジェクトを作成後、下記手順で新しいRazorコンポーネントを追加します。
- ソリューションエクスプローラ上で「Pages」フォルダを右クリック
- [追加] - [新しい項目] - [Razorコンポーネント]を選択

f:id:Makky12:20191004192648p:plain f:id:Makky12:20191004192700p:plain

プログラムを書く

とりあえず、サンプルで書いたのソースが下記。(クッソ長くなったな...)

razor記法についてはここでは突っ込みませんが、特徴は下記あたりでしょうか。

  • 「@page」でページのリンク(ルーティングパス)を定義
  • 「@code」にバックグラウンドロジックを記載する
    • Vue.jsでいう「<script>」タグ
  • HTML内に「@onclick」「@if」など、分かりやすいディレクティブが使える
    • Vue.jsで言う「v-on:click」や「v-if」
    • 下記ソースには「@onclick」はないですが、デフォルトで作成される「Pages/Counter.razor」に記載されています。

やたら「Vue.jsで言う」と言っていますが、このあたりが先程の

「Vue.jsの"単一ファイルコンポーネント"を、C#で実現した感じ」

な気がします。

// Pages/MyRazor.razor
@page "/myrazor"
@using BlazorApp1.Data
@using System.Collections.Generic
@using System.Linq;
@using System.Net.Http;
@using Newtonsoft.Json;
@using System.Diagnostics
<h1>MyFirstRazor</h1>
<div class="container">
<div class="row">
<div class="col-10 offset-1">
<div class="btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-primary active">
<input type="radio" name="options" id="option1" autocomplete="off" checked />全員
</label>
<label class="btn btn-primary">
<input type="radio" name="options" id="option2" autocomplete="off" />日本人
</label>
<label class="btn btn-primary">
<input type="radio" name="options" id="option3" autocomplete="off" />外国人
</label>
</div>
</div>
</div>
<div class="row">
<div class="col-10 offset-1">
<table class="table table-striped">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Name</th>
<th scope="col">Country</th>
</tr>
</thead>
<tbody>
@if (goalkeepers != null)
{
foreach (var gk in goalkeepers)
{
<tr>
<td>@gk.Id</td>
<td>@gk.Name</td>
<td>@gk.Country</td>
</tr>
}
}
</tbody>
</table>
</div>
</div>
</div>
@code
{
List<GoalKeeper> goalkeepers = null;
List<GoalKeeper> allGoalKeepers = null;
protected override async Task OnInitializedAsync()
{
var client = new HttpClient();
var response = await client.GetStringAsync("(Azure Functionの呼び出し用URL)");
allGoalKeepers = JsonConvert.DeserializeObject<List<GoalKeeper>>(response);
goalkeepers = new List<GoalKeeper>(allGoalKeepers);
}
private EventCallback FilterGoalKeeper(int mode)
{
Debug.WriteLine(mode.ToString());
List<GoalKeeper> gk = null;
switch (mode)
{
case 0:
gk = new List<GoalKeeper>(allGoalKeepers);
break;
case 1:
gk = (List<GoalKeeper>)from item in allGoalKeepers
where item.Country == "Japan"
orderby item.Id
select item;
break;
case 2:
gk = (List<GoalKeeper>)from item in allGoalKeepers
where item.Country != "Japan"
orderby item.Id
select item;
break;
}
}
}
// Data/GoalKeeper.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BlazorApp1.Data
{
public class GoalKeeper
{
public int Id { get; set; }
public string Name { get; set; }
public string Country { get; set; }
public GoalKeeper(int id, string name, string country)
{
this.Id = id;
this.Name = name;
this.Country = country;
}
}
}
Bootstrapの適用

また、HTML部分を見て気づいた人もいるでしょうが、上記HTMLにはBootstrap4を適用してます。

Blazorでも、下記パッケージをNuGet経由でインストールすれば、Bootstrapを使用出来ます。

インストール後、Pages/_Host.cshtmlファイルの「body」タグに下記を追加するだけでOKです。

<body>
<!-- この1行を追加-->
<script src="_content/BlazorStrap/blazorStrap.js"></script>
</body>

Azureで動かす

で、クライアント部分は完成したので、せっかくなのでAzureにデプロイして、Azure上で動かします。

デプロイ方法ですが、下記方法でOKです。

  • ソリューションエクスプローラでプロジェクトを右クリックして「発行」を選択
  • 「発行先を選択」で「Azure App Service」を選択
  • 「App Service 新規作成」で、下記画像の各種情報を指定し、「作成」をクリックする。
    • 「リソースグループ」「ホスティングプラン」は、その場で新規作成ができます。
    • デフォルトだとUSリージョンが選ばれている場合があるので注意。

※もし「発行先」で「WebサーバーかAzurか」という選択が出た場合は「Azure」を選択してください。
(一度だけ出たのですが、再現しなかった...)

f:id:Makky12:20191004193752p:plain f:id:Makky12:20191004193802p:plain

ただ、Azureにデプロイ完了しても、このままでは動きません。
Azureがまだ.net Core3.0に対応していないようなので、.net Core3.0が動くようにする必要があります。

それには、下記手順を実行すればOKです。

  • デプロイしたBlazorの「App Service」リソースで、「拡張機能」を選択する
  • ASP.NET Core 3.0 (x64) Runtime」をインストールする
  • 「設定」→「構成」をクリックし、「全般設定」タグで以下の設定をする。
    • スタック:.net core
    • プラットフォーム:64bit

f:id:Makky12:20191004194003p:plain f:id:Makky12:20191004194014p:plain

これでデプロイしたBlazorアプリの「概要」に表示されているURLを表示すれば、Azure上でBlazorアプリが動くはずです。

f:id:Makky12:20191004195255p:plain

※なお、デプロイ&再デプロイ時に下記ダイアログが表示されますが、これは先程の「Azureがまだ.net Core3.0に対応していない」のが理由と思われるので、とりあえずは気にしなくてOKです。

f:id:Makky12:20191004195436p:plain

ちなみに、Azure Functionのソースはこちら。

using System;
using System.IO;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace Company.Function
{
public static class HttpTriggerCSharp
{
[FunctionName("HttpTriggerCSharp")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
var gk = new List<GoalKeeper>();
gk.Add(new GoalKeeper(1, "ハーフナー・ディド", "Netherland"));
gk.Add(new GoalKeeper(2, "伊藤 裕二", "Japan"));
gk.Add(new GoalKeeper(3, "楢崎正剛", "Japan"));
gk.Add(new GoalKeeper(4, "川島永嗣", "Japan"));
gk.Add(new GoalKeeper(5, "ミチェル・ランゲラク", "Australia"));
string resopnseJson = JsonConvert.SerializeObject(gk);
return (ActionResult)new OkObjectResult(resopnseJson);
}
}
class GoalKeeper
{
public int Id { get; set; }
public string Name { get; set; }
public string Country { get; set; }
public GoalKeeper(int id, string name, string country) {
this.Id = id;
this.Name = name;
this.Country = country;
}
}
}

まとめ

と、かなり駆け足でしたが、Blazorについて、簡単に紹介しました。

個人的にマイクロソフトは、環境やプラットフォームはかなりシェア持ってるけど、Web系言語としての採用率がJS系フレームワークPHPなどに比べてイマイチ...と思っていただけに、巻き返しに期待したいところです。