https://d226lax1qjow5r.cloudfront.net/blog/blogposts/build-a-secret-santa-app-with-blazor/blog_secret-santa_blazor_1200x600.jpg

Blazorでシークレットサンタアプリを作ろう

最終更新日 December 18, 2020

所要時間:4 分

アドベントは期待の季節である。もちろん、私たちの多くがクリスマスを前にして感じる精神的な期待もある。また、伝統の中でリラックスし、家族とともに喜ぶための休暇への期待もある。

の精神で C#アドベントこの困難な時代に、我が家がどのように伝統を守っていくかをお話させてください。今年は、毎年恒例のシークレットサンタゲームを仮想化するためにBlazorアプリを作りました。参加者が自分の電話番号を登録し、誰にプレゼントを送るかをメッセージで伝えることができます。

問題点

毎年、私たちはシークレットサンタのプレゼント交換をしている。妻は家族全員に声をかけ、誰が参加したいか確認する。その人数は、家族の若いメンバーからの参加状況によって変動する。通常、終了時には15人ほどの参加者がいる。

その後、テレサが参加者全員分のカードを購入し、ゲームのルールを記入する。例えば、○○ドル以上は使わない、などだ。そしてすべてのカードを封筒に入れ、感謝祭(11月の第4木曜日)に集まってカードを配る。

毎年問題にぶつかるのだが、サンクスギビング・ディナーには必ず何人かの参加者が欠席する。ニューヨーク、ニュージャージー、フロリダに分散している我が家では、欠席者にランダムにシークレット・サンタを割り当てることはできない。過去には、参加しない人が一人、その場にいない人を選んで、その人が自分自身を受け取らないようにすることで、いつもこの問題を回避してきた。その後、妻がすべての封筒に適切な人に宛名を書いて送る。

今年は、1人か2人が欠席したのではなく、12人が欠席した。

コードへ直行

このチュートリアルを飛ばして、自分でシークレット・サンタ・ゲームを実行したい場合は、すべてのコードが GitHub

前提条件

  • 最新の .NET SDK

  • このデモではVisual Studio 2019を使用している。必要であれば、VS Codeを使うこともできる。

  • 私は Postgresを使います。このデモでは、サーバーが立ち上がっていると仮定します。データベースのコンテキストを更新すれば、どんなデータベースを使ってもかまいません。

  • 私はこれをAzureにデプロイした。そうするかどうかはあなた次第だが、これを実行するにはIIS Expressまたは

Vonage API Account

To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.

This tutorial also uses a virtual phone number. To purchase one, go to Numbers > Buy Numbers and search for one that meets your needs.

プロジェクトの作成

最初のステップはプロジェクトの作成です。開発ディレクトリに移動し、ターミナルで以下のコマンドを実行する:

dotnet new blazorserver --no-https -n SecretSanta

このコマンドは、以下のフォルダとプロジェクトを作成します。 SecretSantaを作成します。 cd SecretSantaというフォルダとプロジェクトを作成し、このディレクトリに移動して以下のコマンドを実行する:

dotnet add package Vonage
dotnet add package Microsoft.AspNetCore.Components.Authorization
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL

データモデルの構築

ここでは エンティティフレームワークコアを使用します。先に述べたように、私はこのためにPostgresを使用していますが、Postgresを使用する包括的な必要性はありません。どんなデータベースを使っても構いません。

という名前のファイルを作成し SecretSantaParticipantという名前のファイルを作成し、そこに以下を追加する:

