在插件中使用Secure Configuration

我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面的微软最有价值专家(Microsoft MVP),欢迎关注我的微信公众号 MSFTDynamics365erLuoYong ,回复409或者20200510可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!

在插件中使用Secure Configuration 的官方文档请参考 Write a plug-in 的 Pass configuration data to your plug-in 章节,本博文参考了 What is Unsecure/Secure Configuration on a Dynamics CRM/365 for Enterprise Plugin? 。在Action中获取输入参数和设置输出参数的值则参考了  Setting Output Parameters in Plugins for Custom Actions

首先我需要修改前面博文 Dynamics 365通过Action调用Graph API获取用户经理信息  创建的Action,将其所有的步骤去掉,然后激活。如下:

 

 

我使用的插件代码如下,我这里面获取了secure configuration的值。

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Net.Http;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Xml.Linq;
using System.Linq;

namespace DemoPlugins
{
    public class GetUserManagerActionPost : IPlugin
    {
        private readonly string _secureString;

        public GetUserManagerActionPost(string unsecureString, string secureString)
        {
            if (String.IsNullOrEmpty(secureString))
            {
                throw new InvalidPluginExecutionException("Secure strings are required for this plugin to execute.");
            }

            _secureString = secureString;
        }

        public void Execute(IServiceProvider serviceProvider)
        {
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            tracingService.Trace($"Enter {this.GetType()} on {DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss:ms")}");
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService orgSvc = serviceFactory.CreateOrganizationService(context.UserId);
            try
            {
                string userEmail = string.Empty;
                if (context.InputParameters.Contains("UserEmail") && context.InputParameters["UserEmail"] is string)
                {
                    userEmail = context.InputParameters["UserEmail"].ToString();
                }
                if (string.IsNullOrEmpty(userEmail))
                {
                    if (context.InputParameters.Contains("User") && context.InputParameters["User"] is EntityReference)
                    {
                        var user = (EntityReference)context.InputParameters["User"];
                        userEmail = orgSvc.Retrieve("systemuser", user.Id, new ColumnSet("internalemailaddress")).GetAttributeValue<string>("internalemailaddress");
                    }
                }
                if (string.IsNullOrEmpty(userEmail))
                {
                    throw new InvalidPluginExecutionException("EmailAddr is empty!");
                }
                tracingService.Trace($"UserEmail = {userEmail} on {DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss:ms")}");
                XElement secureXml = XElement.Parse(_secureString);
                var clientId = (from item in secureXml.Descendants("ClientId") select item).FirstOrDefault().Value;
                var clientSecret = (from item in secureXml.Descendants("ClientSecret") select item).FirstOrDefault().Value;
                var tenantId = (from item in secureXml.Descendants("TenantId") select item).FirstOrDefault().Value;
                var scope = (from item in secureXml.Descendants("Scope") select item).FirstOrDefault().Value;
                string tokenUrl = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";
                AuthResponse authRepsonse = null;
                using (HttpClient httpClient = new HttpClient())
                {
                    var authRequest = new HttpRequestMessage(HttpMethod.Post, tokenUrl);
                    var requestBody = new StringContent($"client_id={clientId}&scope={scope}&client_secret={clientSecret}&grant_type=client_credentials");
                    requestBody.Headers.ContentType.MediaType = "application/x-www-form-urlencoded";
                    authRequest.Content = requestBody;
                    var authResponseStr = httpClient.SendAsync(authRequest).Result.Content.ReadAsStringAsync().Result;
                    tracingService.Trace($"authResponseStr = {authResponseStr} on {DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss:ms")}");
                    using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(authResponseStr)))
                    {
                        DataContractJsonSerializer deseralizer = new DataContractJsonSerializer(typeof(AuthResponse));
                        authRepsonse = (AuthResponse)deseralizer.ReadObject(ms);
                    }
                    if (authRepsonse != null && !string.IsNullOrEmpty(authRepsonse.access_token))
                    {
                        var request = new HttpRequestMessage(HttpMethod.Get, $"https://graph.microsoft.com/v1.0/users/{userEmail}/manager?$select=displayName,mail");
                        //request.Headers.Add("otherheraderitem", "headeritemvalue");
                        //request.Content = new StringContent(inJson, Encoding.UTF8, "application/json");
                        request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authRepsonse.access_token);
                        var getUserResponseStr = httpClient.SendAsync(request).Result.Content.ReadAsStringAsync().Result;
                        tracingService.Trace($"getUserResponseStr = {getUserResponseStr} on {DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss:ms")}");
                        using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(getUserResponseStr)))
                        {
                            DataContractJsonSerializer deseralizer = new DataContractJsonSerializer(typeof(GetUserResponse));
                            var getUserResponse = (GetUserResponse)deseralizer.ReadObject(ms);
                            context.OutputParameters["ManagerName"] = getUserResponse.displayName;
                            context.OutputParameters["ManagerEmail"] = getUserResponse.mail;
                        }
                    }
                    else
                    {
                        throw new InvalidPluginExecutionException($"Get access token error!" + authResponseStr);
                    }
                }
                tracingService.Trace($"Leave {this.GetType()} on {DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss:ms")}");
            }
            catch (Exception ex)
            {
                tracingService.Trace($"{this.GetType()} encountered unexpected exception: {ex.Message + ex.StackTrace} on {DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss:ms")}");
                throw new InvalidPluginExecutionException(ex.Message + ex.StackTrace);
            }
        }
    }

    public class AuthResponse
    {
        public string access_token { get; set; }
        public int expires_in { get; set; }
        public int ext_expires_in { get; set; }
        public string token_type { get; set; }
    }

    public class GetUserResponse
    {
        public string displayName { get; set; }

        public string mail { get; set; }
    }
}

 

 

创建或者更新插件插件程序集后,需要注册步骤。

 

 

注册的步骤如下,注意,一定要注册在PostOperation阶段。

 

我使用的Secure Configuration示例:

<GraphAuthInfo>
<ClientId>xxx</ClientId>
<TenantId>xxxx</TenantId>
<ClientSecret><![CDATA[xxx]]></ClientSecret>
<Scope><![CDATA[https%3A%2F%2Fgraph.microsoft.com%2F.default]]></Scope>
</GraphAuthInfo>

  

posted @ 2020-05-10 18:37  微软MVP(15-18)罗勇  阅读(283)  评论(0编辑  收藏  举报