{"action":"created","comment":{"url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/pulls/comments/180587618","pull_request_review_id":111027265,"id":180587618,"diff_hunk":"@@ -0,0 +1,154 @@\n+﻿// Copyright (c) Microsoft Corporation. All rights reserved.\r\n+// Licensed under the MIT License.\r\n+\r\n+using System;\r\n+using System.IO;\r\n+using System.Linq;\r\n+using System.Text;\r\n+using System.Threading.Tasks;\r\n+using System.Web;\r\n+using Microsoft.Bot.Builder.Core.Extensions;\r\n+using Microsoft.WindowsAzure.Storage;\r\n+using Microsoft.WindowsAzure.Storage.Blob;\r\n+using Newtonsoft.Json;\r\n+\r\n+namespace Microsoft.Bot.Builder.Azure\r\n+{\r\n+    /// <summary>\r\n+    /// Models IStorage using Azure Storge Blobs\r\n+    /// </summary>\r\n+    /// <remarks>\r\n+    /// The AzureBlobStorage implements State's IStorage using a single Azure Storage Blob Container.\r\n+    /// Each entity or StoreItem is serialized into a JSON string and stored in an individual text blob.\r\n+    /// Each blob is named after the StoreItem key which is encoded and ensure it conforms a valid blob name.\r\n+    /// </remarks>\r\n+    public class AzureBlobStorage : IStorage\r\n+    {\r\n+        private readonly static JsonSerializerSettings serializationSettings = new JsonSerializerSettings()\r\n+        {\r\n+            // we use all so that we get typed roundtrip out of storage, but we don't use validation because we don't know what types are valid\r\n+            TypeNameHandling = TypeNameHandling.All\r\n+        };\r\n+\r\n+        /// <summary>\r\n+        /// The Azure Storage Blob Container where entities will be stored\r\n+        /// </summary>\r\n+        public Lazy<CloudBlobContainer> Container { get; private set; }\r\n+\r\n+        /// <summary>\r\n+        /// Creates the AzureBlobStorage instance\r\n+        /// </summary>\r\n+        /// <param name=\"dataConnectionString\">Azure Storage connection string</param>\r\n+        /// <param name=\"containerName\">Name of the Blob container where entities will be stored</param>\r\n+        public AzureBlobStorage(string dataConnectionString, string containerName)\r\n+            : this(CloudStorageAccount.Parse(dataConnectionString), containerName)\r\n+        {\r\n+        }\r\n+\r\n+        /// <summary>\r\n+        /// Creates the AzureBlobStorage instance\r\n+        /// </summary>\r\n+        /// <param name=\"storageAccount\">Azure CloudStorageAccount instance</param>\r\n+        /// <param name=\"containerName\">Name of the Blob container where entities will be stored</param>\r\n+        public AzureBlobStorage(CloudStorageAccount storageAccount, string containerName)\r\n+        {\r\n+            if (storageAccount == null) throw new ArgumentNullException(nameof(storageAccount));\r\n+\r\n+            // Checks if a container name is valid\r\n+            NameValidator.ValidateContainerName(containerName);\r\n+\r\n+            this.Container = new Lazy<CloudBlobContainer>(() =>\r\n+              {\r\n+                  var blobClient = storageAccount.CreateCloudBlobClient();\r\n+                  var container = blobClient.GetContainerReference(containerName);\r\n+                  container.CreateIfNotExistsAsync().Wait();\r\n+                  return container;\r\n+              });\r\n+        }\r\n+\r\n+        /// <summary>\r\n+        /// Get a blob name validated representation of an entity\r\n+        /// </summary>\r\n+        /// <param name=\"key\">The key used to identify the entity</param>\r\n+        /// <returns></returns>\r\n+        private static string GetBlobName(string key)\r\n+        {\r\n+            if (string.IsNullOrEmpty(key)) throw new ArgumentNullException(nameof(key));\r\n+\r\n+            var blobName = HttpUtility.UrlEncode(key);\r\n+            NameValidator.ValidateBlobName(blobName);\r\n+            return blobName;\r\n+        }\r\n+\r\n+        /// <summary>\r\n+        /// Deletes entity blobs from the configured container\r\n+        /// </summary>\r\n+        /// <param name=\"keys\">An array of entitiy keys</param>\r\n+        /// <returns></returns>\r\n+        public async Task Delete(string[] keys)\r\n+        {\r\n+            if (keys == null) throw new ArgumentNullException(nameof(keys));\r\n+\r\n+            foreach (var blobName in keys.Select(GetBlobName))\r\n+            {\r\n+                var blobReference = this.Container.Value.GetBlobReference(blobName);\r\n+                await blobReference.DeleteAsync(\r\n+                    DeleteSnapshotsOption.None, new AccessCondition { IfMatchETag = \"*\" }, new BlobRequestOptions(), new OperationContext()).ConfigureAwait(false);\r\n+            }\r\n+        }\r\n+\r\n+        /// <summary>\r\n+        /// Retrieve entities from the configured blob container\r\n+        /// </summary>\r\n+        /// <param name=\"keys\">An array of entitiy keys</param>\r\n+        /// <returns></returns>\r\n+        public async Task<StoreItems> Read(string[] keys)\r\n+        {\r\n+            if (keys == null) throw new ArgumentNullException(nameof(keys));\r\n+\r\n+            var storeItems = new StoreItems();\r\n+            foreach (string blobName in keys.Select(GetBlobName))\r\n+            {\r\n+                using (var memoryStream = new MemoryStream())\r\n+                {\r\n+                    var blobReference = this.Container.Value.GetBlobReference(blobName);\r\n+                    await blobReference.DownloadToStreamAsync(memoryStream).ConfigureAwait(false);\r\n+                    using (var streamReader = new StreamReader(memoryStream, Encoding.UTF8))\r\n+                    {\r\n+                        var json = streamReader.ReadToEnd();\r\n+                        var obj = JsonConvert.DeserializeObject(json, serializationSettings);\r\n+                        IStoreItem storeItem = obj as IStoreItem;\r\n+                        if (storeItem != null)\r\n+                        {\r\n+                            storeItem.eTag = blobReference.Properties.ETag;\r\n+                        }\r\n+\r\n+                        storeItems[blobName] = storeItem;\r\n+                    }\r\n+                }\r\n+            }\r\n+\r\n+            return storeItems;\r\n+        }\r\n+\r\n+        /// <summary>\r\n+        /// Stores a new entity in the configured blob container\r\n+        /// </summary>\r\n+        /// <param name=\"changes\"></param>\r\n+        /// <returns></returns>\r\n+        public async Task Write(StoreItems changes)\r\n+        {\r\n+            if (changes == null) throw new ArgumentNullException(nameof(changes));\r\n+\r\n+            foreach (var change in changes)\r\n+            {\r\n+                var blobName = GetBlobName(change.Key);\r\n+                var newValue = change.Value as IStoreItem;\r\n+                var json = JsonConvert.SerializeObject(newValue, Formatting.None, serializationSettings);\r\n+                var blobReference = this.Container.Value.GetBlockBlobReference(blobName);\r\n+\r\n+                await blobReference.UploadTextAsync(json, new AccessCondition { IfMatchETag = newValue.eTag ?? \"*\" }, new BlobRequestOptions(), new OperationContext()).ConfigureAwait(false);\r","path":"libraries/Microsoft.Bot.Builder.Azure/AzureBlobStorage.cs","position":150,"original_position":150,"commit_id":"a9cf55e5bac46f6e557cf89a9aea6c1230f13325","original_commit_id":"a9cf55e5bac46f6e557cf89a9aea6c1230f13325","user":{"login":"drub0y","id":284152,"avatar_url":"https://avatars3.githubusercontent.com/u/284152?v=4","gravatar_id":"","url":"https://api.github.com/users/drub0y","html_url":"https://github.com/drub0y","followers_url":"https://api.github.com/users/drub0y/followers","following_url":"https://api.github.com/users/drub0y/following{/other_user}","gists_url":"https://api.github.com/users/drub0y/gists{/gist_id}","starred_url":"https://api.github.com/users/drub0y/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/drub0y/subscriptions","organizations_url":"https://api.github.com/users/drub0y/orgs","repos_url":"https://api.github.com/users/drub0y/repos","events_url":"https://api.github.com/users/drub0y/events{/privacy}","received_events_url":"https://api.github.com/users/drub0y/received_events","type":"User","site_admin":false},"body":"Rather than serializing in memory and then uploading the string, you could technically serialize to a `JsonWriter` layered over a `StreamWriter` layered over the raw stream from the blob that you get from `CloudBlockBlob::OpenWriteAsync`. The gain here is, once again, less garbage being created, thus lowering GC overhead.","created_at":"2018-04-10T22:35:45Z","updated_at":"2018-04-10T22:38:04Z","html_url":"https://github.com/Microsoft/botbuilder-dotnet/pull/388#discussion_r180587618","pull_request_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/pulls/388","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/pulls/comments/180587618"},"html":{"href":"https://github.com/Microsoft/botbuilder-dotnet/pull/388#discussion_r180587618"},"pull_request":{"href":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/pulls/388"}}},"pull_request":{"url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/pulls/388","id":180074138,"html_url":"https://github.com/Microsoft/botbuilder-dotnet/pull/388","diff_url":"https://github.com/Microsoft/botbuilder-dotnet/pull/388.diff","patch_url":"https://github.com/Microsoft/botbuilder-dotnet/pull/388.patch","issue_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/issues/388","number":388,"state":"open","locked":false,"title":"Azure Blob Storage Provider","user":{"login":"JuanAr","id":805847,"avatar_url":"https://avatars2.githubusercontent.com/u/805847?v=4","gravatar_id":"","url":"https://api.github.com/users/JuanAr","html_url":"https://github.com/JuanAr","followers_url":"https://api.github.com/users/JuanAr/followers","following_url":"https://api.github.com/users/JuanAr/following{/other_user}","gists_url":"https://api.github.com/users/JuanAr/gists{/gist_id}","starred_url":"https://api.github.com/users/JuanAr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JuanAr/subscriptions","organizations_url":"https://api.github.com/users/JuanAr/orgs","repos_url":"https://api.github.com/users/JuanAr/repos","events_url":"https://api.github.com/users/JuanAr/events{/privacy}","received_events_url":"https://api.github.com/users/JuanAr/received_events","type":"User","site_admin":false},"body":"This PR includes the .NET version of the AzureBlobStorage provider.\r\nItems are stored as blobs within the configured Azure Storage account's Container. Container is checked on initialization and created if they do not exist.\r\nTests include a similar approach to the AzureTable tests and require the Storage Emulator to be installed (will be started) locally.","created_at":"2018-04-06T23:22:46Z","updated_at":"2018-04-10T22:38:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a0a2f53424948a17a6d24abf9bf58b4b86638fd1","assignee":null,"assignees":[],"requested_reviewers":[{"login":"tomlm","id":17789481,"avatar_url":"https://avatars0.githubusercontent.com/u/17789481?v=4","gravatar_id":"","url":"https://api.github.com/users/tomlm","html_url":"https://github.com/tomlm","followers_url":"https://api.github.com/users/tomlm/followers","following_url":"https://api.github.com/users/tomlm/following{/other_user}","gists_url":"https://api.github.com/users/tomlm/gists{/gist_id}","starred_url":"https://api.github.com/users/tomlm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tomlm/subscriptions","organizations_url":"https://api.github.com/users/tomlm/orgs","repos_url":"https://api.github.com/users/tomlm/repos","events_url":"https://api.github.com/users/tomlm/events{/privacy}","received_events_url":"https://api.github.com/users/tomlm/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[{"id":893296494,"url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/labels/state-management","name":"state-management","color":"fef2c0","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/pulls/388/commits","review_comments_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/pulls/388/comments","review_comment_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/issues/388/comments","statuses_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/statuses/a9cf55e5bac46f6e557cf89a9aea6c1230f13325","head":{"label":"Microsoft:southworks/azureblobstorage-provider","ref":"southworks/azureblobstorage-provider","sha":"a9cf55e5bac46f6e557cf89a9aea6c1230f13325","user":{"login":"Microsoft","id":6154722,"avatar_url":"https://avatars2.githubusercontent.com/u/6154722?v=4","gravatar_id":"","url":"https://api.github.com/users/Microsoft","html_url":"https://github.com/Microsoft","followers_url":"https://api.github.com/users/Microsoft/followers","following_url":"https://api.github.com/users/Microsoft/following{/other_user}","gists_url":"https://api.github.com/users/Microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/Microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Microsoft/subscriptions","organizations_url":"https://api.github.com/users/Microsoft/orgs","repos_url":"https://api.github.com/users/Microsoft/repos","events_url":"https://api.github.com/users/Microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/Microsoft/received_events","type":"Organization","site_admin":false},"repo":{"id":117021670,"name":"botbuilder-dotnet","full_name":"Microsoft/botbuilder-dotnet","owner":{"login":"Microsoft","id":6154722,"avatar_url":"https://avatars2.githubusercontent.com/u/6154722?v=4","gravatar_id":"","url":"https://api.github.com/users/Microsoft","html_url":"https://github.com/Microsoft","followers_url":"https://api.github.com/users/Microsoft/followers","following_url":"https://api.github.com/users/Microsoft/following{/other_user}","gists_url":"https://api.github.com/users/Microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/Microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Microsoft/subscriptions","organizations_url":"https://api.github.com/users/Microsoft/orgs","repos_url":"https://api.github.com/users/Microsoft/repos","events_url":"https://api.github.com/users/Microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/Microsoft/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Microsoft/botbuilder-dotnet","description":".NET SDK used to build chat bots for the Microsoft Bot Framework.","fork":false,"url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet","forks_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/forks","keys_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/teams","hooks_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/hooks","issue_events_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/issues/events{/number}","events_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/events","assignees_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/assignees{/user}","branches_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/branches{/branch}","tags_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/tags","blobs_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/git/refs{/sha}","trees_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/statuses/{sha}","languages_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/languages","stargazers_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/stargazers","contributors_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/contributors","subscribers_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/subscribers","subscription_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/subscription","commits_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/commits{/sha}","git_commits_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/git/commits{/sha}","comments_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/comments{/number}","issue_comment_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/issues/comments{/number}","contents_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/contents/{+path}","compare_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/merges","archive_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/downloads","issues_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/issues{/number}","pulls_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/pulls{/number}","milestones_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/milestones{/number}","notifications_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/labels{/name}","releases_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/releases{/id}","deployments_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/deployments","created_at":"2018-01-10T23:03:16Z","updated_at":"2018-04-10T22:33:45Z","pushed_at":"2018-04-10T22:33:43Z","git_url":"git://github.com/Microsoft/botbuilder-dotnet.git","ssh_url":"git@github.com:Microsoft/botbuilder-dotnet.git","clone_url":"https://github.com/Microsoft/botbuilder-dotnet.git","svn_url":"https://github.com/Microsoft/botbuilder-dotnet","homepage":null,"size":2672,"stargazers_count":79,"watchers_count":79,"language":"C#","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":34,"mirror_url":null,"archived":false,"open_issues_count":57,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":34,"open_issues":57,"watchers":79,"default_branch":"master"}},"base":{"label":"Microsoft:master","ref":"master","sha":"b32d291b7431bd936b04d284a648b222e8e6c0cf","user":{"login":"Microsoft","id":6154722,"avatar_url":"https://avatars2.githubusercontent.com/u/6154722?v=4","gravatar_id":"","url":"https://api.github.com/users/Microsoft","html_url":"https://github.com/Microsoft","followers_url":"https://api.github.com/users/Microsoft/followers","following_url":"https://api.github.com/users/Microsoft/following{/other_user}","gists_url":"https://api.github.com/users/Microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/Microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Microsoft/subscriptions","organizations_url":"https://api.github.com/users/Microsoft/orgs","repos_url":"https://api.github.com/users/Microsoft/repos","events_url":"https://api.github.com/users/Microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/Microsoft/received_events","type":"Organization","site_admin":false},"repo":{"id":117021670,"name":"botbuilder-dotnet","full_name":"Microsoft/botbuilder-dotnet","owner":{"login":"Microsoft","id":6154722,"avatar_url":"https://avatars2.githubusercontent.com/u/6154722?v=4","gravatar_id":"","url":"https://api.github.com/users/Microsoft","html_url":"https://github.com/Microsoft","followers_url":"https://api.github.com/users/Microsoft/followers","following_url":"https://api.github.com/users/Microsoft/following{/other_user}","gists_url":"https://api.github.com/users/Microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/Microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Microsoft/subscriptions","organizations_url":"https://api.github.com/users/Microsoft/orgs","repos_url":"https://api.github.com/users/Microsoft/repos","events_url":"https://api.github.com/users/Microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/Microsoft/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Microsoft/botbuilder-dotnet","description":".NET SDK used to build chat bots for the Microsoft Bot Framework.","fork":false,"url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet","forks_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/forks","keys_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/teams","hooks_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/hooks","issue_events_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/issues/events{/number}","events_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/events","assignees_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/assignees{/user}","branches_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/branches{/branch}","tags_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/tags","blobs_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/git/refs{/sha}","trees_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/statuses/{sha}","languages_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/languages","stargazers_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/stargazers","contributors_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/contributors","subscribers_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/subscribers","subscription_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/subscription","commits_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/commits{/sha}","git_commits_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/git/commits{/sha}","comments_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/comments{/number}","issue_comment_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/issues/comments{/number}","contents_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/contents/{+path}","compare_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/merges","archive_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/downloads","issues_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/issues{/number}","pulls_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/pulls{/number}","milestones_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/milestones{/number}","notifications_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/labels{/name}","releases_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/releases{/id}","deployments_url":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/deployments","created_at":"2018-01-10T23:03:16Z","updated_at":"2018-04-10T22:33:45Z","pushed_at":"2018-04-10T22:33:43Z","git_url":"git://github.com/Microsoft/botbuilder-dotnet.git","ssh_url":"git@github.com:Microsoft/botbuilder-dotnet.git","clone_url":"https://github.com/Microsoft/botbuilder-dotnet.git","svn_url":"https://github.com/Microsoft/botbuilder-dotnet","homepage":null,"size":2672,"stargazers_count":79,"watchers_count":79,"language":"C#","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":34,"mirror_url":null,"archived":false,"open_issues_count":57,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":34,"open_issues":57,"watchers":79,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/pulls/388"},"html":{"href":"https://github.com/Microsoft/botbuilder-dotnet/pull/388"},"issue":{"href":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/issues/388"},"comments":{"href":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/issues/388/comments"},"review_comments":{"href":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/pulls/388/comments"},"review_comment":{"href":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/pulls/388/commits"},"statuses":{"href":"https://api.github.com/repos/Microsoft/botbuilder-dotnet/statuses/a9cf55e5bac46f6e557cf89a9aea6c1230f13325"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"drub0y"}}