public class SecretSantaParticipant
{
    [Key]
    [Required]
    [Phone(ErrorMessage ="Phone Number must be a fully " +
        "formed phone number with no special charecters")]
    public string PhoneNumber { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public string Address { get; set; }

    public string GiftIdeas { get; set; }
    
    public string RequestId { get; set; }

    [ForeignKey("MatchForeignKey")]
    public SecretSantaParticipant Match { get; set; }

    public string Role { get; set; }

    public bool HasGiver { get; set; }
    
    [ForeignKey("GiverForeignKey")]
    public SecretSantaParticipant Giver { get; set; }
}

このクラスは、シークレットサンタアカウントを管理するためにクライアントとサーバ間で渡すデータモデルとなります。

データベース・コンテキストの作成

という名前のファイルを作成する。 SecretSantaContext.cs.ファイルを作成する。 SecretSantaContextクラスを DbContextという名前のファイルを作成し、そこに以下を追加する。

private readonly IConfiguration _config;
public DbSet<SecretSantaParticipant> Participants { get; set; }

public SecretSantaContext(IConfiguration config) => _config = config;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) =>
    optionsBuilder.UseNpgsql(_config["CONNECTION_STRING"]);

注:別のデータベースを使いたい場合は、ここで変更します。

認証プロバイダーの作成

を使用します。 Verify APIを使用します。を使用します。カスタムの AuthenticationStateProviderを作成します。新しいファイル AuthProvider.csを作成し AuthProviderクラスを AuthenticationStateProvider.

クラス内に AuthProviderクラスに ClaimsIdentiyというプライベート・メンバーを追加する。 _identity:

private ClaimsIdentity _identity = new ClaimsIdentity();

このクレームIDを最初は匿名で初期化し、ユーザーが最初にこのページにアクセスしたときにクレームがないようにします。

認証状態の取得

次に、認証状態を取得する手段を提供しましょう。 GetAuthenticationStateAsyncメソッドをオーバーロードします。このメソッドは、私たちの ID を含む認証状態を返します。

public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
    return await Task.FromResult(new AuthenticationState(new ClaimsPrincipal(_identity)));
}

認証状態の更新

このステート・プロバイダーは、特定のユーザーのセッションにスコープされ、そのユーザーが特定のページでアクセスできることをアプリに伝えます。その結果、認証状態を更新する手段が必要になります。

そのために、ログインとログアウトのメソッドを追加します。ログインメソッド AuthorizeUserメソッドは、ユーザーの電話番号と役割(管理者であれば、より多くの情報を見ることができます)を持つ新しい ClaimsIdentityを作成し、ユーザーの電話番号と役割(管理者であれば、より多くのものを見ることができます。)そして AuthProviderを見ている人に、認証状態が変更されたことを通知します:

public void AuthorizeUser(SecretSantaParticipant participant)
{
    var claims = new[] { new Claim(ClaimTypes.Name, participant.PhoneNumber) };
    claims.Append(new Claim(ClaimTypes.Role, participant.Role));
    _identity = new ClaimsIdentity(claims,"apiauth_type");            
    var user = new ClaimsPrincipal(_identity);
    NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
}

逆に LogOutUserメソッドは ClaimsIdentityを anonymous にリセットし、 ステートプロバイダのリッスンしているもの全てに認証ステートを更新したことを通知します。

public void LogOutUser()
{
    _identity = new ClaimsIdentity();
    var user = new ClaimsPrincipal(_identity);
    NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
}

シークレット・サンタ・サービス

アプリに必要なバックエンドの処理をすべて行えるようにするために、依存関係の注入可能なサービスを追加します。このサービスには、検証の処理、データベースからの読み書き、参加者へのメッセージ送信などが含まれます。という名前のファイルを作成します。 SecretSantaService.cs.

に3つのものを依存注入する。 SecretSantaService:

  1. 私たちの VonageClientVonage API リクエストをすべて処理します。

  2. 私たちの SecretSantaContextデータベースへのすべての接続を調停する

  3. アプリの設定にアクセスできる IConfigurationオブジェクトで、アプリのコンフィギュレーションにアクセスできる。

このように宣言する:

private readonly VonageClient _client;
private readonly SecretSantaContext _db;
private readonly IConfiguration _config;

そして、コンストラクターを使ってサービスに注入する:

public SecretSantaService(VonageClient client, SecretSantaContext context, IConfiguration config)
{
   _client = client;
   _db = context;
   _config = config;
}

ベリファイ・リクエストの作成

参加者の電話番号を使って、アカウントへのアクセスを確認する。この方法は、ログインに一種の1FAを作ることになる。私は、安全なログインが必要な状況では1FAを使いませんが、これは家族で楽しむゲームであり、私たちの目的は電話番号を確認することなので、このままにしておきます。

