Azure Static Web Appsを試してみる(Blazor WebAssembly + ASP.NET Core Web API)

普段のお仕事に役立つ普遍的なプログラミングTIPSや、業界で注目度が高い最新情報をお届けする「編集部ピックアップ」。
今回はAzure Static Web AppsのフロントエンドアプリとしてデプロイしたBlazor WebAssemblyアプリから、Azure App ServiceにデプロイしたWeb APIを呼び出す方法についてお届けします。

Azure Static Web Appsとは?

Azure Static Web Appsは静的コンテンツ(HTML、JavaScript、CSS)で作成したWebアプリケーションをホストするためのクラウドサービスです。GitHubやAzure DevOpsのリポジトリに置いたWebアプリケーションを更新するたびに、GitHub ActionsやAzure Pipelinesにより自動的にビルドとデプロイが行われます。

Angular、React、Vue.jsといったJavaScriptフレームワークや、Blazor WebAssemblyを使用したWebアプリケーションにも対応しており、バックエンドにはAPIとしてAzure Functionsを利用することも可能です。

また、最近のアップデートによりバックエンドにはAzure Functions以外、Azure App ServiceやAzure Container Appsなどで作成したWeb APIを設定することもできるようになりました。

本記事では、Visual Studio 2022を使用してBlazor WebAssemblyアプリケーションとASP.NET Core Web APIアプリケーションを作成し、GitHub Actionsを使用してそれぞれのアプリケーションをデプロイして動作を確認してみます。

ASP.NET Core Web APIアプリケーションの作成

Web APIの内容

公式ドキュメントで紹介されている「アルバム API」を参考にASP.NET Core Web APIアプリケーションを作成します。

このアルバム APIは以下のリポジトリで公開されています。

Web APIの作成

プロジェクトテンプレートから「ASP.NET Core Web API」を選択します。プロジェクト名には「WebApiApp1」を設定します。

ASP.NET Core Web APIアプリケーションの作成

「コントローラーを使用する (最小限の API を使用する場合にはオフにします)」のチェックをOFFにして[作成]をクリックします。

ASP.NET Core Web APIアプリケーションの作成

Program.csのコードを以下のように更新します。

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.MapGet("/", async context =>
{
    await context.Response.WriteAsync("Hit the /albums endpoint to retrieve a list of albums!");
});

app.MapGet("api/albums", () =>
{
    return Album.GetAll();
})
.WithName("GetAlbums");

app.Run();

record Album(int Id, string Title, string Artist, double Price, string Image_url)
{
    public static List<Album> GetAll()
    {
        var albums = new List<Album>(){
            new Album(1, "You, Me and an App Id", "Daprize", 10.99, "https://aka.ms/albums-daprlogo"),
            new Album(2, "Seven Revision Army", "The Blue-Green Stripes", 13.99, "https://aka.ms/albums-containerappslogo"),
            new Album(3, "Scale It Up", "KEDA Club", 13.99, "https://aka.ms/albums-kedalogo"),
            new Album(4, "Lost in Translation", "MegaDNS", 12.99,"https://aka.ms/albums-envoylogo"),
            new Album(5, "Lock Down Your Love", "V is for VNET", 12.99, "https://aka.ms/albums-vnetlogo"),
            new Album(6, "Sweet Container O' Mine", "Guns N Probeses", 14.99, "https://aka.ms/albums-containerappslogo")
         };

        return albums;
    }
}

エンドポイント/api/albumsでアルバムのリストを返すWeb APIが完成しました。

GitHubにリポジトリを作成

Visual Studioのメニューから[Git]-[Git リポジトリの作成]をクリックして、GitHubにリポジトリ「StaticWebAppsTest-WebApiApp1」を作成してローカルリポジトリからアプリケーションのソースをプッシュします。

GitHubにリポジトリを作成

Azure App Serviceにデプロイ

Visual Studioのメニューから[ビルド]-[WebApiApp1 の発行]をクリックして、作成したASP.NET Core Web APIアプリケーションをAzure App Service(Linux)へデプロイします。

Azure App Serviceにデプロイ

この際に上記で作成したGitHubのリポジトリを設定してGitHub ActionsによるCI/CDを設定しておきます。

Azure App Serviceにデプロイ

追加されたワークフローファイル(*.yml)をコミットしてプッシュするとGitHub Actionsによるデプロイが実行されます。

Azure App Serviceにデプロイ
Azure App Serviceにデプロイ

ワークフローが成功してAzure App Serviceにデプロイされれば完了です。

Blazor WebAssemblyアプリケーションの作成

プロジェクトテンプレートから「Blazor WebAssembly」を選択します。プロジェクト名には「BlazorWasmApp1」を設定します。

Blazor WebAssemblyアプリケーションの作成

Albumクラスの追加

DataフォルダにAlbum.csを追加して以下のようにAlbumクラスを追加します。

namespace BlazorWasmApp1.Data
{
    public class Album
    {
        public int Id { get; set; }

        public string? Title { get; set; }

        public string? Artist { get; set; }

        public double Price { get; set; }

