diff --git a/IntermediatorBotSample/Bot/IntermediatorBot.cs b/IntermediatorBotSample/Bot/IntermediatorBot.cs index 2ce893d..189b599 100644 --- a/IntermediatorBotSample/Bot/IntermediatorBot.cs +++ b/IntermediatorBotSample/Bot/IntermediatorBot.cs @@ -3,6 +3,7 @@ using Microsoft.Bot.Builder; using Microsoft.Bot.Schema; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; namespace IntermediatorBotSample.Bot @@ -11,7 +12,7 @@ public class IntermediatorBot : IBot { private const string SampleUrl = "https://github.com/tompaana/intermediator-bot-sample"; - public async Task OnTurn(ITurnContext context) + public async Task OnTurnAsync(ITurnContext context, CancellationToken ct) { Command showOptionsCommand = new Command(Commands.ShowOptions); @@ -33,7 +34,7 @@ public async Task OnTurn(ITurnContext context) Activity replyActivity = context.Activity.CreateReply(); replyActivity.Attachments = new List() { heroCard.ToAttachment() }; - await context.SendActivity(replyActivity); + await context.SendActivityAsync(replyActivity); } } } diff --git a/IntermediatorBotSample/CommandHandling/Command.cs b/IntermediatorBotSample/CommandHandling/Command.cs index c757c20..17a534d 100644 --- a/IntermediatorBotSample/CommandHandling/Command.cs +++ b/IntermediatorBotSample/CommandHandling/Command.cs @@ -262,7 +262,10 @@ public static Commands StringToCommand(string commandAsString) { if (Enum.TryParse(commandAsString, out Commands result)) { - return result; + if (Enum.IsDefined(typeof(Commands), commandAsString)) + { + return result; + } } foreach (Commands command in Enum.GetValues(typeof(Commands))) diff --git a/IntermediatorBotSample/CommandHandling/CommandHandler.cs b/IntermediatorBotSample/CommandHandling/CommandHandler.cs index b67f433..51cd1d5 100644 --- a/IntermediatorBotSample/CommandHandling/CommandHandler.cs +++ b/IntermediatorBotSample/CommandHandling/CommandHandler.cs @@ -266,7 +266,7 @@ await _connectionRequestHandler.AcceptOrRejectRequestAsync( if (replyActivity != null) { - await context.SendActivity(replyActivity); + await context.SendActivityAsync(replyActivity); } return wasHandled; diff --git a/IntermediatorBotSample/IntermediatorBotSample.csproj b/IntermediatorBotSample/IntermediatorBotSample.csproj index 3c91270..419b9f5 100644 --- a/IntermediatorBotSample/IntermediatorBotSample.csproj +++ b/IntermediatorBotSample/IntermediatorBotSample.csproj @@ -1,15 +1,26 @@ - + - netcoreapp2.0 + netcoreapp2.2 - - - - - + + + + + + + + + + + + + + + + diff --git a/IntermediatorBotSample/Middleware/CatchExceptionMiddleware.cs b/IntermediatorBotSample/Middleware/CatchExceptionMiddleware.cs new file mode 100644 index 0000000..99b57ff --- /dev/null +++ b/IntermediatorBotSample/Middleware/CatchExceptionMiddleware.cs @@ -0,0 +1,44 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Bot.Builder.Core.Extensions +{ + /// + /// This piece of middleware can be added to allow you to handle exceptions when they are thrown + /// within your bot's code or middleware further down the pipeline. Using this handler you might + /// send an appropriate message to the user to let them know that something has gone wrong. + /// You can specify the type of exception the middleware should catch and this middleware can be added + /// multiple times to allow you to handle different exception types in different ways. + /// + /// + /// The type of the exception that you want to catch. This can be 'Exception' to + /// catch all or a specific type of exception + /// + public class CatchExceptionMiddleware : IMiddleware where T : Exception + { + private readonly Func _handler; + + public CatchExceptionMiddleware(Func callOnException) + { + _handler = callOnException; + } + + public async Task OnTurnAsync(ITurnContext context, NextDelegate next, CancellationToken cancellationToken = default(CancellationToken)) + { + try + { + // Continue to route the activity through the pipeline + // any errors further down the pipeline will be caught by + // this try / catch + await next(cancellationToken).ConfigureAwait(false); + } + catch (T ex) + { + // If an error is thrown and the exception is of type T then invoke the handler + await _handler.Invoke(context, ex).ConfigureAwait(false); + } + } + + } +} diff --git a/IntermediatorBotSample/Middleware/HandoffMiddleware.cs b/IntermediatorBotSample/Middleware/HandoffMiddleware.cs index 645116f..ec10d32 100644 --- a/IntermediatorBotSample/Middleware/HandoffMiddleware.cs +++ b/IntermediatorBotSample/Middleware/HandoffMiddleware.cs @@ -6,6 +6,7 @@ using Microsoft.Bot.Schema; using Microsoft.Extensions.Configuration; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using Underscore.Bot.MessageRouting; using Underscore.Bot.MessageRouting.DataStore; @@ -89,7 +90,7 @@ public HandoffMiddleware(IConfiguration configuration) MessageLogs = new MessageLogs(connectionString); } - public async Task OnTurn(ITurnContext context, MiddlewareSet.NextDelegate next) + public async Task OnTurnAsync(ITurnContext context, NextDelegate next, CancellationToken ct) { Activity activity = context.Activity; @@ -134,7 +135,7 @@ public async Task OnTurn(ITurnContext context, MiddlewareSet.NextDelegate next) else { // No action taken - this middleware did not consume the activity so let it propagate - await next().ConfigureAwait(false); + await next(ct).ConfigureAwait(false); } } } @@ -148,6 +149,10 @@ public async Task OnTurn(ITurnContext context, MiddlewareSet.NextDelegate next) // Handle the result, if necessary await MessageRouterResultHandler.HandleResultAsync(messageRouterResult); } + else + { + await next(ct).ConfigureAwait(false); + } } /// diff --git a/IntermediatorBotSample/Startup.cs b/IntermediatorBotSample/Startup.cs index 0179b49..31ce4fe 100644 --- a/IntermediatorBotSample/Startup.cs +++ b/IntermediatorBotSample/Startup.cs @@ -2,8 +2,10 @@ using IntermediatorBotSample.Middleware; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.Bot.Builder.BotFramework; +using Microsoft.Bot.Builder; using Microsoft.Bot.Builder.Core.Extensions; +using Microsoft.Bot.Builder.BotFramework; +using Microsoft.Bot.Builder.Integration; using Microsoft.Bot.Builder.Integration.AspNet.Core; using Microsoft.Bot.Builder.TraceExtensions; using Microsoft.Extensions.Configuration; @@ -50,8 +52,8 @@ public void ConfigureServices(IServiceCollection services) // an "Ooops" message is sent. options.Middleware.Add(new CatchExceptionMiddleware(async (context, exception) => { - await context.TraceActivity("Bot Exception", exception); - await context.SendActivity($"Sorry, it looks like something went wrong: {exception.Message}"); + await context.TraceActivityAsync("Bot Exception", exception); + await context.SendActivityAsync($"Sorry, it looks like something went wrong: {exception.Message}"); })); // The Memory Storage used here is for local bot debugging only. When the bot @@ -94,13 +96,7 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env) app.UseDefaultFiles() .UseStaticFiles() .UseMvc() // Required Razor pages - .UseBotFramework(bot => - { - // This is how you can define a custom endpoint in case you're unhappy with - // the default "/api/messages": - bot.BasePath = Configuration["BotBasePath"]; - bot.MessagesPath = Configuration["BotMessagesPath"]; - }); + .UseBotFramework(); } } }