1FAをキックオフするために、検証を開始し、VerifyキックオフのIDを返すメソッドを追加します。これはVonage Verify APIを使って行う。この時点では、たった1行のコードです:

public async Task<string> StartVeriy(string number)
{
   return (await _client.VerifyClient.VerifyRequestAsync(
       new VerifyRequest 
       { 
           Brand = "North Pole Access", 
           SenderId = _config["VONAGE_NUMBER"],
           Number= number,
           WorkflowId = VerifyRequest.Workflow.SMS,
           PinExpiry=300
       }
       )).RequestId;
}

ハンドルの確認

ユーザが自分の番号を入力してログインしたり、アカウントを作成したりすると、Verify APIに検証リクエストを完了するよう依頼することができます。これは Vonage Verify Client の VerifyCheckメソッドを使用します:

public async Task<bool> ConfirmCode(string id, string code)
{
   try
   {
       var result = await _client.VerifyClient.VerifyCheckAsync(new VerifyCheckRequest { Code = code, RequestId = id });
       return true;
   }
   catch (VonageVerifyResponseException)
   {
       return false;
   }            
}

シャッフルユーザー

次の方法は、ユーザーをシャッフルし、シークレットサンタゲームの割り当てを配布します。この方法は、シークレットサンタの割り当てを持っていないすべてのユーザーを調べ、まだシークレットサンタを持っていないユーザーのプールからランダムに選択します。 Giverの中からランダムに選びます。

public async Task ShuffleUsers()
{
   var rnd = new Random(DateTime.UtcNow.Second);
   
   var participants = _db.Participants.ToList();
   while (participants.Any(x => !x.HasGiver))
   {
       var participant1 = participants.First(x => !x.HasGiver);
       var unmatched = participants.Where(x => x.Match == null && x.PhoneNumber !=participant1.PhoneNumber);
       if(unmatched.Count() == 0)
       {
           System.Diagnostics.Debug.WriteLine("encountered Edge case");
           var match = participants.First(x => x.PhoneNumber != participant1.PhoneNumber);
           participant1.Giver = match;
           participant1.Match = match.Match;
           match.Match.Giver = participant1;
           match.Match = participant1;
           participant1.HasGiver = true;                    
       }
       else
       {
           var match = unmatched.ToList().ElementAt(rnd.Next(unmatched.Count() - 1));
           participant1.Giver = match;
           participant1.HasGiver = true;
           match.Match = participant1;                    
       }                
   }
   await _db.SaveChangesAsync();
}

参加者に知らせる

ユーザーがシャッフルされたので、今度は誰がマッチするかを全員に伝える必要がある!

そのためにVonage SMS APIを使います。参加者をループさせ、シークレットサンタが誰か、いくら使うか、どこにプレゼントを送るかを伝えます。私はこの部分をVonage LVNで行っているが、これは1メッセージ/秒でスロットルする。そのため、アプリはリクエストの間に1秒待つようにします。このゲームには若い参加者もいるので、サンタが彼らの助けを必要としていることを伝えるつもりだ!

public async Task NotifyUsers()
{
   foreach(var participant in _db.Participants)
   {
       var message = $"Hello {participant.Name} this is Santa. " +
           $"I'm desperately busy up here at the North Pole and need your help. " +
           $"Could you help me out and find a gift for {participant.Match.Name}? " +
           $"It doesn't need to extravagant, I wouldn't spend more than $25." +
           $"You can send the gift directly to them at: {participant.Match.Address}. ";
       if (!string.IsNullOrEmpty(participant.Match.GiftIdeas))
       {
           message += $"They wrote me with some ideas of what to get them: {participant.Match.GiftIdeas}";
       }
       await _client.SmsClient.SendAnSmsAsync(new SendSmsRequest
       {
           To=participant.PhoneNumber,
           From=_config["VONAGE_NUMBER"],
           Text=message
       });
       Thread.Sleep(1000);
   }
}

