チュートリアル: Microsoft Dataverse を使用して ASP.NET Core Blazor WebAssembly アプリを作成する

このチュートリアルの手順を使用して、Dataverse に接続する Blazor WebAssembly アプリを作成します。 この記事の焦点は、特定の Dataverse インスタンスでユーザーを認証し、データを取得するために必要な手順を理解することです。

Blazor WebAssembly は、ASP.NET Core Blazor で使用可能な 2 つのホスティング モデルの 1 つです。 もう 1 つは Blazor Server です。 違いの詳細については、ASP.NET Core Blazor ホスティング モデル をご覧ください。

このチュートリアルは、ASP.NET Core Blazor WebAssembly スタンドアロンアプリを Microsoft Entra ID で保護する の記事に記載の手順を基にしています。 Dataverse は認証に Microsoft Entra ID を使用するため、このチュートリアルでは、提供されたアプリテンプレートを使用して作成した基本アプリを Dataverse に接続できるように変更する方法を説明します。

ゴール

このチュートリアルを完了すると、認証されたユーザーがアクセスできる Dataverse アカウント テーブルからのデータを表示する Blazor WebAssembly アプリが作成されます。

 このチュートリアルの目標を表します。

前提条件

このチュートリアルを使用するには、以下が必要です。

  • データベースで Dataverse 環境に アクセスする
  • アカウント テーブルと連絡先テーブルへの読み取りアクセスを提供するセキュリティ ロールを持つ Dataverse ユーザー
  • C# プログラミング言語についての理解
  • ASP.NET Core Blazor の理解は役に立ちますが必須ではありません
  • ASP.NET と Web 開発 ワークロードがインストールされた Visual Studio 2022 の最新のバージョン。

ステップ 1: データベースに関する前提条件と情報を確認する

環境が適切に構成されていること、および手順 2 でアクションを実行する場所を理解していることを確認しましょう。

Dataverse データベースを確認する

  1. Power Apps にサインインします。

  2. ナビゲート ウィンドウで ソリューション を選択します。

    Dataverse データベースのない環境を示すメーカー ポータル。

  3. インストールされているソリューションのリストが表示されない場合は、上部にある環境セレクターを使用して、データベースがある別の環境を選択してください。 それ以外の場合は、新しい環境を作成します。

Dataverse Web API URI を取得する

インスタンス Web API サービスのルート URL が必要です。 この URL は、Dataverse 環境の開発者向けリソース ページにあります。

開発者向けリソースの表示またはダウンロード にある指示に従って、URLをコピーします。

次のようになります。https://yourorgname.api.crm.dynamics.com/api/data/v9.2/

  1. Power Apps にサインインします。

  2. 左上隅の [ワッフル] アイコンを選択してから 管理者 を選択します。

     Microsoft 365 管理センターへのナビゲーション。

  3. Microsoft 365 管理センターの左側のナビゲーションで、すべて表示 を選択してから ID を選択します。

     Microsoft Entra 管理センターへのナビゲーション。

  4. Microsoft Entra 管理センターで、左側のナビゲーション ウィンドウで アプリケーション ノードを展開し、アプリの登録 を選択します。

     Microsoft Entra アプリの登録ページに移動する。

ここから手順 2 が始まります。

ステップ 2: 認証用に Microsoft Entra ID を使用して Blazor WebAssembly スタンドアロンアプリを作成する

ASP.NET Core Blazor WebAssembly スタンドアロン アプリを Microsoft Entra ID で保護する 記事では、アプリを作成するための完全な手順が掲載されています。

これらのステップでは、Microsoft Entra ID でアプリ登録を作成する方法と .NET Core CLI コマンドを実行して、Microsoft Entra ID 認証のサポートを受けて基本的なアプリの足場を生成する方法について説明します。

注意

