public void Send(Notification notification)
        {
            WebHookNotification webhookNotification = notification as WebHookNotification;
            if (webhookNotification == null)
            {
                throw new ArgumentException("Invalid type passed to web hook notification handler. Expected an instance of WebHookNotification.");
            }                        
            
            // Create Web Hook
            WebHook webhook = new WebHook();
            webhook.Description = webhookNotification.CallbackResponse;
            webhook.WebHookUri = webhookNotification.CallbackUrl;
            webhook.Id = "2";

            // Create Notification List (multiple notifications can be sent to the single web hook)
            List<NotificationDictionary> notificationList = new List<NotificationDictionary>();
            Dictionary<string, object> data = new Dictionary<string, object>
            {
                { "ID", webhookNotification.CreatedBy.ToString() },
                { "Created Date", webhookNotification.CreatedDate.ToString() },
            };
            notificationList.Add(new NotificationDictionary("customEvent", data));
            
            // Create a Work Item for processing the Web Hook
            WebHookWorkItem workItem = new WebHookWorkItem(webhook, notificationList);

            WebHookHandler webhookHandler = new WebHookHandler();
            webhookHandler.SendWebHook(workItem);
        }
        private HttpRequestMessage createWebHookRequest(WebHookWorkItem workItem)
        {
            if (workItem == null)
            {
                throw new ArgumentNullException("workItem");
            }

            WebHook hook = workItem.WebHook;

            // Create WebHook request
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, hook.WebHookUri);

            // Fill in request body based on WebHook and work item data
            JObject body = createWebHookRequestBody(workItem);
            if (workItem.WebHook.Secret != null)
            {
                signWebHookRequest(workItem, request, body);
            }
            else
            {
                string serializedBody = body.ToString();
                request.Content = new StringContent(serializedBody, Encoding.UTF8, "application/json");

            }


            // Add extra request or entity headers
            foreach (var kvp in hook.Headers)
            {
                if (!request.Headers.TryAddWithoutValidation(kvp.Key, kvp.Value))
                {
                    if (!request.Content.Headers.TryAddWithoutValidation(kvp.Key, kvp.Value))
                    {
                        string msg;// = string.Format(CultureInfo.CurrentCulture, CustomResources.Manager_InvalidHeader, kvp.Key, hook.Id);
                        //_logger.Error(msg);
                    }
                }
            }

            return request;
        }
        public async Task SendWebHook(WebHookWorkItem workItem)
        {
            try
            {
                // Setting up and send WebHook request 
                HttpRequestMessage request = createWebHookRequest(workItem);
                HttpClient _httpClient = new HttpClient();
                HttpResponseMessage response = await _httpClient.SendAsync(request);

                if (response.IsSuccessStatusCode)
                {
                    return;
                }
                else if (response.StatusCode == HttpStatusCode.Gone)
                {
                    return;
                }
            }
            catch (Exception ex)
            {

            }
        }
        /// <summary>
        /// Creates a <see cref="JObject"/> used as the <see cref="HttpRequestMessage"/> entity body for a <see cref="WebHook"/>.
        /// </summary>
        /// <param name="workItem">The <see cref="WebHookWorkItem"/> representing the data to be sent.</param>
        /// <returns>An initialized <see cref="JObject"/>.</returns>
        private JObject createWebHookRequestBody(WebHookWorkItem workItem)
        {
            if (workItem == null)
            {
                throw new ArgumentNullException("workItem");
            }

            Dictionary<string, object> body = new Dictionary<string, object>();

            // Set properties from work item
            body[BodyIdKey] = workItem.Id;
            body[BodyAttemptKey] = workItem.Offset + 1;

            // Set properties from WebHook
            IDictionary<string, object> properties = workItem.WebHook.Properties;
            if (properties != null)
            {
                body[BodyPropertiesKey] = new Dictionary<string, object>(properties);
            }

            // Set notifications
            body[BodyNotificationsKey] = workItem.Notifications;

            return JObject.FromObject(body);
        }
        private void signWebHookRequest(WebHookWorkItem workItem, HttpRequestMessage request, JObject body)
        {
            if (workItem == null)
            {
                throw new ArgumentNullException("workItem");
            }
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }
            if (body == null)
            {
                throw new ArgumentNullException("body");
            }

            byte[] secret = Encoding.UTF8.GetBytes(workItem.WebHook.Secret);
            using (var hasher = new HMACSHA256(secret))
            {
                string serializedBody = body.ToString();
                request.Content = new StringContent(serializedBody, Encoding.UTF8, "application/json");

                byte[] data = Encoding.UTF8.GetBytes(serializedBody);
                byte[] sha256 = hasher.ComputeHash(data);
                string headerValue = string.Format(CultureInfo.InvariantCulture, SignatureHeaderValueTemplate, EncodingUtilities.ToHex(sha256));
                request.Headers.Add(SignatureHeaderName, headerValue);
            }
        }