最新情報を送信

サインアップした後、ユーザーが設定できることはあまりないだろうが、アドレスとシークレットサンタへのプレゼントのアイデアを変更できるようにすることにした。その結果、ユーザーが自分のアカウントを編集すると、プレゼントする人に更新を知らせるSMSが送信されます:

public async Task NotifyUserOfUpdate(SecretSantaParticipant participant)
{
   if(participant.Match != null)
   {
       var msg = $"Hello, this is Santa again, just wanted to let you know that your match {participant.Name} sent me some updates:" +
           $" Their Address is {participant.Address}.";
       if (!string.IsNullOrEmpty(participant.GiftIdeas))
       {
           msg += $" And they indicated they'd want {participant.GiftIdeas}";
       }
       await _client.SmsClient.SendAnSmsAsync(new SendSmsRequest
       {
           To = participant.Match.PhoneNumber,
           From = _config["VONAGE_NUMBER"],
           Text = msg
       });
   }
}

ミドルウェアの設定

そのためにいくつかのミドルウェアを使っている。データベースへの接続を維持するためにデータベース・コンテキストを使っている。そして VonageClientを使って Vonage に API リクエストを行い、コンフィギュレーション・オブジェクトを使って Vonage の番号を取り出しています。そして AuthProviderを使って認証状態を取得しています。

これらのサービスをすべてアプリに登録する必要がある。そのために Startup.csに入って ConfigureServicesメソッドを見つける。そこに以下を追加する:

services.AddDbContext<SecretSantaContext>();
var creds = Credentials.FromApiKeyAndSecret(Configuration["API_KEY"], Configuration["API_SECRET"]);
services.AddSingleton(new VonageClient(creds));
services.AddScoped<SecretSantaService>();
services.AddScoped<AuthenticationStateProvider, AuthProvider>();

サービスがすべてセットアップされたので、次はAuthenticationとAuthorizationを有効にして、すべてをAuthorizeしなければならない。このまま Startup.csファイルにとどまり Configureメソッドに以下の2行を追加する:

app.UseAuthorization();
app.UseAuthentication();

フロントエンドの構築

バックエンドのすべての作業が終わったので、あとはフロントエンドを構築するだけだ。認可コンポーネントを使用して認可の状態をすべてのコンポーネントに伝搬させるので、まずアプリ全体を CascadingAuthenticationStateコンポーネントで包む必要がある。 App.razorを開き、アプリ全体を <CascadingAuthenticationState></CascadingAuthenticationState>タグでアプリ全体を囲みます。

ログインコンポーネントの追加

を追加する。 Login.razorファイルを追加する。 /Pagesこの中に、ログインを処理する入力と、実際にログインを実行するボタンを追加します:

@inject SecretSantaService SecretSantaService
@inject SecretSantaContext Database
@inject NavigationManager NavigationManager
@using Vonage.Verify
<h3>Login</h3>
Phone Number:
<input class="input-group-text" @bind="_phoneNumber" />
<button class="btn-group-sm" @onclick="StartLogin">Login</button>
<br />
@if (_numberExists == false)
{
    <p1>Nubmer Not Registered</p1>
    <br />
}
<a href="/registration">Register here</a>

次に、ログインを実行するためのロジックを追加します。ベリファイリクエストを開始し、ベリファイが開始されていない場合はユーザーにコードを送信します。そうでなければ、OTPを入力するための確認ページにルーティングします。

@code {
    private string _phoneNumber;
    private bool? _numberExists;

    private async Task StartLogin()
    {
        if (!_phoneNumber.StartsWith("1"))
        {
            _phoneNumber = "1" + _phoneNumber;
        }
        var user = Database.Participants.Where(x => x.PhoneNumber == _phoneNumber).FirstOrDefault();
        if (user != null)
        {
            try
            {
                var verifyId = await SecretSantaService.StartVeriy(_phoneNumber);
                user.RequestId = verifyId;
                await Database.SaveChangesAsync();
                NavigationManager.NavigateTo($"/confirmCode/{verifyId}");
            }
            catch (VonageVerifyResponseException ex)
            {
                if (ex.Response.Status == "10")
                {
                    NavigationManager.NavigateTo($"/confirmCode/{user.RequestId}");
                }
            }
        }
        else
        {
            _numberExists = false;
        }
    }
}

