다음을 통해 공유


샘플: Windows 8 데스크톱 최신 OData 앱

 

게시 날짜: 2016년 11월

적용 대상: Dynamics CRM 2015

이 샘플 코드는 Microsoft Dynamics CRM 2015 및 Microsoft Dynamics CRM Online 2015 업데이트용입니다.이 코드는 다운로드 패키지의 다음 위치에서 확인할 수 있습니다.

SampleCode\CS\ModernAndMobileApps\ModernOdataApp

Microsoft Dynamics CRM SDK 패키지를 다운로드합니다.

요구 사항

이 샘플에는 Microsoft.Preview.WindowsAzure.ActiveDirectory.AuthenticationMicrosoft.IdentityModel.Clients.ActiveDirectory NuGet 패키지가 필요합니다. 이러한 패키지는 프로젝트의 솔루션을 로드할 때 자동으로 다운로드 및 설치됩니다.

이 SDK에서 제공된 샘플 코드를 실행하기 위한 요구 사항에 대한 자세한 내용은 샘플 및 도우미 코드 사용을 참조하십시오.

보여 주기

Windows 8 샘플 앱 기본 화면

샘플 앱의 타일 모양 사용자 인터페이스

이 샘플에서는 SDK 어셈블리에 연결하지 않고 조직 웹 서비스에 요청을 보낼 수 있는 Windows 8.1 데스크톱 최신 응용 프로그램을 작성하는 방법을 보여 줍니다. 이 샘플에서는 Microsoft Azure Active Directory Authentication Library(ADAL) 및 OData 프로토콜을 사용합니다.

기본 앱 페이지에 표시되는 타일은 7개이지만 계정 및 작업 타일만 이벤트 처리기 코드에 연결됩니다. 다른 타일은 자리 표시자일 뿐입니다.

예제 코드는 Microsoft Dynamics CRM Online 서버 및 가상 조직에 사용하도록 구성되어 있지만 IFD 서버에도 사용할 수 있습니다.

전체 샘플의 핵심 섹션만 표시하는 코드 조각은 이 항목의 뒷부분에 나와 있습니다.

예제

다음 코드 조각은 조직 웹 서비스로 사용자를 인증하는 방법을 보여 줍니다.


using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Threading.Tasks;
using Windows.UI.Popups;
using Windows.Security.Authentication.Web;
using System.Net;
using System.Threading;
using System.IO;
using System.Text;

namespace ModernOdataApp
{
    /// <summary>
    /// Manages authentication with the organization web service.
    /// </summary>
    public static class CurrentEnvironment
    {
        # region Class Level Members

        private static AuthenticationContext _authenticationContext;

        // TODO Set these string values as approppriate for your app registration and organization.
        // For more information, see the SDK topic "Walkthrough: Register an app with Active Directory".
        private const string _clientID = "893262be-fbdc-4556-9325-9f863b69495b";
        public const string CrmServiceUrl = "https://my-domain.crm.dynamics.com/";

        # endregion

        // <summary>
        /// Perform any required app initialization.
        /// This is where authentication with Active Directory is performed.
        public static async Task<string> Initialize()
        {
            Uri serviceUrl = new System.Uri(CrmServiceUrl + "/XRMServices/2011/Organization.svc/web?SdkClientVersion=6.1.0000.0000");

            // Dyamics CRM Online OAuth URL.
            string _oauthUrl = DiscoveryAuthority(serviceUrl);

            // Obtain the redirect URL for the app. This is only needed for app registration.
            Uri redirectUri = WebAuthenticationBroker.GetCurrentApplicationCallbackUri();

            // Obtain an authentication token to access the web service. 
            _authenticationContext = new AuthenticationContext(_oauthUrl, false);
            AuthenticationResult result = await _authenticationContext.AcquireTokenAsync(CrmServiceUrl, _clientID, redirectUri);

            // Verify that an access token was successfully acquired.
            if (result.Status != AuthenticationStatus.Success)
            {
                if (result.Error == "authentication_failed")
                {
                    // Try again.
                    _authenticationContext = new AuthenticationContext(_oauthUrl, false);
                    result = await _authenticationContext.AcquireTokenAsync(CrmServiceUrl, _clientID, redirectUri);
                }
                else
                {
                    DisplayErrorWhenAcquireTokenFails(result);
                }
            }
            return result.AccessToken;
        }

