LoginSignup
12
13

More than 3 years have passed since last update.

BlazorアプリをFirebase Databaseと連携させる

Last updated at Posted at 2019-09-12

BlazorクライアントアプリケーションをFirebase Hostingにデプロイし、Firebase Databaseと連携したいと思います。

ezgif-5-3d431567faf1.gif

開発環境

Windows10
Visual Studio 2019 Preview
.Net Core 3.0 Preview 9
Firebase CLI for Windows(beta)

Firebaseの準備

Firebase-CLIを使えるようにする

VisualStudioのプロジェクトをFirebaseにデプロイするために、Firebase-Cliを準備します。Firebase CLI for Windows(beta)は、Node.jsなどのインストールが不要なので便利です。
firebase-cli.JPG

PATHを通しておきます。
firebase-cli-path.png

Firebaseにログインし、新しいプロジェクトを作成

Firebaseアカウントを作成し、ログインして、新しいプロジェクトを作成します。
左側の開発メニューから「Authentication」を選択し、認証方法を設定します。今回は匿名(anonymous)を有効にします。
auth-tokumei.JPG

Firebase Databaseの作成

左側の開発メニューから「Database」を選択し、データベースの作成を行います。
保護ルールは、「テストモードで開始」を選択し、ロケーションはデフォルトのままにします。

Database (Realtime Database)の「ルール」で、.read:true , .write:true になっていることを確認します。
なっていない場合、画面上で書き換えます。

database_rule.JPG

Firebase Databaseの設定はこれで終わりです。Firebase Databaseは「Realtime Database」を使います。

マイアプリの追加

Firebaseの左側の歯車メニューから「プロジェクトの設定」を選びます。
「全般」の「マイアプリ」のウェブアプリ「</>」を選択します。
アプリの登録で「アプリのニックネーム」を付け、「アプリを登録」します。「□このアプリのFirebase Hostingも設定します」はチェックを外した状態で登録します。

次画面で出てくる Firebase SDKの追加画面では、apikey情報が表示されるので控えておきます。
今回必要になるのはapikeydatabaseURLです。
firebase-webapp-s.png

ベースのプロジェクトをデプロイ

VisualStudio2019 でBlazorクライアントアプリケーションを作成

新しいプロジェクトから、Blazorアプリを選択し、「Blazor WebAssembly App」を選択します。Server-Sideはホスティングしませんので、「ASP.NET Core hosted」はチェックしないで作成します。

何もしない状態で、デプロイしてみる

こちら様のサイトを参考に、Firebase Hostingにデプロイしてみます。

(参考)Qiita Blazorで作成したウェブサイトをFirebaseで公開する

firebase deployコマンドの途中でHTTP Error: 503エラーが発生する場合は、何度か試すと成功します。

以上でFirebaseの設定は完了です。

BlazorアプリのFetchDataのページをFirebase Databaseと連携させる

デフォルトのFetchDataページは、静的ファイルの中身を表示しているだけのものです。Firebase Databaseと連携させます。

Firebase Nugetパッケージの追加

FirebaseAuthentication.net と FirebaseDatabase.netを「Nugetパッケージの管理」から追加します。

(参考)FirebaseAuthentication.net
(参考)FirebaseDatabase.net

Pages/FetchData.razorのWeatherForecastをModel.csに移動

Model.csを新規作成し、モデルクラスとなるPages/FetchData.razorWeatherForecast定義を移動します。

Model.cs
namespace BlazorApp
{
    public class Model
    {
        public class WeatherForecast
        {
            public DateTime Date { get; set; }
            public int TemperatureC { get; set; }
            public string Summary { get; set; }
            public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
        }
    }
}

Firebaseアクセス用のAPIクラスを追加

Firebase Databaseとやりとりを行うAPI.csを新規に追加します。

実装するのは、認証とデータの取得、追加を行う関数です。

API.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

// 参照の追加
using Firebase.Database;
using Firebase.Database.Query;
using Firebase.Auth;

namespace BlazorApp
{
    public class API
    {
        private FirebaseAuth _auth = null;
        public async Task Auth()
        {
            try
            {
                if (_auth == null)
                {
                    // Firebase Database apiKey
                    var auth = new FirebaseAuthProvider(new FirebaseConfig("Firebase Database apikey")); 
                    _auth = await auth.SignInAnonymouslyAsync();
                    Console.WriteLine("Auth OK");
                }
            }
            catch
            {
                Console.WriteLine("Auth NG");
            }
        }