登録ページの追加

新規ユーザーがアプリに電話番号を登録できるようにしたい。そのためには、新しい RegistrationPage.razorファイルを作成し、そこに以下のフォームを追加します:

@inject SecretSantaContext dbContext;
@inject SecretSantaService SecretSantaService
@inject NavigationManager NavigationManager
@inject Microsoft.Extensions.Configuration.IConfiguration Config
@using Vonage.Verify
@page "/registration"
<h3>Register</h3>

<div class="row">
    <div class="col-md-4">
        <EditForm Model="@participant" OnValidSubmit="CreateUser">
            <DataAnnotationsValidator />
            <ValidationSummary />
            Your Phone Number*:<br /><InputText id="phone" @bind-Value="participant.PhoneNumber" /><br />
            Your Name*:<br /><InputText id="Name" @bind-Value="participant.Name" /><br />
            Your Mailing Address*:<br /><InputText id="Address" @bind-Value="participant.Address" /><br />
            Gift ideas (For You!):<br /><InputText id="GiftIdeas" @bind-Value="participant.GiftIdeas" /><br />
            <button type="submit">Register</button>
            <p>*Required fields</p>
        </EditForm>
    </div>
</div>
@if (_userExistsAlready == true)
{
    <p>User exists already try <a href="/">logging in</a></p>
}
@if (!string.IsNullOrEmpty(_error))
{
    <p><b>Error Encountered:</b> @_error</p>
}

次に、create userメソッドを追加して、提案されたユーザーがすでに存在するかどうかデータベースをチェックします。もし存在しなければ、ユーザーを挿入し、Verifyイベントを開始します。そうでなければ、ユーザがすでに存在するため作成に失敗したことを伝えます。また、私はアプリを設定するために管理者の電話番号を持っています。その電話番号がゲームの管理者を決定します。彼らが登録されると、彼らの役割は admin.

@code {
    private SecretSantaParticipant participant = new SecretSantaParticipant();
    private bool? _userExistsAlready;
    private string _error = "";
    private async Task CreateUser()
    {
        participant.PhoneNumber = participant.PhoneNumber.Replace("(", "");
        participant.PhoneNumber = participant.PhoneNumber.Replace(")", "");
        participant.PhoneNumber = participant.PhoneNumber.Replace("-", "");

        if (!participant.PhoneNumber.StartsWith("1"))
        {
            participant.PhoneNumber = "1" + participant.PhoneNumber;
        }
        var userExists = dbContext.Participants.Where(x => x.PhoneNumber == participant.PhoneNumber).Any();
        if (!userExists)
        {

            try
            {
                if (participant.PhoneNumber == Config["ADMIN_NUMBER"])
                {
                    participant.Role = "admin";
                }
                else
                {
                    participant.Role = "user";
                }

                var verifyRequestId = await SecretSantaService.StartVeriy(participant.PhoneNumber);
                participant.RequestId = verifyRequestId;
                dbContext.Participants.Add(participant);
                dbContext.SaveChanges();
                NavigationManager.NavigateTo($"/confirmCode/{verifyRequestId}");
            }
            catch (VonageVerifyResponseException ex)
            {
                _error = ex.Response.ErrorText;
            }
        }
        else
        {
            _userExistsAlready = true;
        }
    }
}

ログインを確定する

誰かがアカウントを作成したりログインしようとした後、正しいコードを持っていることを検証するページに転送する必要があります。Verifyリクエストを送信した後に NavigationManagerはユーザーを新しいURLにルーティングします: NavigationManager.NavigateTo($"/confirmCode/{verifyRequestId}");- という新しいURLにユーザーをルーティングしていることがわかります。という新しいRazorコンポーネントを作成します。 CodeConfirmationPage.razor.このページは、最終的にコードの確認を試みる検証IDを、パスを通してパラメータとして受け取ります。このページには簡単な入力ボックスとボタンがあり、確認を試みます。認証が成功したら、ルートページに戻り、アプリの残りの部分にルーティングできるようになります。