        public string? Image_url { get; set; }

    }
}

Web APIを呼び出すページを追加

PagesフォルダにWeb APIを呼び出すページとしてCallWebApi.razorを追加して内容を以下のように更新します。

@page "/call-web-api"
@using BlazorWasmApp1.Data
@inject HttpClient Http

<PageTitle>Call Web API</PageTitle>

<h1>Albums</h1>

@if (albums == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>番号</th>
                <th>タイトル</th>
                <th>アーティスト</th>
                <th>価格</th>
                <th>URL</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var album in albums)
            {
                <tr>
                    <td>@album.Id</td>
                    <td>@album.Title</td>
                    <td>@album.Artist</td>
                    <td>@album.Price</td>
                    <td>@album.Image_url</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private IEnumerable<Album>? albums = Array.Empty<Album>();
    private const string ServiceEndpoint = "/api/albums";

    protected override async Task OnInitializedAsync() => await GetAlbums();
      
    private async Task GetAlbums()
    {
        albums = await Http.GetFromJsonAsync<Album[]>(ServiceEndpoint);
    }
}

ページの初期化時にGetAlbumsを実行してWeb APIからデータを取得します。

NavMenu.razorの更新

CallWebApi.razorで設定したページ「/call-web-api」を参照するために、SharedフォルダにあるNavMenu.razorを以下のように更新します。

<div class="top-row ps-3 navbar navbar-dark">
    <div class="container-fluid">
        <a class="navbar-brand" href="">BlazorWasmApp1</a>
        <button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu">
            <span class="navbar-toggler-icon"></span>
        </button>
    </div>
</div>

<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
    <nav class="flex-column">
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="oi oi-home" aria-hidden="true"></span> Home
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="counter">
                <span class="oi oi-plus" aria-hidden="true"></span> Counter
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="fetchdata">
                <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="call-web-api">
                <span class="oi oi-code" aria-hidden="true"></span> Call Web API
            </NavLink>
        </div>
    </nav>
</div>

@code {
    private bool collapseNavMenu = true;

    private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;

    private void ToggleNavMenu()
    {
        collapseNavMenu = !collapseNavMenu;
    }
}

27~31行目で/call-web-apiを参照するメニューの要素を追加しています。これでBlazor WebAssemblyアプリの作成は完了です。

GitHubにリポジトリを作成

Visual Studioのメニューから[Git]-[Git リポジトリの作成]をクリックして、GitHubにリポジトリ「StaticWebAppsTest-BlazorWasmApp1」を作成してローカルリポジトリからアプリケーションのソースをプッシュします。

GitHubにリポジトリを作成

Static Web Appsの作成

Azureポータルから「static web apps」で検索して「静的 Web アプリ」をクリックします。

Static Web Appsの作成

[静的 Web アプリ の作成]をクリックします。

Static Web Appsの作成

ホスティングプランを「Standard」に設定します。バックエンドのAPIにAzure Functions以外を使用する際にはStandardを使用する必要があります。

Static Web Appsの作成

「デプロイの詳細」には先ほど作成したGitHubのリポジトリ情報を設定します。「ビルドの詳細」の「プリセット」には「Blazor」を、「アプリの場所」には「BlazorWasmApp1」を設定して、[確認および作成]をクリックします。

Static Web Appsの作成

[作成]を開始します。設定したGitHub Actionsのワークフローが成功してStatic Web Appsにデプロイされれば完了です。

Static Web AppsとAzure App Serviceをリンクする

公式ドキュメントを参考にAzure App ServiceをバックエンドのWeb APIに設定します。

Azureポータルのメニューから[API]をクリックして、さらに[リンク]をクリックします。

Static Web AppsとAzure App Serviceをリンクする

「バックエンド リソースの種類」に「Web アプリ」を設定して、今回Azure App ServiceにデプロイしておいたASP.NET Core Web APIアプリケーションを設定します。

Static Web AppsとAzure App Serviceをリンクする

[リンク]をクリックして設定を完了します。

Static Web AppsとAzure App Serviceをリンクする

動作を確認してみる

Azureポータルのメニューから[概要]をクリックして、さらに「URL」に表示されているアプリケーションのURLをクリックします。

動作を確認してみる

デプロイしたBlazor WebAssemblyアプリケーションが表示されます。メニューから[Call Web API]をクリックして以下のようにWeb APIからデータを取得して表示できれば成功です。

動作を確認してみる

さいごに

今回はAzure Static Web AppsへBlazor WebAssemblyアプリをデプロイして、Blazor WebAssembly アプリからAzure App ServiceへデプロイしたASP.NET Core Web APIアプリを呼び出してデータを表示作成してみました。

Web API側でCORSの設定を行う必要がなく、Statics Web Appsからリンクの設定をするだけでStatics Web Appsからのみ呼び出せるように実装できるのも便利だと思います。

今回は取り上げていないのですが、ローカルでの開発をより効率よく行うことが可能な「Static Web Apps CLI」も用意されているので今後こちらも紹介できればと思います。

上記コードを実装しているサンプルはコチラです。


参考

\  この記事をシェアする  /