ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Blazor Wasm 에서 Dataverse API 연결 - 2
    Blazor 2022. 12. 22. 13:14
    728x90

    Blazor Wasm 에서 Dataverse API 연결 - 2

    블레이저 웹 어셈블리에서 Dataverse를 서버로서 사용하는 방법에 대해 알아본다. Dataverse API를 사용하고 Azure AD를 통해 인증을 실행한다. Blazor Wasm 에서 Dataverse API 연결에서 이어진다.

    Dataverse API 인증 세팅

    1. Power Apps(https://make.powerapps.com/) 에 접속한다. Dataverse를 접속하려는 환경으로 변경한다.
    2. 우상단의 톱니바퀴 아이콘 -> 개발자 리소스 -> 웹 API 엔드포인트를 복사한다.

      화면 캡처 2022-12-21 113018

      화면 캡처 2022-12-21 113109
    3. 클라이언트 프로젝트의 'wwwroot/appsettings.json' 파일을 연다. 그 후 CDSWebAPI Key 값으로 하는 항목들을 추가한다. 아래를 참고 하자. Power Platform 환경 URL의 경우 웹 API 엔드포인트 에서 /api/data/v9.2 를 제외한 앞부분을 집어넣으면 된다.
    4. "AzureAd": { "ClientId": "{앱 클라이언트 ID}", "Authority": "https://login.microsoftonline.com/{Azure AD 테넌트}/", "ValidateAuthority": true }, "CDSWebAPI": { "ResourceUrl": "{Power Platform 환경 URL}", "Version": "v9.2", "TimeoutSeconds": 30 } }
    
    4. 이후 Nuget Package 관리자로 들어가 `Microsoft.Extensions.Http` 를 설치한다.<br><br>![화면 캡처 2022-12-21 145551](https://user-images.githubusercontent.com/39551265/208832052-cedee514-ea84-4f93-a3bb-e115ab2f22e4.png)<br>
    
    5. Program.cs 파일을 열아 아래와 같은 코드를 추가한다. builder를 선언한 후인 bulider.RootComponents.Add 아래에 추가한다.
    
    ```c#
    // wwwroot/appsettings.json 에서 세팅값을 가져온다.
    var CDSWebApiConfig = builder.Configuration.GetSection("CDSWebAPI");
    var resourceUrl = CDSWebApiConfig.GetSection("ResourceUrl").Value;
    var version = CDSWebApiConfig.GetSection("Version").Value;
    var timeoutSeconds = int.Parse(CDSWebApiConfig.GetSection("TimeoutSeconds").Value);
    
    // 구성 요소(component) 페이지에서 사용할 수 있는 HttpClient 정의 작성 CDSClient는 원하는 이름으로 변경해도 좋다.
    builder.Services.AddHttpClient("CDSClient", client =>
    {
        client.BaseAddress = new Uri($"{resourceUrl}/api/data/{version}/");
        client.Timeout = TimeSpan.FromSeconds(timeoutSeconds);
        client.DefaultRequestHeaders.Add("OData-Version", "4.0");
        client.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
    });
    1. builder.Services.AddMsalAuthentication(options => 안에 다음과 같은 코드를 추가한다. 기본 인증 자격 증명을 설정한다.
      options.ProviderOptions.DefaultAccessTokenScopes.Add($"{resourceUrl}/user_impersonation");

    사용자(Contact) 데이터 가져오는 페이지 만들기

    1. Power Apps 포털에서 확인할 수 있는 account 테이블에 저장된 리스트를 불러올 것이다.

      화면 캡처 2022-12-22 112552
    2. Pages 폴더에 razor 페이지를 추가한다. 그 후 다음과 같은 코드를 추가한다.
    @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>
        @*로그인된 사용자만 안의 내용을 볼 수 있음*@
        <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 {
    
        //검색 결과의 account의 레코드 저장
        private AccountCollection accounts;
    
        //결과 메시지
        private string message = "Loading...";
    
        //Web API의 에러 반환 저장
        private Error error;
    
    
        // 페이지 시작시 실행
        protected override async Task OnInitializedAsync()
        {
            // 기본 엑세스 토큰을 가져옴
            var tokenResult = await TokenProvider.RequestAccessToken();
    
            // 토큰을 받아오는 것에 성공시
            if (tokenResult.TryGetToken(out var token))
            {
                //HttpClient를 만든다. 이때 Program.cs 파일에서 만든정의를 가져온다.
                var client = ClientFactory.CreateClient("CDSClient");
    
                //데이터를 가져올 GET을 작성(기본적으로 ODATA 형식을 사용)
                var request = new HttpRequestMessage()
                    {
                        Method = HttpMethod.Get,
                        RequestUri = new Uri($"{client.BaseAddress}accounts?" +
                            "$select=name,telephone1,address1_city&" +
                            "$expand=primarycontactid($select=fullname,emailaddress1)&" +
                            "$orderby=createdon desc")
                    };
                //헤더에 토큰을 추가
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.Value);
                request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                //반환 값의 한도를 10으로 지정(더 많이 받아오려면 숫자를 변경 5000개 까지 가능)
                request.Headers.Add("Prefer", "odata.maxpagesize=10");
    
                //리퀘스트 전송
                var response = await client.SendAsync(request);
    
                if (response.IsSuccessStatusCode)
                {
                    var str = await response.Content.ReadAsStringAsync();
                    //JSON 반환값으로 AccountCollection 타입의 모델변환
                    accounts = await response.Content.ReadFromJsonAsync<AccountCollection>();
                }
                else
                {
                    //JSON 반환값으로 Error 타입의 모델변환
                    error = await response.Content.ReadFromJsonAsync<Error>();
                    error.statuscode = (int)response.StatusCode;
                    error.reason = response.ReasonPhrase;
                    message = "An error occurred.";
                    logger.LogError($"{error.detail.message}");
    
                }
    
            }
            else
            {
                // 토큰을 받아오지 못했을 경우
                message = "There was a problem authenticating.";
            }
    
        }
    
    
        // 리퀘스트 반환 값을 정의할 모델 value라고 이름짓는건 value 배열값 형태로 JSON이 반환되기 때문이다.
        public class AccountCollection
        {
            public Account[] value { get; set; }
        }
    
        //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; }
    
        }
    
        //Contact에 조회로 지정한 
        public class Contact
        {
    
            public string fullname { get; set; }
    
            public string emailaddress1 { get; set; }
        }
    
        // HttpMessageResponse의 Error 반환 모델 
        public class Error
        {
            [JsonPropertyName("error")]
            public ErrorDetail detail { get; set; }
            public int statuscode { get; set; }
            public string reason { get; set; }
    
        }
    
        public class ErrorDetail
        {
            public string code { get; set; }
            public string message { get; set; }
    
        }
    }
    1. shared/NavMenu.razor 페이지에서 <div class="nav-item px-3>안에 다음과 같은 코드를 추가해 이동 메뉴를 추가한다.
    <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>
    1. 이후 실행해서 해당 페이지를 열어서 다음과 같이 account테이블 정보가 불러와지는것을 확인 가능하다. 해당 페이지는 Azure AD에 로그인한 사용자여야 한다.

      화면 캡처 2022-12-22 113153
    728x90
    반응형

    댓글

Designed by Tistory.