{
    "version": "https:\/\/jsonfeed.org\/version\/1.1",
    "title": "Блоги: заметки с тегом dotnet",
    "_rss_description": "Автоматически собираемая лента заметок, написанных в блогах на Эгее",
    "_rss_language": "ru",
    "_itunes_email": "",
    "_itunes_categories_xml": "",
    "_itunes_image": false,
    "_itunes_explicit": "no",
    "home_page_url": "https:\/\/blogengine.ru\/blogs\/tags\/dotnet\/",
    "feed_url": "https:\/\/blogengine.ru\/blogs\/tags\/dotnet\/json\/",
    "icon": false,
    "authors": [
        {
            "name": "Илья Бирман",
            "url": "https:\/\/blogengine.ru\/blogs\/",
            "avatar": false
        }
    ],
    "items": [
        {
            "id": "119851",
            "url": "https:\/\/stefaniuk.website\/all\/create-workplace-messenger-bot\/",
            "title": "Как я делал бота для Facebook workplace",
            "content_html": "<p>Дали мне задачу: написать бота для мессенджера workplace, с помощью которого можно получать уведомления из нашей CRM и управлять разными вещами. Расскажу о разных интересных вещах с которыми я столкнулся. Бота писал с помощью ASP.NET Core Web API.<\/p>\n<h2>Вебхуки<\/h2>\n<p>Для того чтобы бот мог обрабатывать запросы и сообщения от Facebook нам надо настроить вебхуки. Webhook — механизм оповещения системы о событиях. Для того чтобы Facebook принял наш хук, он должен обрабатывать как GET так и POST запросы.<\/p>\n<p class=\"note\"><a href=\"https:\/\/developers.facebook.com\/docs\/messenger-platform\/getting-started\/webhook-setup\">Подробнее о Webhook в официальной документации<\/a><\/p>\n<p>GET запрос служит для валидации работы нашего эндпоинта. POST принимает данные связанные с активностью пользователя, будь то нажатие на кнопки или другая активность.<\/p>\n<p class=\"cut-button\">Показать код метода-обработчика GET запроса<\/p>\n<div class=\"cut-content\"><pre class=\"e2-text-code\"><code class=\"\">public IActionResult Receive(\u2028[FromQuery(Name = &quot;hub.mode&quot;)] string mode,\u2028\r\n    [FromQuery(Name = &quot;hub.challenge&quot;)] string challenge,\u2028\r\n    [FromQuery(Name = &quot;hub.verify_token&quot;)] string verifyToken)\r\n{\u2028\r\n   if (string.IsNullOrEmpty(verifyToken)) {\u2028\r\n       return Unauthorized();\u2028\r\n    }\u2028\u2028\r\n    if (verifyToken.Equals(FacebookEnvironment.FacebookVToken)) {\u2028\r\n        return Ok(challenge);\u2028\r\n    }\u2028\r\n    return Unauthorized();\u2028\r\n}<\/code><\/pre><p>В качестве verify_token используется токен, который мы указали при регистрации нашего хука.<\/p>\n<\/div><p class=\"cut-button\">Показать код метода-обработчика POST запроса<\/p>\n<div class=\"cut-content\"><pre class=\"e2-text-code\"><code class=\"\">public async Task&lt;IActionResult&gt; Receive([FromBody]FbResponse response = null)\r\n{\r\n    if (response is null) {\r\n        return BadRequest();\r\n    }\r\n\r\n    if (response.Object != &quot;page&quot;) {\r\n        return Ok();\r\n    }\r\n\r\n    foreach (var entry in response.Entries) {\r\n        foreach (var message in entry.Messaging) {\r\n            await PrepareMessageAsync(message);\r\n        }\r\n    }\r\n    return Ok(&quot;EVENT_RECEIVED&quot;);\r\n}<\/code><\/pre><\/div><h2>Авторизация запросов Facebook<\/h2>\n<p>Для авторизации Facebook использует специальный http заголовок (X-Hub-Signature), в нем он передает некую сигнатуру с помощью которой мы можем авторизовать запрос. Для того чтобы добавить такую функциональность в наш контроллер, добавим фильтр.<\/p>\n<p class=\"cut-button\">Пример кода, для проверки подписи<\/p>\n<div class=\"cut-content\"><pre class=\"e2-text-code\"><code class=\"\">private const string Sha1Prefix = &quot;sha1=&quot;;\r\n\r\npublic static bool Validate(string signature, string contentString) {\r\n    if (!signature.StartsWith(Sha1Prefix, StringComparison.OrdinalIgnoreCase)) {\r\n        return false;\r\n    }\r\n    var secret = Encoding.ASCII.GetBytes(FacebookEnvironment.AppSecret);\r\n    var signatureWithoutPrefix = signature.Substring(Sha1Prefix.Length);\r\n    var content = Encoding.ASCII.GetBytes(contentString);\r\n    return GetIsHashValid(secret, signatureWithoutPrefix, content);\r\n}\r\n\r\nprivate static bool GetIsHashValid(byte[] secret, string signature, byte[] content) {\r\n    using var hmac = new HMACSHA1(secret);\r\n    var hash = hmac.ComputeHash(content);\r\n    var hashString = ToHexString(hash);\r\n    return hashString.Equals(signature);\r\n}\r\n\r\nprivate static string ToHexString(IReadOnlyCollection&lt;byte&gt; bytes)\r\n{\r\n    var builder = new StringBuilder(bytes.Count * 2);\r\n    foreach (var b in bytes)\r\n    {\r\n        builder.AppendFormat(&quot;{0:x2}&quot;, b);\r\n    }\r\n\r\n    return builder.ToString();\r\n}<\/code><\/pre><\/div><h2>Тестирование бота<\/h2>\n<p class=\"note-md\"><a href=\"http:\/\/winitpro.ru\/index.php\/2017\/11\/03\/ustanovka-besplatnogo-ssl-sertifikata-lets-encrypt-na-iis-v-windows-server-2012-r2\/\">Как установить letsencrypt сертификат для IIS<\/a>. Если же вы используете связку в виде ubuntu и nginx вам подойдет <a href=\"https:\/\/www.digitalocean.com\/community\/tutorials\/nginx-let-s-encrypt-ubuntu-18-04-ru\">эта инструкция<\/a>.<\/p>\n<p>Для тестирования нужно развернуть бот на сервере, который смотрит в мир. Также необходимо чтобы у сервера было доменное имя и валидный SSL сертификат. В моем случае, в качестве сервера выступала машина на винде, так как другой внутри нашей сети не было. Как мне показалось захостить приложение написанное на .NET Core намного проще под Ubuntu + nginx нежели под Windows + IIS. В качестве поставщика сертификатов выбрал letsencrypt, так как они предоставляют бесплатный сертификат на 3 месяца, с возможностью дальнейшего обновления.<\/p>\n",
            "date_published": "2019-11-26T19:22:26+05:00",
            "date_modified": "2023-06-03T05:26:31+05:00",
            "tags": [
                "asp.net core",
                "dotnet",
                "програмування",
                "проекти",
                "робота"
            ],
            "author": {
                "name": "Bohdan Stefaniuk",
                "url": "https:\/\/stefaniuk.website\/",
                "avatar": "https:\/\/stefaniuk.website\/pictures\/userpic\/userpic@2x.jpg?1565716580"
            },
            "_date_published_rfc2822": "Tue, 26 Nov 2019 19:22:26 +0500",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "119851",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": null,
                "og_images": []
            }
        },
        {
            "id": "119848",
            "url": "https:\/\/stefaniuk.website\/all\/tools-for-analyze-application-dump\/",
            "title": "Инструменты для анализа дампа приложения",
            "content_html": "<p>Иногда наступает ситуация, когда нужно проанализировать дамп приложения. Но почти никто не знает что с ним в дальнейшем делать и какие есть инструменты для работы с ним. В данной заметке я хочу поделится своим набором инструментов.<\/p>\n<h2>Инструменты<\/h2>\n<ol start=\"1\">\n<li><a href=\"https:\/\/github.com\/Microsoft\/perfview\">PerfView<\/a> — открытое решение от компании Microsoft для анализа производительности.<\/li>\n<li><a href=\"https:\/\/www.jetbrains.com\/dotmemory\/\">dotMemory<\/a> — платное решение от компании JetBrains. Привлекает тем что не только умеет анализировать дампы, но и многое другое. Также имеет красивый и удобный GUI<\/li>\n<li><a href=\"https:\/\/github.com\/fremag\/MemoScope.Net\">MemoScope<\/a> — открытое решение от независимого разработчика.<\/li>\n<li>Visual Studio —  имеет встроенный функционал по анализу дампов приложения.<\/li>\n<\/ol>\n<h2>Ссылки<\/h2>\n<p><b>PerfView<\/b><\/p>\n<ol start=\"1\">\n<li><a href=\"https:\/\/blogs.msdn.microsoft.com\/vancem\/tag\/perfview\/\">Блог MSDN по тегу PerfView<\/a><\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=eX644hod65s\"> Video: PerfView: Measure and Improve Your App’s Performance For Free<\/a><\/li>\n<li><a href=\"https:\/\/channel9.msdn.com\/Series\/PerfView-Tutorial\">Video: Video tutorial by Chanel 9<\/a><\/li>\n<li><a href=\"https:\/\/blogs.msdn.microsoft.com\/dotnet\/2012\/10\/09\/improving-your-apps-performance-with-perfview\/\">Improving Your App’s Performance with PerfView<\/a><\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=qGEeZZBwVp4\">Video: PerfView: The Ultimate .NET Performance Tool<\/a><\/li>\n<\/ol>\n<p><b>MemoScope<\/b><\/p>\n<ol start=\"1\">\n<li><a href=\"https:\/\/github.com\/fremag\/MemoScope.Net\/wiki\">Официальная Wiki<\/a><\/li>\n<\/ol>\n<p><b>Visual Studio<\/b><\/p>\n<ol start=\"1\">\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=lU_YZtvslnI\">Video: Debugging Memory Leaks Using New NET Memory Diagnostic Tools<\/a><\/li>\n<li><a href=\"https:\/\/docs.microsoft.com\/en-us\/visualstudio\/debugger\/using-dump-files?view=vs-2017\">Visual Studio Docs<\/a><\/li>\n<\/ol>\n<p><b>DotMemory<\/b><\/p>\n<ol start=\"1\">\n<li><a href=\"https:\/\/www.jetbrains.com\/help\/dotmemory\/Examples.html\">Official Page<\/a><\/li>\n<\/ol>\n",
            "date_published": "2018-12-13T21:27:23+05:00",
            "date_modified": "2023-06-03T05:23:05+05:00",
            "tags": [
                "dotnet",
                "інструменти"
            ],
            "author": {
                "name": "Bohdan Stefaniuk",
                "url": "https:\/\/stefaniuk.website\/",
                "avatar": "https:\/\/stefaniuk.website\/pictures\/userpic\/userpic@2x.jpg?1565716580"
            },
            "_date_published_rfc2822": "Thu, 13 Dec 2018 21:27:23 +0500",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "119848",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": null,
                "og_images": []
            }
        }
    ],
    "_e2_version": 4079,
    "_e2_ua_string": "Aegea 11.0 (v4079e)"
}