@using Microsoft.AspNetCore.Identity
@inject SecretSantaService VonageService
@inject SecretSantaContext db
@inject NavigationManager NavigationManager
@inject AuthenticationStateProvider Provider

@page "/confirmCode/{VerifyRequestId}"

<h3>Confirm Code!</h3>
<input class="input-group-text" @bind="_code" />
<button class="btn-group-lg" @onclick="CheckCode">Confirm</button>

@if (_authenticated == false)
{
    <p>Authentication Successful</p>
}

@code {
    [Parameter]
    public string VerifyRequestId { get; set; }
    private string _code;
    private bool? _authenticated;

    private async Task CheckCode()
    {
        _authenticated = await VonageService.ConfirmCode(VerifyRequestId, _code);
        if (_authenticated == true)
        {
            var user = db.Participants.Where(x => x.RequestId == VerifyRequestId).FirstOrDefault();
            ((AuthProvider)Provider).AuthorizeUser(user);
            NavigationManager.NavigateTo("/");
        }
    }
}

Accountページ

最後に追加するのは、実際のアカウントページです。このページでは、ユーザーが管理者であるかどうかによって、アクセスレベルに違いがあります。実際のゲームが開始されるとき、管理者は全員が正しくログインしていることを確認し、ゲームが開始されたというメッセージを全員に送ることができます。

このページの表示部分には、全員の名前とアカウント情報、そしてマッチした相手を表示します(まだマッチが保留中でないと仮定しています)。また、誰かが更新を選択した場合に対応できるように、住所とギフトアイデアフィールドは編集可能なままにします。という名前のrazorファイルを作成し AccountComponent.razorという名前のrazorファイルを作成し、以下を追加します:

@inject SecretSantaContext Db
@inject AuthenticationStateProvider Provider
@inject NavigationManager NavigationManager
@inject SecretSantaService SecretSantaService
@using System.Security.Claims
<h3>Accounts</h3>
<table class="table-bordered">
    <tr>
        <th>Your Name</th>
        <td>@participant.Name</td>
    </tr>
    <tr>
        <th>Your Address</th>
        <td><input class="input-group" @bind="participant.Address" /></td>
    </tr>
    <tr>
        <th>Gift Ideas For You</th>
        <td><input class="input-group" @bind="participant.GiftIdeas" /></td>
    </tr>
    @if (participant.Match != null)
    {
        <tr>
            <th>Your Secret Santa</th>
            <td>@participant.Match.Name</td>
        </tr>
        <tr>
            <th>Gift Ideas</th>
            <td>@participant.Match.GiftIdeas</td>
        </tr>
        <tr>
            <th>Your Secret Santa's Address</th>
            <td>@participant.Match.Address</td>
        </tr>
    }
    else
    {
        <tr>
            <th>Status</th>
            <td>Pending match</td>
        </tr>
    }
</table>
@if (_isAdmin)
{
    <h3>Admin Section</h3>
    <table class="table-bordered">
        <thead>
            <tr>
                <th>Name</th>
                <th>Phone Number</th>
                <th>Address</th>
                <th>Gift ideas</th>
                <th>Matched?</th>
            </tr>
        </thead>
        @foreach (var par in _participants)
        {
            <tr>
                <td>@par.Name</td>
                <td>@par.PhoneNumber</td>
                <td>@par.Address</td>
                <td>@par.GiftIdeas</td>
                <td>@(par.Match!=null)</td>
            </tr>
        }
    </table>
    <button @onclick="Shuffle" class="btn-group-lg">Shuffle And Send</button>
    <button @onclick="SecretSantaService.NotifyUsers">Notify Participants</button>
    <br />
}
<p>@msg</p>
<button style="cursor:pointer" @onclick="UpdateAccount">Update Account</button>
<a @onclick="Logout" href="">Log Out</a>

