원문참조

간단한 웹 API 빠른 시작 샘플(C#)

Dynamics CRM 2016
적용 대상: Dynamics 365 (online), Dynamics 365 (on-premises)

이 샘플은 Microsoft Dynamics 365 Server로 인증한 다음 기본적인 웹 API 작업인 WhoAmI Function를 호출하는 방법을 보여줍니다. 다른 웹 API 샘플과 달리 이 샘플은 다른 비표준 도우미 라이브러리 또는 추가 소스 파일에 종속되지 않습니다. 모든 소스 코드는 논리 흐름 및 인증 프로세스를 이해할 수 있도록 하나의 Program.cs 파일에 들어있습니다. 이 샘플에서는 온라인, 온-프레미스 및 인터넷 연결 배포(IFD)를 사용합니다.
이 샘플에서 일반 요구 사항은 다음과 같습니다.

  • 솔루션을 열고 구축하려면 Microsoft Visual Studio 2015 이후 버전이 필요합니다. 이 제품인 무료 버전인 Visual Studio Express 또는 Visual Studio Community를 다운로드할 수 있습니다.
  • 온라인 또는 온-프레미스 Microsoft Dynamics 365 Server에 연결하기 위한 인터넷 또는 네트워크 연결.
  • 사용자 Microsoft Dynamics 365 Server (온라인 또는 온-프레미스)의 사용자 계정.
  • 연습: Azure Active Directory를 사용하여 Dynamics 365 등록에서 설명한 대로 Dynamics 365(온라인)를 사용하는 경우 샘플 응용 프로그램이 Active Directory Azure에 등록되어야 합니다.
  • 연습: Active Directory를 사용하여 Dynamics 365 등록에서 설명한 대로 인터넷 연결 배포(IFD)와 함께 Dynamics 365(온-프레미스)를 사용하는 경우 샘플 응용 프로그램이 사용자의 Active Directory 테넌트로 등록되어야 합니다.
System_CAPS_important중요
기본적으로 처음에는 솔루션이 성공적으로 빌드되지 않습니다. 사용자 계정 및/또는 응용 프로그램 등록 정보를 제공하기 위해 소스 코드에서 //TODO 주석이 있는 줄을 편집해야 합니다.
이 간단한 샘플에서는 Microsoft Dynamics 365 Server에 대한 인증과 HTTP 프로토콜을 사용하여 기본 웹 API 호출 형성의 웹 API를 사용하여 개발하는 데 필요한 두 가지 기본 개념을 보여줍니다.
클라이언트 응용 프로그램에서 어떠한 Dynamics 365 리소스에 액세스하기 전에 인증이 필요합니다. 이 프로세스는 다른 배포 형식에 다른 인증 메커니즘이 필요하며 웹 기반 인증 메커니즘은 여러 프로그래밍 단계가 필요하기 때문에 중요합니다. 온-프레미스 배포에 필요한 Windows 통합 인증은 비교적 간단하며 사용자 이름 및 암호만 필요합니다. 그 후 프로그램은 이후에 인증된 사용자의 에이전트로 작동합니다.
그에 비해 온라인 및 IFD 배포에는 사전에 클라이언트 응용 프로그램 등록이 필요하며 다단계 OAuth 인증 프로세스를 사용합니다.Dynamics 365(온라인) 등록 과정은 문서 연습: Azure Active Directory를 사용하여 Dynamics 365 등록에 설명되어 있습니다.인터넷 연결 배포(IFD)와 Dynamics 365(온-프레미스) 등록 과정은 문서 연습: Active Directory를 사용하여 Dynamics 365 등록에 설명되어 있습니다. 각 후속 웹 API 요청은 OAuth로 인증되어야 합니다. 다행히 복잡한 OAuth 인증은 .NET 클라이언트에 대한 Active Directory 인증 라이브러리(ADAL)를 사용하여 간소화할 수 있습니다. 이는 샘플에 NuGet 패키지 Microsoft.IdentityModel.Clients.ActiveDirectory로 추가됩니다. 이 샘플에서 OAuth 인증은 추가로 메시지 요청에 필요한 OAuth 인증 헤더를 추가하는 OAuthMessageHandler 클래스가 포함되어 캡슐화됩니다. 이후 샘플에서는 지원 인증 기능은 웹 API 도우미 라이브러리에 분리됩니다. 자세한 내용은 Microsoft Dynamics 365에서 사용자 인증을 참조하십시오.
Dynamics 365 웹 API는 OData 사양를 기반으로 하는 REST API이므로 엔터티, 호출 함수 및 동작에 대해 표준 HTTP 요청을 지원합니다. 이 샘플에서는 GET 요청을 사용하여 WhoAmI Function함수를 호출한 다음 이 함수에서 결과 HTTP 응답에 제공된 정보를 사용하는 것을 설명합니다. 이 호출을 지원하기 위해 이 샘플에서 는 몇 가지 표준 라이브러리가 활용됩니다.

먼저 간단한 웹 API 빠른 시작 샘플(C#)로 이동하여 샘플 아카이브 파일(Simple Web API quick-start sample (CS.zip))을 다운로드하고 로컬 폴더에 압축을 풉니다. 이 폴더는 다음 파일을 포함합니다.

파일 목적/설명
Program.cs 이 샘플에 대한 소스 코드를 포함합니다.
SimpleWebApi.sln
SimpleWebApi.csproj
packages.config
AssemblyInfo.cs
App.config
이 샘플에 대한 표준 Microsoft Visual Studio 2015 솔루션, 프로젝트, NuGet 패키지 구성, 어셈블리 정보 및 응용 프로그램 구성 파일입니다.

다음 절차에 따라 이 샘플을 실행하십시오.

  1. 솔루션 파일(SimpleWebApi.sln)을 찾아 두 번 클릭하여 Visual Studio에 솔루션을 로드합니다.
  2. 솔루션 탐색기에서 Program.cs파일을 두 번 클릭하여 편집기에서 엽니다.
  3. Main 메서드 내에서 //TODO 주석을 찾아 필요한 연결 문자열 값을 추가하고 관련된 줄의 주석을 제거합니다.
  4. SimpleWebApi 솔루션을 빌드합니다. 누락되었거나 업데이트되어야 하는 모든 필요한 NuGet 패키지가 자동으로 다운로드되고 설치됩니다.
  5. Visual Studio 내에서 SimpleWebApi 프로젝트를 실행합니다. 모든 샘플 솔루션은 기본적으로 디버그 모드에서 실행되도록 구성됩니다.
  6. 동작은 배포 형식에 따라 다릅니다.
    • 온라인 및 IFD 배포의 경우 콘솔 응용 프로그램에서 사용자 자격 증명 및 암호를 입력할 수 있는 새 창이 열립니다.
    • 온-프레미스 배포의 경우 콘솔 응용 프로그램에서 제공된 Dynamics 365 계정의 암호를 요구하는 메시지가 표시됩니다.

    해당 정보를 제공한 다음 Enter를 누릅니다.

이 파일에 대한 최신 소스는 샘플 다운로드 패키지에 있습니다.
Program.cs

namespace Microsoft.Crm.Sdk.Samples
{
    /// <summary>
    /// A basic Web API client application for Dynamics 365 (CRM). This sample authenticates
    /// the user and then calls the WhoAmI Web API function.
    /// </summary>
    /// <remarks>
    /// Prerequisites:
    ///   -  To run this application, you must have a CRM Online or on-premise account.
    ///   -  For CRM Online or Internet-facing deployments (IFD), the application must be registered
    ///      with Azure Active Directory as described in this article:
    ///      https://msdn.microsoft.com/en-us/library/dn531010.aspx
    ///
    /// The WhoAmI Web API function is documented here:
    ///    https://msdn.microsoft.com/en-us/library/mt607925.aspx
    /// </remarks>
    static class SimpleWebApi
    {
        //TODO: Uncomment then substitute your correct Dynamics 365 organization service
        // address for either CRM Online or on-premise (end with a forward-slash).
        //private static string serviceUrl = "https://mydomain.crm.dynamics.com/myorg/";   // CRM Online
        //private static string serviceUrl = "https://<organization name>.<domain name>/";   // CRM IFD
        //private statics string serviceUrl = "http://myserver/myorg/";        // CRM on-premises
        //TODO: For an on-premises deployment, set your organization credentials here. (If
        // online or IFD, you can you can disregard or set to null.)
        private static string userAccount = "<user-account>";  //CRM user account
        private static string domain = "<server-domain>";  //CRM server domain
        //TODO: For CRM Online or IFD deployments, substitute your app registration values
        // here. (If on-premise, you can disregard or set to null.)
        private static string clientId = "<app-reg-guid>";     //e.g. "e5cf0024-a66a-4f16-85ce-99ba97a24bb2"
        private static string redirectUrl = "<redirect-URL>";  //e.g. "http://localhost/SdkSample"
        static public void Main(string[] args)
        {
            //One message handler for OAuth authentication, and the other for Windows integrated
            // authentication.  (Assumes that HTTPS protocol only used for CRM Online.)
            HttpMessageHandler messageHandler;
            if (serviceUrl.StartsWith("https://"))
            {
                messageHandler = new OAuthMessageHandler(serviceUrl, clientId, redirectUrl,
                         new HttpClientHandler());
            }
            else
            {
                //Prompt for user account password required for on-premise credentials.  (Better
                // approach is to use the SecureString class here.)
                Console.Write("Please enter the password for account {0}: ", userAccount);
                string password = Console.ReadLine().Trim();
                NetworkCredential credentials = new NetworkCredential(userAccount, password, domain);
                messageHandler = new HttpClientHandler() { Credentials = credentials };
            }
            try
            {
                //Create an HTTP client to send a request message to the CRM Web service.
                using (HttpClient httpClient = new HttpClient(messageHandler))
                {
                    //Specify the Web API address of the service and the period of time each request
                    // has to execute.
                    httpClient.BaseAddress = new Uri(serviceUrl);
                    httpClient.Timeout = new TimeSpan(0, 2, 0);  //2 minutes
                    //Send the WhoAmI request to the Web API using a GET request.
                    var response = httpClient.GetAsync("api/data/v8.1/WhoAmI",
                            HttpCompletionOption.ResponseHeadersRead).Result;
                    if (response.IsSuccessStatusCode)
                    {
                        //Get the response content and parse it.
                        JObject body = JObject.Parse(response.Content.ReadAsStringAsync().Result);
                        Guid userId = (Guid)body["UserId"];
                        Console.WriteLine("Your system user ID is: {0}", userId);
                    }
                    else
                    {
                        Console.WriteLine("The request failed with a status of '{0}'",
                               response.ReasonPhrase);
                    }
                }
            }
            catch (Exception ex)
            {
                DisplayException(ex);
                throw;
            }
            finally
            {
                Console.WriteLine("Press <Enter> to exit the program.");
                Console.ReadLine();
            }
        }
        /// <summary> Displays exception information to the console. </summary>
        /// <param name="ex">The exception to output</param>
        private static void DisplayException(Exception ex)
        {
            Console.WriteLine("The application terminated with an error.");
            Console.WriteLine(ex.Message);
            while (ex.InnerException != null)
            {
                Console.WriteLine("\t* {0}", ex.InnerException.Message);
                ex = ex.InnerException;
            }
        }
    }
    /// <summary>
    ///Custom HTTP message handler that uses OAuth authentication thru ADAL.
    /// </summary>
    class OAuthMessageHandler : DelegatingHandler
    {
        private AuthenticationHeaderValue authHeader;
        public OAuthMessageHandler(string serviceUrl, string clientId, string redirectUrl,
                HttpMessageHandler innerHandler)
            : base(innerHandler)
        {
            // Obtain the Azure Active Directory Authentication Library (ADAL) authentication context.
            AuthenticationParameters ap = AuthenticationParameters.CreateFromResourceUrlAsync(
                    new Uri(serviceUrl + "api/data/")).Result;
            AuthenticationContext authContext = new AuthenticationContext(ap.Authority, false);
            //Note that an Azure AD access token has finite lifetime, default expiration is 60 minutes.
            AuthenticationResult authResult = authContext.AcquireToken(serviceUrl, clientId, new Uri(redirectUrl));
            authHeader = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
        }
        protected override Task<HttpResponseMessage> SendAsync(
                 HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            request.Headers.Authorization = authHeader;
            return base.SendAsync(request, cancellationToken);
        }
    }
}
283 Comments
댓글 남기기