private void CallWebHooks(ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateWebhookKind kind, String objectHandler = null, Exception exception = null)
        {
            using (var scope = new PnPMonitoredScope("ProvisioningTemplate WebHook Call"))
            {
                var webhooks = new List <ProvisioningWebhookBase>();

                // Merge the webhooks at template level with those at global level
                if (template.ProvisioningTemplateWebhooks != null && template.ProvisioningTemplateWebhooks.Any())
                {
                    webhooks.AddRange(template.ProvisioningTemplateWebhooks);
                }
                if (template.ParentHierarchy?.ProvisioningWebhooks != null && template.ParentHierarchy.ProvisioningWebhooks.Any())
                {
                    webhooks.AddRange(template.ParentHierarchy.ProvisioningWebhooks);
                }

                // If there is any webhook
                if (webhooks.Count > 0)
                {
                    foreach (var webhook in webhooks.Where(w => w.Kind == kind))
                    {
                        var requestParameters = new Dictionary <String, String>();

                        if (exception != null)
                        {
                            // For GET requests we limit the size of the exception to avoid issues
                            requestParameters["__exception"] =
                                webhook.Method == ProvisioningTemplateWebhookMethod.GET ?
                                exception.Message : exception.ToString();
                        }

                        SimpleTokenParser internalParser = new SimpleTokenParser();
                        foreach (var webhookparam in webhook.Parameters)
                        {
                            requestParameters.Add(webhookparam.Key, parser.ParseString(webhookparam.Value));
                            internalParser.AddToken(new WebhookParameter(webhookparam.Key, requestParameters[webhookparam.Key]));
                        }
                        var url = parser.ParseString(webhook.Url); // parse for template scoped parameters
                        url = internalParser.ParseString(url);     // parse for webhook scoped parameters

                        switch (webhook.Method)
                        {
                        case ProvisioningTemplateWebhookMethod.GET:
                        {
                            url += $"&__webhookKind={kind.ToString()}";         // add the webhook kind to the REST request URL

                            foreach (var k in requestParameters.Keys)
                            {
                                url += $"&{HttpUtility.UrlEncode(k)}={HttpUtility.UrlEncode(requestParameters[k])}";
                            }

                            if (kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted ||
                                kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted ||
                                kind == ProvisioningTemplateWebhookKind.ExceptionOccurred)
                            {
                                url += $"&__handler={HttpUtility.UrlEncode(objectHandler)}";         // add the handler name to the REST request URL
                            }
                            try
                            {
                                if (webhook.Async)
                                {
                                    Task.Factory.StartNew(async() =>
                                        {
                                            await httpClient.GetAsync(url);
                                        });
                                }
                                else
                                {
                                    httpClient.GetAsync(url).GetAwaiter().GetResult();
                                }
                            }
                            catch (HttpRequestException ex)
                            {
                                scope.LogError(ex, "Error calling provisioning template webhook");
                            }
                            break;
                        }

                        case ProvisioningTemplateWebhookMethod.POST:
                        {
                            requestParameters.Add("__webhookKind", kind.ToString());         // add the webhook kind to the parameters of the request body

                            if (kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted ||
                                kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted ||
                                kind == ProvisioningTemplateWebhookKind.ExceptionOccurred)
                            {
                                requestParameters.Add("__handler", objectHandler);         // add the handler name to the parameters of the request body
                            }
                            try
                            {
                                if (webhook.Async)
                                {
                                    Task.Factory.StartNew(async() =>
                                        {
                                            switch (webhook.BodyFormat)
                                            {
                                            case ProvisioningTemplateWebhookBodyFormat.Json:
                                                await httpClient.PostAsJsonAsync(url, requestParameters);
                                                break;

                                            case ProvisioningTemplateWebhookBodyFormat.Xml:
                                                await httpClient.PostAsXmlAsync(url, requestParameters);
                                                break;

                                            case ProvisioningTemplateWebhookBodyFormat.FormUrlEncoded:
                                                var content = new FormUrlEncodedContent(requestParameters);
                                                await httpClient.PostAsync(url, content);
                                                break;
                                            }
                                        });
                                }
                                else
                                {
                                    switch (webhook.BodyFormat)
                                    {
                                    case ProvisioningTemplateWebhookBodyFormat.Json:
                                        httpClient.PostAsJsonAsync(url, requestParameters).GetAwaiter().GetResult();
                                        break;

                                    case ProvisioningTemplateWebhookBodyFormat.Xml:
                                        httpClient.PostAsXmlAsync(url, requestParameters).GetAwaiter().GetResult();
                                        break;

                                    case ProvisioningTemplateWebhookBodyFormat.FormUrlEncoded:
                                        var content = new FormUrlEncodedContent(requestParameters);
                                        httpClient.PostAsync(url, content).GetAwaiter().GetResult();
                                        break;
                                    }
                                }
                            }
                            catch (HttpRequestException ex)
                            {
                                scope.LogError(ex, "Error calling provisioning template webhook");
                            }
                            break;
                        }
                        }
                    }
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Public method to send a Webhook notification
        /// </summary>
        /// <param name="webhook">The reference webhook to notify</param>
        /// <param name="httpClient">The HttpClient instance to use to send the notification</param>
        /// <param name="kind">The Kind of webhook</param>
        /// <param name="parser">The parser to use for parsing parameters, optional</param>
        /// <param name="objectHandler">The objectHandler name, optional</param>
        /// <param name="exception">The exception, optional</param>
        /// <param name="scope">The PnP Provisioning Scope, if any, optional</param>
        public static void InvokeWebhook(ProvisioningWebhookBase webhook,
                                         HttpClient httpClient,
                                         ProvisioningTemplateWebhookKind kind, TokenParser parser = null,
                                         string objectHandler    = null, Exception exception = null,
                                         PnPMonitoredScope scope = null)
        {
            var requestParameters = new Dictionary <String, String>();

            if (exception != null)
            {
                // For GET requests we limit the size of the exception to avoid issues
                requestParameters["__exception"] =
                    webhook.Method == ProvisioningTemplateWebhookMethod.GET ?
                    exception.Message : exception.ToString();
            }

            SimpleTokenParser internalParser = new SimpleTokenParser();

            foreach (var webhookparam in webhook.Parameters)
            {
                requestParameters.Add(webhookparam.Key, parser != null ? parser.ParseString(webhookparam.Value) : webhookparam.Value);
                internalParser.AddToken(new WebhookParameter(webhookparam.Key, requestParameters[webhookparam.Key]));
            }
            var url = parser != null?parser.ParseString(webhook.Url) : webhook.Url; // parse for template scoped parameters

            url = internalParser.ParseString(url);                                  // parse for webhook scoped parameters

            switch (webhook.Method)
            {
            case ProvisioningTemplateWebhookMethod.GET:
            {
                url += $"&__webhookKind={kind.ToString()}";         // add the webhook kind to the REST request URL

                foreach (var k in requestParameters.Keys)
                {
                    url += $"&{HttpUtility.UrlEncode(k)}={HttpUtility.UrlEncode(requestParameters[k])}";
                }

                if ((kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted ||
                     kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted ||
                     kind == ProvisioningTemplateWebhookKind.ExceptionOccurred) && objectHandler != null)
                {
                    url += $"&__handler={HttpUtility.UrlEncode(objectHandler)}";         // add the handler name to the REST request URL
                }
                try
                {
                    if (webhook.Async)
                    {
                        Task.Factory.StartNew(async() =>
                            {
                                await httpClient.GetAsync(url);
                            });
                    }
                    else
                    {
                        httpClient.GetAsync(url).GetAwaiter().GetResult();
                    }
                }
                catch (HttpRequestException ex)
                {
                    scope?.LogError(ex, "Error calling provisioning template webhook");
                }
                break;
            }

            case ProvisioningTemplateWebhookMethod.POST:
            {
                requestParameters.Add("__webhookKind", kind.ToString());         // add the webhook kind to the parameters of the request body

                if ((kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted ||
                     kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted ||
                     kind == ProvisioningTemplateWebhookKind.ExceptionOccurred) && objectHandler != null)
                {
                    requestParameters.Add("__handler", objectHandler);         // add the handler name to the parameters of the request body
                }
                try
                {
                    if (webhook.Async)
                    {
                        Task.Factory.StartNew(async() =>
                            {
                                switch (webhook.BodyFormat)
                                {
                                case ProvisioningTemplateWebhookBodyFormat.Json:
#if !NETSTANDARD2_0
                                    await httpClient.PostAsJsonAsync(url, requestParameters);
#else
                                    await httpClient.PostAsync(url, new StringContent(JsonConvert.SerializeObject(requestParameters), Encoding.UTF8, "application/json"));
#endif
                                    break;

                                case ProvisioningTemplateWebhookBodyFormat.Xml:
#if !NETSTANDARD2_0
                                    await httpClient.PostAsXmlAsync(url, requestParameters);
#else
                                    await httpClient.PostAsync(url, new StringContent(SerializeXml(requestParameters), Encoding.UTF8, "application/xml"));
#endif
                                    break;

                                case ProvisioningTemplateWebhookBodyFormat.FormUrlEncoded:
                                    var content = new FormUrlEncodedContent(requestParameters);
                                    await httpClient.PostAsync(url, content);
                                    break;
                                }
                            });
                    }
                    else
                    {
                        switch (webhook.BodyFormat)
                        {
                        case ProvisioningTemplateWebhookBodyFormat.Json:
#if !NETSTANDARD2_0
                            httpClient.PostAsJsonAsync(url, requestParameters).GetAwaiter().GetResult();
#else
                            httpClient.PostAsync(url, new StringContent(JsonConvert.SerializeObject(requestParameters), Encoding.UTF8, "application/json")).GetAwaiter().GetResult();
#endif
                            break;

                        case ProvisioningTemplateWebhookBodyFormat.Xml:
#if !NETSTANDARD2_0
                            httpClient.PostAsXmlAsync(url, requestParameters).GetAwaiter().GetResult();
#else
                            httpClient.PostAsync(url, new StringContent(SerializeXml(requestParameters), Encoding.UTF8, "application/xml"));
#endif
                            break;

                        case ProvisioningTemplateWebhookBodyFormat.FormUrlEncoded:
                            var content = new FormUrlEncodedContent(requestParameters);
                            httpClient.PostAsync(url, content).GetAwaiter().GetResult();
                            break;
                        }
                    }
                }
                catch (HttpRequestException ex)
                {
                    scope?.LogError(ex, "Error calling provisioning template webhook");
                }
                break;
            }
            }
        }