このコードでは、ページを初期化するメソッドを用意する。認証状態のIDが管理者であるとします。その場合、データベースに問い合わせ、現在のゲーム参加者のリストを取得し、別のテーブルに表示します。ユーザーをシャッフルしてシークレットサンタを割り当てるボタンを用意し、管理者がコンテストを開始するボタンを用意します。

@code {
    SecretSantaParticipant participant = new SecretSantaParticipant();
    List<SecretSantaParticipant> _participants = new List<SecretSantaParticipant>();
    string msg;
    bool _isAdmin;

    protected override async Task OnInitializedAsync()
    {
        var user = (await ((AuthProvider)Provider).GetAuthenticationStateAsync()).User.Claims.First(x => x.Type == ClaimTypes.Name).Value;
        participant = Db.Participants.ToList().FirstOrDefault(x => x.PhoneNumber == user);
        _isAdmin = participant.Role == "admin";
        if (_isAdmin)
        {
            _participants = Db.Participants.ToList();
        }
        StateHasChanged();
    }

    private async void Shuffle()
    {
        await SecretSantaService.ShuffleUsers();
    }

    private void Logout()
    {
        ((AuthProvider)Provider).LogOutUser();

    }
    private async void UpdateAccount()
    {
        var par = Db.Participants.FirstOrDefault(x => x.PhoneNumber == participant.PhoneNumber);
        par = participant;

        await Db.SaveChangesAsync();
        msg = "Account Updated";

        try
        {
            await SecretSantaService.NotifyUserOfUpdate(par);
        }
        catch (Exception ex) { msg = ex.Message; }
        StateHasChanged();
    }
}

インデックスにルートを設定する

アプリをセットアップするために必要なコード関連の最後の作業は、ファイルの中身を Index.razorファイルの内容を AuthorizeViewを追加することで、Auth sateが許可されていればAccountページが表示され、そうでなければログインページが表示されます。index.razorファイルに以下を追加する:

@page "/"

<AuthorizeView>
    <Authorized>
        <AccountComponent></AccountComponent>
    </Authorized>
    <NotAuthorized>
        <Login></Login>
    </NotAuthorized>
</AuthorizeView>

構成

アプリを書いたので、データベースをセットアップし、アプリに適切な環境変数を追加する必要がある。

appsettings.json

ファイルを開き appsettings.jsonファイルを開き、以下のキーを追加する:

"CONNECTION_STRING": "Host=localhost;Database=secretsantausers;User Id=username;Password=password;Port=5432",
"API_KEY": "API_KEY",
"API_SECRET": "API_SECRET",
"VONAGE_NUMBER": "VONAGE_NUMBER"

を設定する。 API_KEYAPI_SECRETを設定します。 Vonageダッシュボード.を設定します。 VONAGE_NUMBERVonageバーチャル番号.管理者番号を、ゲームの管理者にしたい人(おそらくあなた自身)の携帯電話番号に設定する。最後に CONNECTION_STRINGをデータベースの接続文字列に設定します。

データベースの移行

最後に、データベースを移行する必要があります。これを行うには、エンティティフレームワークツールが必要です:

dotnet tool install --global dotnet-ef

その後、fluentツールを実行してマイグレーションを作成する:

dotnet ef migrations add initial_create

最後に、fluentからアップデートツールを実行して、適切なマイグレーションをすべて適用します:

dotnet ef database update

結論

これで完了だ!これで、IIS Expressの再生ボタンを押すか、ターミナルから dotnet runコマンドで実行できます。これで準備は完了だ!

その他のリソース

  • Verify APIの包括的な概要については、Verify APIのドキュメントサイトをご覧ください。 ドキュメントウェブサイト.

  • SMS APIのその他の使用方法はこちらをご覧ください。 こちら

  • このデモのすべてのソースコードは GitHub

シェア:

https://a.storyblok.com/f/270183/384x384/73d57fd8eb/stevelorello.png
Steve Lorelloヴォネージの卒業生

元.NETデベロッパーアドボケイト @Vonage、フルスタック・ポリグロティック・ソフトウェア・エンジニア、AI/ML