I am trying to add middleware into echo bot, that converts message into lower cases.
I have created Middleware class that inherits from IMiddleware
public class MiddlewareOne : IMiddleware
{
public async Task OnTurnAsync(ITurnContext turnContext, NextDelegate next, CancellationToken cancellationToken = default)
{
if(turnContext.Activity.Type == ActivityTypes.Message)
{
Debug.WriteLine(turnContext.Activity.Text);
turnContext.Activity.Text = turnContext.Activity.Text.ToLower();
await next(cancellationToken);
Debug.WriteLine(turnContext.Activity.Text);
}
else
{
await next(cancellationToken);
}
}
}
}
Now I am trying to add it into Startup.cs file. I found somewhere it should be added as Transient.
services.AddTransient<MiddlewareOne>();
Still, it's not working. I think MiddlewareOne class is okay, but how should I configure it in Startup.cs file?
Thank you
You have to register the middleware in your BotFrameworkAdapter descendant (e.g. BotFrameworkHttpAdapter) by calling the Use method in constructor. You can pass the middleware as a constructor parameter and DI will take care of activation.
An example (made without VS assistance)
public class MyAdapter : BotFrameworkHttpAdapter
{
public MyAdapter(MiddlewareOne mw1, IConfiguration configuration, ILogger<BotFrameworkHttpAdapter> logger)
: base(configuration, logger)
{
Use(mw1);
// other code..
}
}
Related
I use the CQS pattern in my asp.net core project. Let's start with an example to better explain what I want to achieve. I created a command:
public class EmptyCommand : INotification{}
The command handler:
public class EmptyCommandHandler : INotificationHandler<EmptyCommand>
{
public Task Handle(EmptyCommand notification, CancellationToken cancellationToken)
{
return Task.FromResult(string.Empty);
}
}
The query:
public class EmptyQuery : IRequest<string>{}
The query handler:
public class EmptyQueryHandler : IRequestHandler<EmptyQuery, string>
{
public Task<string> Handle(EmptyQuery notification, CancellationToken cancellationToken)
{
return Task.FromResult(string.Empty);
}
}
and this is a simple example of how to run the command and query and invoke the Handle method from the EmptyCommandHandler and EmptyQueryHandler:
readonly IMediator _mediator;
public HomeController(IMediator mediator)
{
_mediator = mediator;
}
public async Task<IActionResult> Index()
{
await _mediator.Publish(new EmptyCommand());
var queryResult = await _mediator.Send(new EmptyQuery());
return View();
}
Please bear in mind that query can return other types not necessarily the string.
I would like to create some kind of a bridge class e.g. MediatorBoostrapper, which allows me to run some business logic(e.g. log command/query via Logger) every time the Publish method is invoked and then
invoke the public Task Handle(EmptyCommand notification,... method from the command handler. The solution must be generic, so this method would be invoked every time I run the Publish method. I also want to be able to do the same thing for the Send method.
I was thinking about the creation of the public class MediatorBoostrapper : IMediator
but not sure what should be a proper implementation of the class and if my idea is good.
Any ideas? Cheers
Edit
I want to have an example of how to use the Behaviors
to create a generic way to run some external method from the generic handler every time I Run the Send method for queries. I want to have a similar example for Publish method, which I use for sending commands.
I want to have an example of how to use Polymorphic dispatch
for the creation of the GenericCommandHandler and a GenericQueryHandler
I created a sample project on GitHub which can be found here
You can feel free to try to extend this project with your solution.
This time I want to answer the question starting from the end.
2.
TL;DR Polymorphic Dispatch cannot be used for the CQS
After some time of playing with the MediatR library, reading the comments under my Question and consultation with my friend, I found the Polymorphic Dispatch(PD) can be used to create a generic handler only in case of the Commands. The PD solution cannot be implemented for Queries. Based on the Documentation, the handlers are contravariant and not covariant. This means the PD works only in the case where the TResponse is a constant type. In case of the Queries, this is false and each Query handler can return a different result.
I also found this issue. I think it's interesting to know you can use the Polymorphic Dispatch only if your container supports it.
1. Behaviors is the one and only solution for CQS when using the MediatR.
Based on the comment under my question from #Steve and comment from jbogard I've found the way how to use Behaviors and IRequestHandler for the strict Command pattern. The full comment:
Just to summarize the changes, there are 2 main flavors of requests:
those that return a value, and those that do not. The ones that do not
now implement IRequest<T> where T : Unit. This was to unify requests
and handlers into one single type. The diverging types broke the
pipeline for many containers, the unification means you can use
pipelines for any kind of request.
It forced me to add the Unit type in all cases, so I've added some helper classes for you.
IRequestHandler<T> - implement this and you will return Task<Unit>.
AsyncRequestHandler<T> - inherit this and you will return Task.
RequestHandler<T> - inherit this and you will return nothing (void).
For requests that do return values:
IRequestHandler<T, U> - you will return Task<U>
RequestHandler<T, U> - you will return U
I got rid of the AsyncRequestHandler because it really wasn't doing anything after the consolidation, a redundant base class.
The example
a) The Commands management:
public class EmptyCommand : IRequest{...}
public class EmptyCommandHandler : RequestHandler<EmptyCommand>
{
protected override void Handle(EmptyCommand request){...}
}
b) The Queries management:
// can be any other type not necessarily `string`
public class EmptyQuery : IRequest<string>{...}
public class EmptyQueryHandler : IRequestHandler<EmptyQuery, string>
{
public Task<string> Handle(EmptyQuery notification, CancellationToken cancellationToken)
{
return Task.FromResult("Sample response");
}
}
c) The sample LogginBehavior class:
public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
readonly ILogger<LoggingBehavior<TRequest, TResponse>> _logger;
public LoggingBehavior(ILogger<LoggingBehavior<TRequest, TResponse>> logger)
{
_logger = logger;
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var requestType = typeof(TRequest).Name;
var response = await next();
if (requestType.EndsWith("Command"))
{
_logger.LogInformation($"Command Request: {request}");
}
else if (requestType.EndsWith("Query"))
{
_logger.LogInformation($"Query Request: {request}");
_logger.LogInformation($"Query Response: {response}");
}
else
{
throw new Exception("The request is not the Command or Query type");
}
return response;
}
}
d) To register the LoggingBehavior add the command
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
to the body of the ConfigureServices method in the Startup.cs.
e) The example of how to run sample command and query:
await _mediator.Send(new EmptyCommand());
var result = await _mediator.Send(new EmptyQuery());
MediatR supports dispatching notifications to generic handlers (polymorphic dispatch). For example:
public class GenericHandler<TNotification> : INotificationHandler<TNotification>
where TNotification : INotification
{
public Task Handle(TNotification notification, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
This handler will be invoked for every notification that is published through Publish(). The same is true for requests (queries/commands). You should also take a look at behaviors.
If you're using MediatR with ASP.NET Core I suggest you use the MediatR.Extensions.Microsoft.DependencyInjection library which takes care of wiring all the handlers together.
[NOTE: This is a "replacement" question. The first one was based on my main project's code so I've redone the question with code from a single-purpose project that illustrates the principle more cleanly. The question remains the same, just better presented.]
The Scenario
I'm trying to setup a command pre-processor on a CQRS request pipeline using MediatR pipeline behaviors and Autofac for request routing. My goal is for the pre-processor to run only for commands (ICommand<>) as opposed to all requests (IRequest<>), which will result in the pre-processor executing for commands, queries and events.
The Issue
I can get my GenericPreProcessor or any other pre-processor to run fine for all types of requests, but any method I've used to try to "filter" the injection either returns an error or simply doesn't execute the desired pre-processor.
My working-for-all-requests pipeline configuration in Autofac looks like this:
// Pipeline pre/post processors
builder
.RegisterGeneric(typeof(RequestPostProcessorBehavior<,>))
.As(typeof(IPipelineBehavior<,>));
builder
.RegisterGeneric(typeof(RequestPreProcessorBehavior<,>))
.As(typeof(IPipelineBehavior<,>));
// Works as desired: Fires generic pre-processor for ALL requests, both cmd and query
builder
.RegisterGeneric(typeof(GenericRequestPreProcessor<>))
.As(typeof(IRequestPreProcessor<>));
// Works for all requests, but I need a way to limit it to commands
builder
.RegisterGeneric(typeof(MyCommandPreProcessor<>))
.As(typeof(IRequestPreProcessor<>));
Conceptually I'm trying to do something like any of these, which fail:
builder
.RegisterGeneric(typeof(MyCommandPreProcessor<>)) // Note generic
.As(typeof(IRequestPreProcessor<ICommand<>>));
// Intellisense error "Unexpected use of an unbound generic"
builder
.RegisterType(typeof(MyCommandPreProcessor)) // Note non-generic
.As(typeof(IRequestPreProcessor<ICommand<>>));
// Intellisense error "Unexpected use of an unbound generic"
builder
.RegisterType(typeof(MyCommandPreProcessor)) // Note non-generic
.As(typeof(IRequestPreProcessor<ICommand<CommonResult>>));
// No errors, but MyCommandPreProcessor not firing
I'm trying a couple of different configurations for MyCommandPreProcessor, a generic and a non-generic but am stumped with either:
public class MyCommandPreProcessor<TRequest> : IRequestPreProcessor<TRequest>
{
public Task Process(TRequest request, CancellationToken cancellationToken)
{
Debug.WriteLine("***** MYCOMMAND PREPROCESSOR CALLED *****");
return Task.CompletedTask;
}
}
- OR -
public class MyCommandPreProcessor : IRequestPreProcessor<IRequest<ICommonResponse>>
{
public Task Process(TRequest request, CancellationToken cancellationToken)
{
Debug.WriteLine("***** MYCOMMAND PREPROCESSOR CALLED *****");
return Task.CompletedTask;
}
}
My Question
Any ideas on how I can register a pre-processor that will be restricted to only fire for IRequest<> types that are closed types of ICommand<>?
Supporting Materials
Project on GitHub
The entire minimal sample project can be viewed or cloned at https://github.com/jhoiby/MediatRPreProcessorTest
Autofac MediatR Config
A working config, with a single GenericRequestPreProcessor for all requests.
builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly).AsImplementedInterfaces();
var mediatrOpenTypes = new[]
{
typeof(IRequestHandler<,>),
typeof(IRequestHandler<>),
typeof(INotificationHandler<>)
};
foreach (var mediatrOpenType in mediatrOpenTypes)
{
// Register all command handler in the same assembly as WriteLogMessageCommandHandler
builder
.RegisterAssemblyTypes(typeof(MyCommandHandler).GetTypeInfo().Assembly)
.AsClosedTypesOf(mediatrOpenType)
.AsImplementedInterfaces();
// Register all QueryHandlers in the same assembly as GetExternalLoginQueryHandler
builder
.RegisterAssemblyTypes(typeof(MyQueryHandler).GetTypeInfo().Assembly)
.AsClosedTypesOf(mediatrOpenType)
.AsImplementedInterfaces();
}
// Pipeline pre/post processors
builder.RegisterGeneric(typeof(RequestPostProcessorBehavior<,>)).As(typeof(IPipelineBehavior<,>));
builder.RegisterGeneric(typeof(RequestPreProcessorBehavior<,>)).As(typeof(IPipelineBehavior<,>));
builder.RegisterGeneric(typeof(GenericRequestPreProcessor<>)).As(typeof(IRequestPreProcessor<>));
// builder.RegisterGeneric(typeof(GenericRequestPostProcessor<,>)).As(typeof(IRequestPostProcessor<,>));
// builder.RegisterGeneric(typeof(GenericPipelineBehavior<,>)).As(typeof(IPipelineBehavior<,>));
builder.Register<SingleInstanceFactory>(ctx =>
{
var c = ctx.Resolve<IComponentContext>();
return t => c.Resolve(t);
});
builder.Register<MultiInstanceFactory>(ctx =>
{
var c = ctx.Resolve<IComponentContext>();
return t => (IEnumerable<object>)c.Resolve(typeof(IEnumerable<>).MakeGenericType(t));
});
MyCommandPreProcessor Class
I'm experimenting with both of these, generic and non-generic:
public class MyCommandPreProcessor<TRequest> : IRequestPreProcessor<TRequest>
{
public Task Process(TRequest request, CancellationToken cancellationToken)
{
Debug.WriteLine("***** MYCOMMAND PREPROCESSOR CALLED *****");
return Task.CompletedTask;
}
}
- AND -
public class MyCommandPreProcessor : IRequestPreProcessor<IRequest<ICommonResponse>>
{
public Task Process(TRequest request, CancellationToken cancellationToken)
{
Debug.WriteLine("***** MYCOMMAND PREPROCESSOR CALLED *****");
return Task.CompletedTask;
}
}
Inheritance Structures
// Requests
IMediatR.IRequest<TResponse>
<- IMessage<TResponse>
<- ICommand<TResponse>
<- concrete MyCommand : ICommand<CommonResponse>
<- IQuery<TResponse>
<- concrete MyQuery : IQuery<CommonResponse>
// Request Handlers
IMediatR.IRequestHandler<in TRequest,TResponse>
<- IMessageHandler<in TRequest,TResponse>
<- ICommandHandler<in TRequest,TResponse>
<- concrete MyCommandHandler : ICommandHandler<MyCommand,CommonResponse>
<- IQueryHandler<In TRequest,TResponse>
<- concrete MyQueryHandler : IQueryHandler<MyQuery,CommonResponse>
// CommonResponse - A POCO that returns result info
ICommonResponse
<- concrete CommonResponse
Commands
public interface IMessage<TResponse> : MediatR.IRequest<TResponse>
{
}
public interface ICommand<TResponse> : IMessage<TResponse>
{
}
public class MyCommand : ICommand<CommonResponse>
{
}
Command Handlers
public interface IMessageHandler<in TRequest, TResponse>
: MediatR.IRequestHandler<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
}
public interface ICommandHandler<in TRequest, TResponse>
: IMessageHandler<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
}
public class MyCommandHandler : ICommandHandler<MyCommand, CommonResponse>
{
public async Task<CommonResponse> Handle(
MyCommand request,
CancellationToken cancellationToken)
{
Debug.WriteLine(" ***** Command handler executing *****");
return
new CommonResponse(
succeeded: true,
data: "Command execution completed successfully.");
}
}
PreProcessor Injection Target (in the MediatR Pipeline Code)
The constructor that receives the injected IRequestPreProcessor<> is:
public RequestPreProcessorBehavior(IEnumerable<IRequestPreProcessor<TRequest>> preProcessors)
{
...
}
It can be seen on Github on line 17 of the file at:
https://github.com/jbogard/MediatR/blob/master/src/MediatR/Pipeline/RequestPreProcessorBehavior.cs
Thank you!
I have the same exact scenario as you and I believe the issue is stemming from RequestPreProcessorBehavior<TRequest, TResponse> not passing all types down to IRequestPreProcessor<TRequest>.
You either:
No constraints: check the type of request in MyCommandPreProcessor<TRequest> in every IRequestPreProcessor:
public Task Process(TRequest request, CancellationToken cancellationToken)
{
var isCommand = typeof(TRequest).GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICommand<>));
if (isCommand)
{
// Magic
}
}
Create your own pre-processing behavior that exposes TRequest of IPipelineBehavior<TRequest, TResponse>:
public interface IRequestPreProcessor<in TRequest, TResponse> : IRequestPreProcessor<TRequest>
where TRequest : IRequest<TResponse>
{
}
public class MyRequestPreProcessorBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
private readonly IEnumerable<IRequestPreProcessor<TRequest, TResponse>> _preProcessors;
public RequestPreProcessorBehavior(IEnumerable<IRequestPreProcessor<TRequest, TResponse>> preProcessors)
{
_preProcessors = preProcessors;
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
foreach (var processor in _preProcessors)
{
await processor.Process(request, cancellationToken).ConfigureAwait(false);
}
return await next().ConfigureAwait(false);
}
}
With option 2, you would add constraints to any class that implemented IRequestPreProcessor<TRequest, TResponse> for command / query specific pre-processors.
Just add the interface on command/query class and add the preprocessor for that interface.
Please go through the below example
public interface IUser{}
public class AddUserCommand: IUser, IRequest<UserModel>{....
public class UpdateUserCommand: IUser, IRequest<UserModel>{....
public class GetUserQuery: IRequest<UserModel>{....
remember: here in above classes GetUserQuery class don't have IUser interface.
Now lets create the pre-processor class which execute only for command/query which marked with IUser interface
public class UserCommandQueryPrepProcessor<T>: IRequestPreProcessor<T> where T: IUser
{.....
public Task Process(T request, CancellationToken token)
{ //enter your interface specific logic here
}
}
Note: above UserCommandQueryPrepProcessor class is a generic class with where IUser which executes only for class 'AddUserCommand' and 'UpdateUserCommand' inheriting IUser interface.
I am adding a global error handler filter in Startup.cs like this:
services.AddMvc(o =>
{
o.Filters.Add(new GlobalExceptionFilter());
});
However, I need to pass in my Email Service which is also being injected. How can I retrieve it from these services in the filter?
public class GlobalExceptionFilter : IExceptionFilter
{
private readonly IEmailService _emailService;
public GlobalExceptionFilter()
{
}
public void OnException(ExceptionContext context)
{
}
}
I use to be able to use DependencyResolver Class to do that in MVC5. Is there a way to accomplish this in core? Or is there a way for me to force instantiation of the service in the Startup so I can pass it as part of the constructor?
I tried looking it up in the services and then looking at ImplementationInstance, but its null at this point so I can't grab it from there it appears. Also keep in mind that my EmailService requires a parameter of IOptions<Settings> so that it can get email settings it needs.
You can use constructor injection.
public class GlobalExceptionFilter : IExceptionFilter
{
private readonly IEmailService emailService;
public GlobalExceptionFilter(IEmailService emailService)
{
this.emailService = emailService;
}
public void OnException(ExceptionContext context)
{
//do something with this.emailService
}
}
But you have to change the way you are registering the global filter in ConfigureServices method. You should use the Add overload which takes a Type
services.AddMvc(o =>
{
o.Filters.Add(typeof(GlobalExceptionFilter));
});
Another option is, explicitly resolving the dependency inside the OnException method by calling the GetService method on HttpContext.RequestServices.
using Microsoft.Extensions.DependencyInjection;
public void OnException(ExceptionContext context)
{
var emailService = context.HttpContext.RequestServices.GetService<IEmailService>();
// use emailService
}
But you should be fine with the first approach. Let the framework resolve it for you and inject to your constructor instead of you trying to do it.
I think best practice for a Global Exception Handler is actually to create a custom middleware step for it. From the documentation
Exception filters are good for trapping exceptions that occur within MVC actions, but they're not as flexible as error handling middleware. Prefer middleware for the general case, and use filters only where you need to do error handling differently based on which MVC action was chosen.
Then you register you classes in the ConfigureServices method:
services.AddTransient<IEmailService, EmailService>();
Then in your Configure method, you register your customer global exception handler. You will want this to be the first thing you do in the Configure method so you catch any exceptions following it in other middleware.
app.UseMiddleware<MyGlobalExceptionHandler>();
And any services you registered will be available for your middleware constructor which might look something like this:
public sealed class MyGlobalExceptionHandler
{
private readonly RequestDelegate _next;
private readonly IEmailService _emailService;
public NlogExceptionHandler(
RequestDelegate next,
IEmailService emailService)
{
_next = next;
_emailService = emailService;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
try
{
_emailService.SendEmail(ex.ToString());
}
catch (Exception ex2)
{
//Its good practice to have a second catch block for simple logging in case the email fails too
}
throw;
}
}
}
I have been experimenting with Unity and a customer Filter / FilterProvider. My concern is that the classes are never disposed. Here is a code example i started with:
//FilterProvider
public class CustomFilterProvider: IFilterProvider
{
public IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
if (actionDescriptor.GetCustomAttributes<CustomAuthorizeAttribute>().Any())
{
var filter = UnityinstanceLocator.GetConfiguredContainer().Resolve<CustomAuthorize>();
yield return new FilterInfo(filter, FilterScope.Global);
}
}
}
//Filter
public class CustomAuthorizeFilter: IAuthorizationFilter
{
private readonly IFakeService _fakeService;
public CustomAuthorizeFilter(IFakeService fakeService)
{
_fakeService = fakeService;
}
public bool AllowMultiple { get; }
public Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken,
Func<Task<HttpResponseMessage>> continuation)
{
...Do Some stuff
}
}
//Attribute
public class CustomAuthorizeAttribute : Attribute
{
}
My IFakeService implements IDisposable. I set this up as a test. My unity registration for the IFakeService makes use of the HierarchicalLifetimeManager. I never see it being disposed when it is inside a filter. Injecting the IFakeService into the controller works as expected.
The startup for the filter provider looks like this (I am using OWIN):
var config = new HttpConfiguration {DependencyResolver = new UnityDependencyResolver(UnityinstanceLocator.GetConfiguredContainer())};
config.Services.Add(typeof(IFilterProvider), new ComceptFilterProvider());
I suppose I could go old school and wrap my disposable class in a using statement inside the ExecuteAuthorizationFilterAsync method and avoid Dependency Injection all together. Is there a better solution to this if I were to stay with Unity?
In WebApi framework filters are cached. So they are singletons and reused across requests. Instance of your CustomAuthorizeFilter never be disposed during lifetime of application and keeps reference to IFakeService.
Since the Microsoft Bot Framework is using Autofac as a dependency, I figured I'd use it in the rest of my project (using the Bot Framework project scaffold). I'm trying to load the correct Bot Framework IDialog using DI. My Global.asax.cs looks like this:
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
var builder = new ContainerBuilder();
// Get your HttpConfiguration.
var config = GlobalConfiguration.Configuration;
// Register your Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// OPTIONAL: Register the Autofac filter provider.
builder.RegisterWebApiFilterProvider(config);
builder.RegisterType<EchoDialogState>().Named<IDialog<object>>(ActivityTypes.Message);
builder.RegisterType<WelcomeDialog1>().Named<IDialog<object>>(ActivityTypes.ConversationUpdate);
builder.RegisterType<UnknownDialog>().Named<IDialog<object>>(string.Empty).PreserveExistingDefaults();
// Set the dependency resolver to be Autofac.
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
The ActivityTypes are string constants that equate to message, conversationUpdate, etc. For my controllers, I have a base that looks like this to resolve the Autofac DI Container:
public class BaseApiController : ApiController
{
public IContainer Container { get; private set; } = ((IContainer)((AutofacWebApiDependencyResolver)GlobalConfiguration.Configuration.DependencyResolver).Container);
}
In my MessagesController that catches all bot interactions, my code looks like this:
[BotAuthentication]
public class MessagesController : BaseApiController
{
public virtual async Task<HttpResponseMessage> Post([FromBody] Activity activity)
{
using (var scope = Container.BeginLifetimeScope())
{
var dialog = scope.ResolveNamed<IDialog<object>>(activity.GetActivityType());
await Conversation.SendAsync(activity, () => dialog);
}
return new HttpResponseMessage(System.Net.HttpStatusCode.Accepted);
}
}
The activity.GetActivityType() simply returns back a string with equates with the ActivityTypes referred to above. When I breakpoint on scope.ResolveNamed, it looks like the correct IDialog has been returned to dialog. However, when the Conversation.SendAsync runs, the wrong IDialog is running. For example, I see EchoDialogState being injected into dialog, but then the code inside WelcomeDialog1 is always being called instead.
Am I doing this wrong? What would cause the incorrect IDialog being run inside the delegate function?
If it helps, this is an example of the IDialog that's running:
[Serializable]
public class WelcomeDialog1 : IDialog<object>
{
public async Task StartAsync(IDialogContext context)
{
context.Wait(MessageReceivedAsync);
}
public async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
var message = await argument;
var name = message.From.Name;
await context.PostAsync($"Hi {name}. Welcome to SMEBot! First time here stuff.");
context.Wait(MessageReceivedAsync);
}
}
Instead of doing a context.Wait in the MessageReceivedAsync method of your WelcomeDialog1, try doing a context.Done.
In the way you are doing it now, the WelcomeDialog1 is still listening to your messages. Usually the welcome message is done using the ConnectorClient in the MessageController as it is a simple message. You don't need all the dialog infrastructure.