        private ChildQuery GetDatabaseQuery(string path = null)
        {
            Console.WriteLine("GetDatabaseQuery Start");
            if (_auth == null)
            {
                throw new NullReferenceException();
            }
            Console.WriteLine("GetDatabaseQuery End");

            return new FirebaseClient(
                 // Firebase Database databaseURL
                "https://Firebase Database databaseURL.firebaseio.com",      
                new FirebaseOptions
                {
                    AuthTokenAsyncFactory = () => Task.FromResult(_auth.FirebaseToken),
                })
                .Child(path);
        }

        /// <summary>
        /// Firebase Databaseからデータ取得
        /// </summary>
        /// <returns></returns>
        public async Task<Model.WeatherForecast[]> GetData()
        {
            Console.WriteLine("GetData Start");
            try
            {
                var query = GetDatabaseQuery("/WeatherForecast");
                var result = await query.OnceAsync<Model.WeatherForecast>();
                var resultobject = result.Select(o => o.Object);
                Console.WriteLine("Object count:" + resultobject.Count().ToString());
                Console.WriteLine("GetData End");
                return resultobject.ToArray();
            }
            catch
            {
                Console.WriteLine("GetData NG");
                return null;
            }
        }

        /// <summary>
        /// Firebase Databaseへデータ追加
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public async Task SetData(Model.WeatherForecast value)
        {
            Console.WriteLine("SetData Start");
            try
            {
                var query = GetDatabaseQuery("/WeatherForecast");
                await query.PostAsync(value);
                Console.WriteLine("SetData End");
            }
            catch
            {
                Console.WriteLine("SetData NG");
            }
        }
    }
}

Pages/FetchData.razorからAPI.csを呼び出す

最後に FetchData.razor内で、API.csの処理を呼び出します。

FetchData.razor
@page "/fetchdata"
@inject HttpClient Http

<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from the server.</p>

<div style="display:inline-flex">
    <p>Date</p>
    <input type="date" @bind-value="addItem.Date" />
    <p>Temp. (C)</p>
    <input type="text" @bind-value="addItem.TemperatureC"/>
    <p>Temp. (F)</p>
    <input type="text" value="@addItem.TemperatureF"/>
    <p>Summary</p>
    <input type="text" @bind-value="addItem.Summary"/>
    <button class="btn btn-primary" @onclick="SetWeatherForecast">Add</button>
</div>

<br />
<br />


@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th>Temp. (C)</th>
                <th>Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var forecast in forecasts)
            {
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    //WeatherForecast[] forecasts;
    // 表示用データ
    Model.WeatherForecast[] forecasts;
    // 追加用データ
    Model.WeatherForecast addItem;
    // Firebase APIクラスのインスタンス
    API firebaseAPI = null;

    protected override async Task OnInitializedAsync()
    {
        //forecasts = await Http.GetJsonAsync<WeatherForecast[]>("sample-data/weather.json");
        addItem = new Model.WeatherForecast();
        addItem.Date = DateTime.Now;
        // データ取得
        await GetWeatherForecast();
    }

    //public class WeatherForecast
    //{
    //    public DateTime Date { get; set; }
    //    public int TemperatureC { get; set; }
    //    public string Summary { get; set; }
    //    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
    //}

    // データ取得
    async Task GetWeatherForecast()
    {
        if(firebaseAPI == null)
        {
            firebaseAPI = new API();
        }
        // 認証後、Firebase Databaseから取得
        await firebaseAPI.Auth().ContinueWith(async task =>
        {
            forecasts = await firebaseAPI.GetData();
            this.StateHasChanged();
        });
    }

    // データ設定
    async void SetWeatherForecast()
    {
        if (firebaseAPI == null)
        {
            firebaseAPI = new API();
        }
        // 認証後、Firebase Databaseへ追加、その後、データ再取得
        await firebaseAPI.Auth()
                         .ContinueWith(async task1 =>
                         {
                            await firebaseAPI.SetData(addItem).ContinueWith(async task2 =>
                                                            {
                                                                await GetWeatherForecast();
                                                            });
                         }
                         );
    }
}

プロジェクトを発行して、Firebase Hostingへデプロイする

プロジェクトを発行後、Firebase CLIから firebase deploy コマンドでデプロイします。
デプロイ後、アプリケーションのURLを開き動作を確認します。

Firebase Databaseの状態

データが追加されたFirebase Databaseには、ツリー上にデータが出来上がっているのが確認できます。

firebase-database.png

うまく動作しない時は

Blazorで作成したクライアントアプリケーションのデバッグは容易ではありません。そこで、ソースではConsole.WriteLine()を使いログを吐き出し、Chromeなどのデバッグ画面を使って、コンソールログを確認します。
consolelog.JPG

関連記事

Blazorで作成したウェブサイトをFirebaseで公開する
C#でFirebaseを使ってみよう!(1) FirebaseとEmail-Password認証
C#でFirebaseを使ってみよう!(3) Databaseを使ってみる

12
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
13