        /// <summary>
        /// Discover the authentication authority.
        /// </summary>
        /// <param name="serviceUrl">The URL of the organization's SOAP endpoint. </param>
        /// <returns>The authority URL.</returns>
        /// <remarks>The service URL must contain the SdkClient property.</remarks>
        /// <example>https://contoso.crm.dynamics.com/XRMServices/2011/Organization.svc/web?SdkClientVersion=6.1.0.533;</example>
        public static string DiscoveryAuthority(Uri serviceUrl)
        {
            // Use AuthenticationParameters to send a request to the organization's endpoint and
            // receive tenant information in the 401 challenge. 
            Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationParameters parameters = null;
            HttpWebResponse response = null;
            try
            {
                // Create a web request where the authorization header contains the word "Bearer".
                HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(serviceUrl);

                // The response is to be encoded.
                httpWebRequest.ContentType = "application/x-www-form-urlencoded";
                response = (HttpWebResponse)httpWebRequest.GetResponse();
            }

            catch (WebException ex)
            {
                response = (HttpWebResponse)ex.Response;

                // A 401 error should be returned. Extract any parameters from the response.
                // The response should contain an authorization_uri parameter.
                parameters = Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationParameters.
                    CreateFromResponseAuthenticateHeader((response.Headers)["WWW-Authenticate"]);
            }
            finally
            {
                if (response != null)
                    response.Dispose();
            }
            // Return the authority URL.
            return parameters.Authority;
        }

        /// <summary>
        /// Returns a response from an Internet resource. 
        /// </summary>       
        public static WebResponse GetResponse(this WebRequest request)
        {
            AutoResetEvent autoResetEvent = new AutoResetEvent(false);
            IAsyncResult asyncResult = request.BeginGetResponse(r => autoResetEvent.Set(), null);

            // Wait until the call is finished
            autoResetEvent.WaitOne(DefaultRequestTimeout);
            return request.EndGetResponse(asyncResult);
        }

        /// <summary>
        /// Get the DefaultRequestTimeout from the server.
        /// </summary>
        public static TimeSpan DefaultRequestTimeout { get; set; }

        /// <summary>
        /// Display an error message to the user.
        /// </summary>
        /// <param name="result">The authentication result returned from AcquireTokenAsync().</param>
        private static async void DisplayErrorWhenAcquireTokenFails(AuthenticationResult result)
        {
            MessageDialog dialog;

            switch (result.Error)
            {
                case "authentication_canceled":
                    // User cancelled, so no need to display a message.
                    break;
                case "temporarily_unavailable":
                case "server_error":
                    dialog = new MessageDialog("Please retry the operation. If the error continues, please contact your administrator.",
                        "Sorry, an error has occurred.");
                    await dialog.ShowAsync();
                    break;
                default:
                    // An error occurred when acquiring a token so show the error description in a MessageDialog.
                    dialog = new MessageDialog(string.Format(
                        "If the error continues, please contact your administrator.\n\nError: {0}\n\nError Description:\n\n{1}",
                        result.Error, result.ErrorDescription), "Sorry, an error has occurred.");
                    await dialog.ShowAsync();
                    break;
            }
        }
    }
}

이 코드가 작동하려면 먼저 지원되는 ID 공급자(AD FS 또는 Microsoft Azure Active Directory)로 앱을 등록해야 합니다. 그런 다음 코드에서 _clientID 및 CrmServiceUrl의 변수 값을 설정해야 합니다. 클라이언트 ID의 값은 앱 등록 중 정의되었습니다.추가 정보:연습: Active Directory를 사용하여 CRM 앱 등록

예제

다음 코드 조각은 HTTP 요청 시 OData 프로토콜 코드를 사용하여 조직 웹 서비스에서 엔터티 레코드를 검색하는 방법을 보여 줍니다. 인증 액세스 토큰은 인증 헤더에 배치됩니다.


using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace ModernOdataApp
{
    public static class HttpRequestBuilder
    {
        /// <summary>
        /// Retrieve entity record data from the organization web service. 
        /// </summary>
        /// <param name="accessToken">The web service authentication access token.</param>
        /// <param name="Columns">The entity attributes to retrieve.</param>
        /// <param name="entity">The target entity for which the data should be retreived.</param>
        /// <returns>Response from the web service.</returns>
        /// <remarks>Builds an OData HTTP request using passed parameters and sends the request to the server.</remarks>
        public static async Task<string> Retrieve(string accessToken, string[] Columns, string entity)
        {
            // Build a list of entity attributes to retrieve as a string.
            string columnsSet = "";
            foreach (string Column in Columns)
            {
                columnsSet += "," + Column;
            }

            // The URL for the OData organization web service.
            string url = CurrentEnvironment.CrmServiceUrl + "/XRMServices/2011/OrganizationData.svc/" + entity + "?$select=" + columnsSet.Remove(0, 1) + "";

            // Build and send the HTTP request.
            HttpClient httpClient = new HttpClient();
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Get, url);
            req.Method = HttpMethod.Get;

            // Wait for the web service response.
            HttpResponseMessage response;
            response = await httpClient.SendAsync(req);
            var responseBodyAsText = await response.Content.ReadAsStringAsync();

            return responseBodyAsText;
        }
    }
}

참고 항목

모바일 및 최신 앱 작성
Windows Store용 Azure Authentication Library(AAL): 심해 잠수
Azure AD를 사용한 Windows Store 애플리케이션 및 REST 웹 서비스 확보
OData.org

© 2017 Microsoft. All rights reserved. 저작권 정보