Configure Slack in .NET Core



1. Create new App in Slack. https://api.slack.com/apps
2. Configure incoming webhook for the channel where we want to receive the messages
3. Copy url from WebHook and create a new section in our appsettings.json file. i.e.  

 "SlackSettings": {
    "NotifyChannelUrl": "https://hooks.slack.com/services/..."
  },

4. Create a new filter to catch exceptions:

    public class SlackExceptionFilterAttribute : ExceptionFilterAttribute
    {
        private readonly SlackNotificationService _slackNotificationService;
        private readonly IHostingEnvironment _hostingEnvironment;

        public SlackExceptionFilterAttribute(SlackNotificationService slackNotificationService, IHostingEnvironment hostingEnvironment)
        {
            _slackNotificationService = slackNotificationService;
            _hostingEnvironment = hostingEnvironment;
        }

        public async override Task OnExceptionAsync(ExceptionContext context)
        {
            try
            {
                if (context.Exception is Shared.Exceptions.INotFoundException)
                {
                    context.Result = new NotFoundResult();
                    return;
                }
                string url = GetAbsoluteUri(context.HttpContext);
                if (_hostingEnvironment.IsProduction())
                    await _slackNotificationService.NotifyException(url, context.Exception.GetType().Name, context.Exception.Message);
            }
            catch (Exception)
            {
            }
        }

        private string GetAbsoluteUri(HttpContext httpContext)
        {
            var request = httpContext.Request;
            UriBuilder uriBuilder = new UriBuilder();
            uriBuilder.Scheme = request.Scheme;
            uriBuilder.Host = request.Host.Host;
            uriBuilder.Path = request.Path.ToString();
            uriBuilder.Query = request.QueryString.ToString();
            return uriBuilder.Uri.ToString();
        }

    }


5. Add the filter in the startup file
            services.AddMvc(opt =>
                {
                    opt.Filters.Add<SlackExceptionFilterAttribute>();
                })

6. Create the notificacion service class:

    public class SlackNotificationService
    {
        private readonly SlackSettings _slackSettings;
        private readonly IHttpContextAccessor _httpContextAccessor;

        public SlackNotificationService(IHttpContextAccessor httpContextAccessor, IOptions<Secrets> option)
        {
            _slackSettings = option.Value.SlackSettings;
            _httpContextAccessor = httpContextAccessor;
        }

        public async Task NotifyException(string url, string errorType, string errorMessage)
        {
            string userAgent = _httpContextAccessor.HttpContext.Request.Headers["User-Agent"].ToString();
            var ip = _httpContextAccessor.HttpContext?.Connection?.RemoteIpAddress?.ToString() ?? string.Empty;
            var fields = new List<Field>()
                        {
                            new Field()
                            {
                                Short = true,
                                Title = "User Agent",
                                Value = userAgent
                            },
                            new Field()
                            {
                                Short = true,
                                Title = "User IP",
                                Value = ip
                            },
                            new Field()
                            {
                                Short = true,
                                Title = "Message",
                                Value = $"{errorType} - {errorMessage}"
                            },
                            new Field()
                            {
                                Short = true,
                                Title = "HTTP Method",
                                Value = _httpContextAccessor.HttpContext.Request.Method
                            }
                        };

            var slackMessage = new SlackMessage()
            {
                text = $"Exception in ...",
                attachments = new List<Attachment>()
                {
                    new Attachment()
                    {
                        color = "danger",
                        author_name = "Apply Website",
                        title = url,
                        title_link = url,
                        fields = fields
                    }
                }
            };

            if ((_slackSettings != null) && (!string.IsNullOrWhiteSpace(_slackSettings.NotifyChannelUrl)))
            {
                using (var client = new HttpClient())
                {
                    var content = JsonConvert.SerializeObject(slackMessage);
                    var response = await client.PostAsync(new Uri(_slackSettings.NotifyChannelUrl), new StringContent(content));
                }
            }
        }

    public class SlackMessage
    {
        public List<Attachment> attachments { get; set; }
        public string text { get; set; }
    }
    public class Field
    {
        [JsonProperty("short")]
        public bool Short { get; set; }
        [JsonProperty("title")]
        public string Title { get; set; }
        [JsonProperty("value")]
        public string Value { get; set; }
    }

    public class Attachment
    {
        public string author_name;
        public string title;
        public string title_link;

        public string color { get; set; }
        public List<Field> fields { get; set; }
    }

}

Comentarios