これらの指示では .NET Core CLI コマンドを使用してアプリを生成します。 Blazor WebAssembly アプリを作成するための Visual Studio プロジェクト テンプレートがありますが、このチュートリアルはそのテンプレートで検証されていません。

ASP.NET Core Blazor WebAssembly スタンドアロン アプリを Microsoft Entra ID で保護する に移動して、指示に従って、基本的なアプリ プロジェクトを生成します。

アプリが実行されることを確認する

ASP.NET Core Blazor WebAssembly スタンドアロン アプリを Microsoft Entra ID で保護する に記載の手順を完了した後、Visual Studio で F5 キーを押してアプリを実行することができます。

変更が行われる前の Blazor WebAssembly アプリの規定動作。

この時点で、ログインしているかどうかにかかわらず、アプリのすべての機能が動作します。 Microsoft Entra ID テナントのメンバーのみがサインインできます。

ステップ 3: API アクセス許可を付与する

Dataverse に接続するには、アプリが接続するための権限を構成する必要があります。

  1. Microsoft Entra ID でアプリの登録に戻り、API アクセス許可 セクションで、権限を追加する を選択します。

    登録済みアプリケーションの API 権限設定ページ。

  2. API 権限を要求する エリアで、自分の組織が使用する API を選択して、Dataverse を検索します。

    Dataverse 権限を検索しています。

  3. Dataverse を選択します。

  4. user_impersonation のアクセス許可を選択する

    Dataverse user_impersonation 権限を追加しています。

    注意

    Dynamics CRMCommon Data Service、および Dataverse は同じサービスを参照します。

  5. アクセス許可の追加 を選択します。

  6. (オプション) 構成済みのアクセス許可 については、使用している Microsoft Entra ID テナント名に管理者の同意を付与する を選択します。 下のスクリーンショットでは、テナント名は 'デフォルトディレクトリ' です。 あなたのものは違うかもしれません。

    登録済みアプリケーションの管理者の同意を付与するオプションボタンを表示するボタン。

    ここで管理者の同意を付与しない場合は、次回アプリケーションにログインするときに選択できます。

ステップ 4: コードの変更を適用する

次のファイルに変更を適用して、アプリケーションで Dataverse データを表示できるようにします。

\wwwroot\appsettings.json

次の 後で タブの変更を適用して、Dataverse への接続の構成データを追加します。

  • 22222222-2222-2222-2222-222222222222 は、使用するテナント ID を表しています。
  • 11111111-1111-1111-1111-111111111111 は、アプリケーションの登録で作成したアプリケーション (クライアント) ID 値を表します。
  • 必ず https://yourorg.api.crm.dynamics.com以前コピーした URL に置き換えてください。
{
  "AzureAd": {
    "Authority": "https://login.microsoftonline.com/22222222-2222-2222-2222-222222222222",
    "ClientId": "11111111-1111-1111-1111-111111111111",
    "ValidateAuthority": true
  }
}

Program.cs

  1. Microsoft.Extensions.Http NuGet パッケージをインストールします。

    1. ソリューション エクスプローラーでプロジェクトを右クリックして、NuGet パッケージを管理する... を選択します。
    2. 閲覧する を選択して、Microsoft.Extensions.Http を検索します。
    3. パッケージの最新版をインストールします。

    必要な NuGet パッケージのインストール。

  2. 先に タブの生成されたコードを 後で タブのコードに置き換えます。BlazorSample は作成したプロジェクトの名前なので異なります。

using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using BlazorSample;

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

builder.Services.AddMsalAuthentication(options =>
{
    builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
    options.ProviderOptions.DefaultAccessTokenScopes
        .Add("https://graph.microsoft.com/User.Read");
});

await builder.Build().RunAsync();

\Pages\FetchAccounts.razor を追加します

