diff --git a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/ApplicationBuilderExtensions.cs b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/ApplicationBuilderExtensions.cs index 2886e9d9a..8f650e098 100644 --- a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/ApplicationBuilderExtensions.cs +++ b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/ApplicationBuilderExtensions.cs @@ -2,17 +2,31 @@ // Licensed under the MIT License. using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Http; using Microsoft.Bot.Builder.Adapters; +using Microsoft.Bot.Builder.Integration.AspNet.Core.Handlers; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using System; namespace Microsoft.Bot.Builder.Integration.AspNet.Core { public static class ApplicationBuilderExtensions { - public static IApplicationBuilder UseBotFramework(this IApplicationBuilder applicationBuilder) + public static IApplicationBuilder UseBotFramework(this IApplicationBuilder applicationBuilder) => + applicationBuilder.UseBotFramework(paths => {}); + + public static IApplicationBuilder UseBotFramework(this IApplicationBuilder applicationBuilder, Action configurePaths) { + if (applicationBuilder == null) + { + throw new ArgumentNullException(nameof(applicationBuilder)); + } + + if (configurePaths == null) + { + throw new ArgumentNullException(nameof(configurePaths)); + } + var options = applicationBuilder.ApplicationServices.GetRequiredService>().Value; var botFrameworkAdapter = new BotFrameworkAdapter(options.CredentialProvider); @@ -22,13 +36,20 @@ namespace Microsoft.Bot.Builder.Integration.AspNet.Core botFrameworkAdapter.Use(middleware); } - var botActivitiesPath = new PathString(options.RouteBaseUrl); + var paths = new BotFrameworkPaths(); - botActivitiesPath.Add("/messages"); + configurePaths(paths); + + if (options.EnableProactiveMessages) + { + applicationBuilder.Map( + paths.BasePath + paths.ProactiveMessagesPath, + botProactiveAppBuilder => botProactiveAppBuilder.Run(new BotProactiveMessageHandler(botFrameworkAdapter).HandleAsync)); + } applicationBuilder.Map( - botActivitiesPath, - botActivitiesAppBuilder => botActivitiesAppBuilder.Run(new BotActivitiesHandler(botFrameworkAdapter).HandleAsync)); + paths.BasePath + paths.MessagesPath, + botActivitiesAppBuilder => botActivitiesAppBuilder.Run(new BotMessageHandler(botFrameworkAdapter).HandleAsync)); return applicationBuilder; diff --git a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotConfigurationBuilder.cs b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotConfigurationBuilder.cs deleted file mode 100644 index 20b55def0..000000000 --- a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotConfigurationBuilder.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Microsoft.Bot.Builder.Middleware; -using Microsoft.Extensions.DependencyInjection; -using System.Collections.Generic; - -namespace Microsoft.Bot.Builder.Integration.AspNet.Core -{ - internal class BotConfigurationBuilder : IBotConfigurationBuilder - { - private readonly List _middleware = new List(); - private readonly IServiceCollection _serviceCollection; - - public BotConfigurationBuilder(IServiceCollection serviceCollection) - { - _serviceCollection = serviceCollection; - } - - public List Middleware { get => _middleware; } - } -} diff --git a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotFrameworkOptions.cs b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotFrameworkOptions.cs index 0ff7128c0..5672da768 100644 --- a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotFrameworkOptions.cs +++ b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotFrameworkOptions.cs @@ -1,9 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using Microsoft.AspNetCore.Http; -using BotMiddleware = Microsoft.Bot.Builder.Middleware; using System.Collections.Generic; +using BotMiddleware = Microsoft.Bot.Builder.Middleware; using Microsoft.Bot.Connector.Authentication; namespace Microsoft.Bot.Builder.Integration.AspNet.Core @@ -15,12 +14,10 @@ namespace Microsoft.Bot.Builder.Integration.AspNet.Core public BotFrameworkOptions() { _middleware = new List(); - - RouteBaseUrl = "/api"; } - public PathString RouteBaseUrl { get; set; } public ICredentialProvider CredentialProvider { get; set; } public IList Middleware { get => _middleware; } + public bool EnableProactiveMessages { get; set; } } } diff --git a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotFrameworkPaths.cs b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotFrameworkPaths.cs new file mode 100644 index 000000000..ad57c2cb9 --- /dev/null +++ b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotFrameworkPaths.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.AspNetCore.Http; + +namespace Microsoft.Bot.Builder.Integration.AspNet.Core +{ + public class BotFrameworkPaths + { + public BotFrameworkPaths() + { + this.BasePath = "/api"; + this.MessagesPath = "/messages"; + this.ProactiveMessagesPath = "/messages/proactive"; + } + + public PathString BasePath { get; set; } + public PathString MessagesPath { get; set; } + public PathString ProactiveMessagesPath { get; set; } + } +} \ No newline at end of file diff --git a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotMessageHandler.cs b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotMessageHandler.cs new file mode 100644 index 000000000..1a4973940 --- /dev/null +++ b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotMessageHandler.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.AspNetCore.Http; +using Microsoft.Bot.Builder.Adapters; +using Microsoft.Bot.Schema; +using Newtonsoft.Json; +using System; +using System.IO; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Bot.Builder.Integration.AspNet.Core.Handlers +{ + public class BotMessageHandler : BotMessageHandlerBase + { + public BotMessageHandler(BotFrameworkAdapter botFrameworkAdapter) : base(botFrameworkAdapter) + { + } + + protected override async Task ProcessMessageRequestAsync(HttpRequest request, BotFrameworkAdapter botFrameworkAdapter, Func botCallbackHandler) + { + var activity = default(Activity); + + using (var bodyReader = new JsonTextReader(new StreamReader(request.Body, Encoding.UTF8))) + { + activity = BotMessageHandlerBase.BotMessageSerializer.Deserialize(bodyReader); + } + + await botFrameworkAdapter.ProcessActivity( + request.Headers["Authorization"], + activity, + botCallbackHandler); + } + } +} \ No newline at end of file diff --git a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotActivitiesHandler.cs b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotMessageHandlerBase.cs similarity index 73% rename from libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotActivitiesHandler.cs rename to libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotMessageHandlerBase.cs index 70528f89a..45f89f237 100644 --- a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotActivitiesHandler.cs +++ b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotMessageHandlerBase.cs @@ -3,22 +3,19 @@ using Microsoft.AspNetCore.Http; using Microsoft.Bot.Builder.Adapters; -using Microsoft.Bot.Schema; using Microsoft.Extensions.DependencyInjection; using Microsoft.Net.Http.Headers; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using System; -using System.IO; using System.Net; -using System.Text; using System.Threading.Tasks; -namespace Microsoft.Bot.Builder.Integration.AspNet.Core +namespace Microsoft.Bot.Builder.Integration.AspNet.Core.Handlers { - internal class BotActivitiesHandler + public abstract class BotMessageHandlerBase { - private static readonly JsonSerializer ActivitySerializer = JsonSerializer.Create(new JsonSerializerSettings + public static readonly JsonSerializer BotMessageSerializer = JsonSerializer.Create(new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver(), Formatting = Newtonsoft.Json.Formatting.Indented, @@ -27,7 +24,7 @@ namespace Microsoft.Bot.Builder.Integration.AspNet.Core private BotFrameworkAdapter _botFrameworkAdapter; - public BotActivitiesHandler(BotFrameworkAdapter botFrameworkAdapter) + public BotMessageHandlerBase(BotFrameworkAdapter botFrameworkAdapter) { _botFrameworkAdapter = botFrameworkAdapter; } @@ -60,18 +57,11 @@ namespace Microsoft.Bot.Builder.Integration.AspNet.Core return; } - var activity = default(Activity); - - using (var bodyReader = new JsonTextReader(new StreamReader(request.Body, Encoding.UTF8))) - { - activity = ActivitySerializer.Deserialize(bodyReader); - } - try { - await _botFrameworkAdapter.ProcessActivity( - request.Headers["Authorization"], - activity, + await ProcessMessageRequestAsync( + request, + _botFrameworkAdapter, botContext => { var bot = httpContext.RequestServices.GetRequiredService(); @@ -86,5 +76,7 @@ namespace Microsoft.Bot.Builder.Integration.AspNet.Core response.StatusCode = (int)HttpStatusCode.Forbidden; } } + + protected abstract Task ProcessMessageRequestAsync(HttpRequest request, BotFrameworkAdapter botFrameworkAdapter, Func botCallbackHandler); } } \ No newline at end of file diff --git a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotProactiveMessageHandler.cs b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotProactiveMessageHandler.cs new file mode 100644 index 000000000..dc856e38f --- /dev/null +++ b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/BotProactiveMessageHandler.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.AspNetCore.Http; +using Microsoft.Bot.Builder.Adapters; +using Microsoft.Bot.Schema; +using Newtonsoft.Json; +using System; +using System.IO; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.Bot.Builder.Integration.AspNet.Core.Handlers +{ + public class BotProactiveMessageHandler : BotMessageHandlerBase + { + public BotProactiveMessageHandler(BotFrameworkAdapter botFrameworkAdapter) : base(botFrameworkAdapter) + { + } + + protected override async Task ProcessMessageRequestAsync(HttpRequest request, BotFrameworkAdapter botFrameworkAdapter, Func botCallbackHandler) + { + var conversationReference = default(ConversationReference); + + using (var bodyReader = new JsonTextReader(new StreamReader(request.Body, Encoding.UTF8))) + { + conversationReference = BotMessageHandlerBase.BotMessageSerializer.Deserialize(bodyReader); + } + + await botFrameworkAdapter.ContinueConversation(conversationReference, botCallbackHandler); + } + } +} \ No newline at end of file diff --git a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/ServiceCollectionExtensions.cs b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/ServiceCollectionExtensions.cs index 5941ac9a5..60e790065 100644 --- a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/ServiceCollectionExtensions.cs +++ b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.Core/ServiceCollectionExtensions.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; using Newtonsoft.Json; using System; @@ -16,18 +15,6 @@ namespace Microsoft.Bot.Builder.Integration.AspNet.Core { services.AddTransient(); - var botBuilder = new BotConfigurationBuilder(services); - - services.Configure(options => - { - var optionsMiddleware = options.Middleware; - - foreach (var mw in botBuilder.Middleware) - { - optionsMiddleware.Add(mw); - } - }); - services.Configure(setupAction); return services; diff --git a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotFrameworkConfigurationBuilder.cs b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotFrameworkConfigurationBuilder.cs index 37fb6c01f..c90114b0d 100644 --- a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotFrameworkConfigurationBuilder.cs +++ b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotFrameworkConfigurationBuilder.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using Microsoft.Bot.Builder.Middleware; +using System; using Microsoft.Bot.Connector.Authentication; namespace Microsoft.Bot.Builder.Integration.AspNet.WebApi @@ -10,9 +11,9 @@ namespace Microsoft.Bot.Builder.Integration.AspNet.WebApi { private BotFrameworkOptions _options; - public BotFrameworkConfigurationBuilder() + public BotFrameworkConfigurationBuilder(BotFrameworkOptions botFrameworkOptions) { - _options = new BotFrameworkOptions(); + _options = botFrameworkOptions; } public BotFrameworkOptions BotFrameworkOptions { get => _options; } @@ -33,5 +34,25 @@ namespace Microsoft.Bot.Builder.Integration.AspNet.WebApi return this; } + + public BotFrameworkConfigurationBuilder EnableProactiveMessages(string proactiveMessagesPath = default(string)) + { + _options.EnableProactiveMessages = true; + + if (proactiveMessagesPath != null) + +{ + _options.Paths.ProactiveMessagesPath = proactiveMessagesPath; + } + + return this; + } + + public BotFrameworkConfigurationBuilder UsePaths(Action configurePaths) + { + configurePaths(_options.Paths); + + return this; + } } } \ No newline at end of file diff --git a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotFrameworkOptions.cs b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotFrameworkOptions.cs index e9e7bcf96..60c73fb7d 100644 --- a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotFrameworkOptions.cs +++ b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotFrameworkOptions.cs @@ -10,15 +10,17 @@ namespace Microsoft.Bot.Builder.Integration.AspNet.WebApi public class BotFrameworkOptions { private readonly List _middleware; + private readonly BotFrameworkPaths _paths; public BotFrameworkOptions() { - RouteBaseUrl = "api/"; _middleware = new List(); + _paths = new BotFrameworkPaths(); } - public string RouteBaseUrl { get; set; } public ICredentialProvider CredentialProvider { get; set; } public List Middleware { get => _middleware; } + public bool EnableProactiveMessages { get; set; } + public BotFrameworkPaths Paths { get => _paths; } } } \ No newline at end of file diff --git a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotFrameworkPaths.cs b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotFrameworkPaths.cs new file mode 100644 index 000000000..db0e93f52 --- /dev/null +++ b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotFrameworkPaths.cs @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Bot.Builder.Integration.AspNet.WebApi +{ + public class BotFrameworkPaths + { + public BotFrameworkPaths() + { + this.BasePath = "api/"; + this.MessagesPath = "messages"; + this.ProactiveMessagesPath = "messages/proactive"; + } + + public string BasePath { get; set; } + public string MessagesPath { get; set; } + public string ProactiveMessagesPath { get; set; } + } +} \ No newline at end of file diff --git a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotMessageHandler.cs b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotMessageHandler.cs new file mode 100644 index 000000000..ed0b48681 --- /dev/null +++ b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotMessageHandler.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Bot.Builder.Adapters; +using Microsoft.Bot.Schema; +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Bot.Builder.Integration.AspNet.WebApi.Handlers +{ + internal sealed class BotMessageHandler : BotMessageHandlerBase + { + public BotMessageHandler(BotFrameworkAdapter botFrameworkAdapter) : base(botFrameworkAdapter) + { + } + + protected override async Task ProcessMessageRequestAsync(HttpRequestMessage request, BotFrameworkAdapter botFrameworkAdapter, Func botCallbackHandler, CancellationToken cancellationToken) + { + var activity = await request.Content.ReadAsAsync(BotMessageHandlerBase.BotMessageMediaTypeFormatters, cancellationToken); + + await botFrameworkAdapter.ProcessActivity( + request.Headers.Authorization?.Parameter, + activity, + botCallbackHandler); + } + } +} \ No newline at end of file diff --git a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotActivitiesHandler.cs b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotMessageHandlerBase.cs similarity index 72% rename from libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotActivitiesHandler.cs rename to libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotMessageHandlerBase.cs index e84e10029..a3c2628dd 100644 --- a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotActivitiesHandler.cs +++ b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotMessageHandlerBase.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using Microsoft.Bot.Builder.Adapters; -using Microsoft.Bot.Schema; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using System; @@ -12,11 +11,11 @@ using System.Net.Http.Formatting; using System.Threading; using System.Threading.Tasks; -namespace Microsoft.Bot.Builder.Integration.AspNet.WebApi +namespace Microsoft.Bot.Builder.Integration.AspNet.WebApi.Handlers { - internal sealed class BotActivitiesHandler : HttpMessageHandler + public abstract class BotMessageHandlerBase : HttpMessageHandler { - private static readonly MediaTypeFormatter[] BotActivityMediaTypeFormatters = new [] { + public static readonly MediaTypeFormatter[] BotMessageMediaTypeFormatters = new [] { new JsonMediaTypeFormatter { SerializerSettings = @@ -30,7 +29,7 @@ namespace Microsoft.Bot.Builder.Integration.AspNet.WebApi private readonly BotFrameworkAdapter _botFrameworkAdapter; - public BotActivitiesHandler(BotFrameworkAdapter botFrameworkAdapter) + public BotMessageHandlerBase(BotFrameworkAdapter botFrameworkAdapter) { _botFrameworkAdapter = botFrameworkAdapter; } @@ -42,26 +41,23 @@ namespace Microsoft.Bot.Builder.Integration.AspNet.WebApi return request.CreateResponse(HttpStatusCode.MethodNotAllowed); } - var requestContent = request.Content; - var requestContentHeaders = requestContent.Headers; + var requestContentHeaders = request.Content.Headers; if (requestContentHeaders.ContentLength == 0) { return request.CreateErrorResponse(HttpStatusCode.BadRequest, "Request body should not be empty."); } - if (!BotActivityMediaTypeFormatters[0].SupportedMediaTypes.Contains(requestContentHeaders.ContentType)) + if (!BotMessageMediaTypeFormatters[0].SupportedMediaTypes.Contains(requestContentHeaders.ContentType)) { - return request.CreateErrorResponse(HttpStatusCode.NotAcceptable, $"Expecting Content-Type of \"{BotActivityMediaTypeFormatters[0].SupportedMediaTypes[0].MediaType}\"."); + return request.CreateErrorResponse(HttpStatusCode.NotAcceptable, $"Expecting Content-Type of \"{BotMessageMediaTypeFormatters[0].SupportedMediaTypes[0].MediaType}\"."); } - var activity = await requestContent.ReadAsAsync(BotActivitiesHandler.BotActivityMediaTypeFormatters, cancellationToken); - try { - await _botFrameworkAdapter.ProcessActivity( - request.Headers.Authorization?.Parameter, - activity, + await ProcessMessageRequestAsync( + request, + _botFrameworkAdapter, botContext => { cancellationToken.ThrowIfCancellationRequested(); @@ -77,13 +73,14 @@ namespace Microsoft.Bot.Builder.Integration.AspNet.WebApi bot = null; } - if(bot == null) + if (bot == null) { throw new InvalidOperationException($"Did not find an {typeof(IBot).Name} service via the dependency resolver. Please make sure you have registered your bot with your dependency injection container."); } return bot.OnReceiveActivity(botContext); - }); + }, + cancellationToken); return request.CreateResponse(HttpStatusCode.OK); } @@ -96,5 +93,7 @@ namespace Microsoft.Bot.Builder.Integration.AspNet.WebApi return request.CreateErrorResponse(HttpStatusCode.NotFound, e.Message); } } + + protected abstract Task ProcessMessageRequestAsync(HttpRequestMessage request, BotFrameworkAdapter botFrameworkAdapter, Func botCallbackHandler, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotProactiveMessageHandler.cs b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotProactiveMessageHandler.cs new file mode 100644 index 000000000..d0ec0b558 --- /dev/null +++ b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/BotProactiveMessageHandler.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Bot.Builder.Adapters; +using Microsoft.Bot.Schema; +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Bot.Builder.Integration.AspNet.WebApi.Handlers +{ + public sealed class BotProactiveMessageHandler : BotMessageHandlerBase + { + public BotProactiveMessageHandler(BotFrameworkAdapter botFrameworkAdapter) : base(botFrameworkAdapter) + { + } + + protected override async Task ProcessMessageRequestAsync(HttpRequestMessage request, BotFrameworkAdapter botFrameworkAdapter, Func botCallbackHandler, CancellationToken cancellationToken) + { + var conversationReference = await request.Content.ReadAsAsync(BotMessageHandlerBase.BotMessageMediaTypeFormatters, cancellationToken); + + await botFrameworkAdapter.ContinueConversation(conversationReference, botCallbackHandler); + } + } +} \ No newline at end of file diff --git a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/HttpConfigurationExtensions.cs b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/HttpConfigurationExtensions.cs index c03b09fe7..5e6a4c004 100644 --- a/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/HttpConfigurationExtensions.cs +++ b/libraries/integration/Microsoft.Bot.Builder.Integration.AspNet.WebApi/HttpConfigurationExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using Microsoft.Bot.Builder.Adapters; +using Microsoft.Bot.Builder.Integration.AspNet.WebApi.Handlers; using System; using System.Web.Http; @@ -11,13 +12,12 @@ namespace Microsoft.Bot.Builder.Integration.AspNet.WebApi { public static HttpConfiguration MapBotFramework(this HttpConfiguration httpConfiguration, Action configurer) { - var optionsBuilder = new BotFrameworkConfigurationBuilder(); + var options = new BotFrameworkOptions(); + var optionsBuilder = new BotFrameworkConfigurationBuilder(options); configurer(optionsBuilder); - var options = optionsBuilder.BotFrameworkOptions; - - ConfigureBotRoute(BuildAdapter()); + ConfigureBotRoutes(BuildAdapter()); return httpConfiguration; @@ -33,23 +33,32 @@ namespace Microsoft.Bot.Builder.Integration.AspNet.WebApi return adapter; } - void ConfigureBotRoute(BotFrameworkAdapter adapter) + void ConfigureBotRoutes(BotFrameworkAdapter adapter) { - var botActivitiesRouteUrl = options.RouteBaseUrl; + var routes = httpConfiguration.Routes; + var baseUrl = options.Paths.BasePath; - if (!botActivitiesRouteUrl.EndsWith("/")) + if (!baseUrl.EndsWith("/")) { - botActivitiesRouteUrl += "/"; + baseUrl += "/"; } - botActivitiesRouteUrl += "messages"; - - httpConfiguration.Routes.MapHttpRoute( - "BotFrameworkV4 Activities Controller", - botActivitiesRouteUrl, + if (options.EnableProactiveMessages) + { + routes.MapHttpRoute( + "BotFramework - Proactive Message Handler", + baseUrl + options.Paths.ProactiveMessagesPath, defaults: null, constraints: null, - handler: new BotActivitiesHandler(adapter)); + handler: new BotProactiveMessageHandler(adapter)); + } + + routes.MapHttpRoute( + "BotFramework - Message Handler", + baseUrl + options.Paths.MessagesPath, + defaults: null, + constraints: null, + handler: new BotMessageHandler(adapter)); } } } diff --git a/samples/Microsoft.Bot.Samples.Connector.EchoBot/Startup.cs b/samples/Microsoft.Bot.Samples.Connector.EchoBot/Startup.cs index 19b254fef..c8c523d91 100644 --- a/samples/Microsoft.Bot.Samples.Connector.EchoBot/Startup.cs +++ b/samples/Microsoft.Bot.Samples.Connector.EchoBot/Startup.cs @@ -36,6 +36,7 @@ namespace Connector.Echo { options.CredentialProvider = new ConfigurationCredentialProvider(Configuration); options.Middleware.Add(new ConversationState(new MemoryStorage())); + options.EnableProactiveMessages = true; }); services.AddTransient(); diff --git a/samples/Microsoft.Bot.Samples.EchoBot-AspNet461/App_Start/BotConfig.cs b/samples/Microsoft.Bot.Samples.EchoBot-AspNet461/App_Start/BotConfig.cs index 0ccc87368..0f1b09bd1 100644 --- a/samples/Microsoft.Bot.Samples.EchoBot-AspNet461/App_Start/BotConfig.cs +++ b/samples/Microsoft.Bot.Samples.EchoBot-AspNet461/App_Start/BotConfig.cs @@ -18,6 +18,7 @@ namespace Microsoft.Bot.Samples.EchoBot_AspNet461 { botConfig .UseMicrosoftApplicationIdentity(ConfigurationManager.AppSettings["BotFramework.MicrosoftApplicationId"], ConfigurationManager.AppSettings["BotFramework.MicrosoftApplicationPassword"]) + .EnableProactiveMessages() .UseMiddleware(new ConversationState(new MemoryStorage())); }); } diff --git a/samples/Microsoft.Bot.Samples.EchoBot-AspNet461/Global.asax.cs b/samples/Microsoft.Bot.Samples.EchoBot-AspNet461/Global.asax.cs index 709178653..7f5835c52 100644 --- a/samples/Microsoft.Bot.Samples.EchoBot-AspNet461/Global.asax.cs +++ b/samples/Microsoft.Bot.Samples.EchoBot-AspNet461/Global.asax.cs @@ -8,8 +8,8 @@ namespace Microsoft.Bot.Samples.EchoBot_AspNet461 { GlobalConfiguration.Configure(config => { - WebApiConfig.Register(config); BotConfig.Register(config); + WebApiConfig.Register(config); }); } }