简单 Web API 快速入门示例 (C#)

 

适用于: Dynamics 365 (online),Dynamics 365 (on-premises)

此示例演示如何通过 Microsoft Dynamics 365 服务器 的身份验证,然后调用 WhoAmI Function 这一基本 Web API 操作。 与其他 Web API 示例不同,此示例不依赖其他非标准帮助程序库或其他源文件。 其所有源代码均包含在 Program.cs 这一个文件中,用于帮助简化对逻辑流和身份验证流的理解。 此示例支持在线、本地部署和面向 Internet 的部署 (IFD)。

要求

此示例具有以下要求:

重要

根据设计,此解决方案最初不能成功构建。 必须在 //TODO 注释指示的行编辑源代码,以便提供用户帐户和/或应用程序注册信息。

演示

此简单示例演示使用 Web API 执行部署所需的两个基本概念:通过 Microsoft Dynamics 365 服务器 的身份验证和构建使用 HTTP 协议的基本 Web API 调用。

必须先通过身份验证,客户端应用程序才能访问任何 Dynamics 365 资源。 此过程不平凡的原因有两个:不同部署类型需要不同的身份验证机制,以及基于 Web 的身份验证机制通常涉及多个编程步骤。 Windows 集成的身份验证是本地部署所需身份验证,相对来说比较直接,只需要用户名和密码。 此外,此程序将充当已通过身份验证的用户的代理。

相反,在线和 IFD 部署要求提前注册客户端应用程序,然后使用多步骤 OAuth 身份验证过程。Dynamics 365(在线) 的注册流程在演练:使用 Azure Active Directory 注册 Dynamics 365 应用程序 一文中有介绍。 具有 面向 Internet 的部署 (IFD) 的 Dynamics 365(本地) 的注册流程在 演练:使用 Active Directory 注册 Dynamics 365 应用程序 一文中有介绍。 每个后续 Web API 请求都必须通过 OAuth 的身份验证。 幸运的是,OAuth 身份验证的许多复杂环节可以通过使用适用于 .NET 客户端的 Active Directory Authentication 库 (ADAL) 来简化,该库以 NuGet 程序包 Microsoft.IdentityModel.Clients.ActiveDirectory 的形式添加到了示例中。 OAuth 身份验证通过添加 OAuthMessageHandler 类(用于向消息请求添加所需的 OAuth 身份验证头)进一步封装在了此示例中。 在将来的示例中,对身份验证功能的支持单独分离到了 Web API 帮助程序库中。 有关详细信息,请参阅在 Microsoft Dynamics 365 中对用户进行身份验证

Dynamics 365 Web API 是基于 OData 规范的 REST API,因此支持针对实体的标准化 HTTP 请求,以及调用函数和操作。 此示例演示通过 GET 请求调用 WhoAmI Function 函数,然后在产生的 HTTP 响应中使用此函数提供的信息。 此示例利用多个标准库帮助执行该调用:

运行此示例:

首先转到简单 Web 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. "https://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);
        }
    }
}

另请参阅

Web API Reference
Web API 示例
使用 Microsoft Dynamics 365 Web API 帮助程序库 (C# 库)
在 Microsoft Dynamics 365 中对用户进行身份验证

Microsoft Dynamics 365

© 2017 Microsoft。 保留所有权利。 版权