これは、アカウント情報を表示する新しいページです。

  1. ソリューション エクスプローラーで、ページ を右クリックして、追加 > Razor コンポーネント… を選択します コンテキスト メニューから、FetchAccounts.razor と名前を付けます。

  2. ファイルのコードを以下のコードに置き換えます。

    @page "/fetchaccounts"
    @using Microsoft.AspNetCore.Components.WebAssembly.Authentication
    @using System.Net.Http.Headers
    @using System.Net.Http.Json
    @using Microsoft.Extensions.Logging;
    @using System.Text.Json.Serialization;
    @inject IAccessTokenProvider TokenProvider
    @inject IHttpClientFactory ClientFactory
    @inject ILogger<FetchAccounts> logger;
    
    <AuthorizeView>
        @*Only show the list if the user is signed in and authorized*@
        <Authorized>
            <h3>Fetch Accounts</h3>
    
            @if (accounts != null)
            {
                <table class="table">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Main Phone</th>
                            <th>City</th>
                            <th>Primary Contact</th>
                            <th>Email (Primary Contact)</th>
                        </tr>
                    </thead>
                    <tbody>
                        @foreach (Account account in accounts.value)
                        {
                            <tr id="@account.accountid">
                                <td>
                                    @((account.name != null)
                                    ? account.name
                                    : string.Empty)
                                </td>
                                <td>
                                    @((account.telephone1 != null)
                                    ? account.telephone1
                                    : string.Empty)
                                </td>
                                <td>
                                    @((account.address1_city != null)
                                    ? account.address1_city
                                    : string.Empty)
                                </td>
                                <td>
                                    @((account.primarycontactid != null)
                                    ? (account.primarycontactid.fullname != null
                                        ? account.primarycontactid.fullname
                                        : string.Empty)
                                    : string.Empty)
                                </td>
                                <td>
                                    @((account.primarycontactid != null)
                                    ? (account.primarycontactid.emailaddress1 !=null
                                        ? account.primarycontactid.emailaddress1
                                        : string.Empty)
                                    : string.Empty)
                                </td>
                            </tr>
                        }
                    </tbody>
                </table>
            }
            else
            {
                <p><em>@message</em></p>
            }
        </Authorized>
        <NotAuthorized>
            <h3>Authentication Failure!</h3>
            <p>You're not signed in.</p>
        </NotAuthorized>
    </AuthorizeView>
    
    
    @code {
    
        //The collection of Account records to display
        private AccountCollection accounts;
    
        //An informational message
        private string message = "Loading...";
    
        //Contains data about an error returned from the Web API
        private Error error;
    
        // Method invoked when the component is ready to start, having received its initial parameters from its parent in the render tree.
        // Override this method if you will perform an asynchronous operation and want the component to refresh when that operation is completed.
        protected override async Task OnInitializedAsync()
        {
            // Tries to get an access token for the current user with the default set of permissions.
            var tokenResult = await TokenProvider.RequestAccessToken();
    
            // If the token request was successful
            if (tokenResult.TryGetToken(out var token))
            {
                //Creates an HttpClient based on the named definition found in Program.Main
                var client = ClientFactory.CreateClient("DataverseClient");
    
                //Prepare the request to get the data
                var request = new HttpRequestMessage()
                {
                    Method = HttpMethod.Get,
                    RequestUri = new Uri($"{client.BaseAddress}accounts?" +
                    "$select=name,telephone1,address1_city&" +
                    "$expand=primarycontactid($select=fullname,emailaddress1)")
                };
                //Add the access token
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.Value);
                //Specify a JSON result is expected
                request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                //Limit the number of results to 10
                request.Headers.Add("Prefer", "odata.maxpagesize=10");
    
                //Send the request
                var response = await client.SendAsync(request);
    
                if (response.IsSuccessStatusCode)
                {
                    //Parse the JSON returned into a strongly typed AccountCollection
                    accounts = await response.Content.ReadFromJsonAsync<AccountCollection>();
                }
                else
                {
                    //Parse the JSON returned into a strongly typed Error
                    error = await response.Content.ReadFromJsonAsync<Error>();
                    error.statuscode = (int)response.StatusCode;
                    error.reason = response.ReasonPhrase;
                    //Display a message to the user
                    message = "An error occurred.";
                    //Log the details so they can be seen in the browser console
                    logger.LogError($"{error.detail.message}");
    
                }
    
            }
            else
            {
                // Notify user that the token request was not successful
                message = "There was a problem authenticating.";
            }
    
        }
    
    
        // The result will be a JSON object with an array of entities set to the value property
        public class AccountCollection
        {
            public Account[] value { get; set; }
        }
    
        //Just the properties of the Account EntityType used for this sample
        // See https://learn.microsoft.com/power-apps/developer/data-platform/webapi/reference/account
        public class Account
        {
    
            public Guid accountid { get; set; }
    
            public string name { get; set; }
    
            public string telephone1 { get; set; }
    
            public string address1_city { get; set; }
    
            public Contact primarycontactid { get; set; }
    
        }
    
        //Just the properties of the Contact EntityType that are expanded from the Account entity
        // See https://learn.microsoft.com/power-apps/developer/data-platform/webapi/reference/contact
        public class Contact
        {
    
            public string fullname { get; set; }
    
            public string emailaddress1 { get; set; }
        }
    
        // Contains the error data returned by the Web API and the HttpMessageResponse
        public class Error
        {
            [JsonPropertyName("error")]
            public ErrorDetail detail { get; set; }
            public int statuscode { get; set; }
            public string reason { get; set; }
    
        }
    
        //Contains data from the Web API
        //See https://learn.microsoft.com/powerapps/developer/data-platform/webapi/compose-http-requests-handle-errors#parse-errors-from-the-response
        public class ErrorDetail
        {
            public string code { get; set; }
            public string message { get; set; }
    
        }
    }
    

このコードでは、次のことが行われます。

  1. 認証されたユーザーのみがデータを含むページを表示できるようにします。
  2. 取得後にアカウント データを表示するテーブルを定義します。
  3. アクセス トークンをリクエストし、そのトークンを HttpRequestMessage とともに使用して、Dataverse からデータを取得します。
  4. サービスから返された JSON が逆シリアル化されるときに型指定されたデータを有効にするクラスを定義します。

\Shared\NavMenu.razor

このファイルを編集して、fetchaccounts razor コンポーネント ページを追加します。

このノードを <nav class="flex-column"> エレメント内の好きな場所に追加します。

<div class="nav-item px-3">
   <NavLink class="nav-link" href="fetchaccounts">
         <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch Accounts
   </NavLink>
</div>

ステップ 5: 機能することを確認する

Visual Studio で、F5 キーを押して、コードを変更してアプリを起動します。

  1. ログインする前に、アカウントを取得 へナビゲートします。 エラー通知が表示されるはずです。

  2. Dataverse データにアクセスできるユーザーとしてサインインします。

    注意

    ユーザーは、初めてログインするときに次のようなダイアログが表示されることが予想されます。

    アプリケーションに対して同意するようにユーザーに促すダイアログ。

    続行するには 同意する をクリックしてください。

  3. アカウントを取得 へナビゲートして、アカウント データが期待どおりに表示されることを確認します。

    完了が正常におこなわれた際に期待される最後の動作。

関連項目

Blazor WebAssembly のグローバル Discovery サービスを使用する
クイック スタート: Blazor Server Web API サンプル (C#)
ASP.NET Core Blazor WebAssembly スタンドアロンアプリを Microsoft Entra ID で保護する
チュートリアル: アプリを Microsoft Entra ID に登録する
Dataverse で OAuth を使用する
Dataverse Web API を使用する

注意

ドキュメントの言語設定についてお聞かせください。 簡単な調査を行います。 (この調査は英語です)

この調査には約 7 分かかります。 個人データは収集されません (プライバシー ステートメント)。