title: How to forward activities / messages to other dialogs in Microsoft bot framework v4
body: <p>I am using below code :</p>
  
  <pre><code>// Copyright (c) Microsoft Corporation. All rights reserved.
  // Licensed under the MIT License.
  
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Threading;
  using System.Threading.Tasks;
  using Microsoft.Bot.Builder;
  using Microsoft.Bot.Builder.Dialogs;
  using Microsoft.Bot.Schema;
  using Microsoft.Extensions.Logging;
  using Microsoft.Recognizers.Text.DataTypes.TimexExpression;
  
  namespace Microsoft.BotBuilderSamples.Dialogs
  {
      public class MainDialog : ComponentDialog
      {
          private readonly IntentsRecognizer _luisRecognizer;
          protected readonly ILogger Logger;
  
          public string CompaniesSelected { get; private set; }
  
          // Dependency injection uses this constructor to instantiate MainDialog
          public MainDialog(IntentsRecognizer luisRecognizer, BookingDialog bookingDialog, ILogger&lt;MainDialog&gt; logger)
              : base(nameof(MainDialog))
          {
              _luisRecognizer = luisRecognizer;
              Logger = logger;
  
              AddDialog(new TextPrompt(nameof(TextPrompt)));
              AddDialog(bookingDialog);
              AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
              {
                  IntroStepAsync,
                  ActStepAsync,
                  FinalStepAsync,
              }));
  
              // The initial child Dialog to run.
              InitialDialogId = nameof(WaterfallDialog);
          }
  
          private async Task&lt;DialogTurnResult&gt; IntroStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
          {
              if (!_luisRecognizer.IsConfigured)
              {
                  await stepContext.Context.SendActivityAsync(
                      MessageFactory.Text("NOTE: LUIS is not configured. To enable all capabilities, add 'LuisAppId', 'LuisAPIKey' and 'LuisAPIHostName' to the appsettings.json file.", inputHint: InputHints.IgnoringInput), cancellationToken);
  
                  return await stepContext.NextAsync(null, cancellationToken);
              }
  
              // Use the text provided in FinalStepAsync or the default if it is the first time.
              var messageText = stepContext.Options?.ToString() ?? "What can I help you with today?\nSay something like \"Book a flight from Paris to Berlin on March 22, 2020\"";
              var promptMessage = MessageFactory.Text(messageText, messageText, InputHints.ExpectingInput);
              return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = promptMessage }, cancellationToken);
          }
  
          private async Task&lt;DialogTurnResult&gt; ActStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
          {
              if (!_luisRecognizer.IsConfigured)
              {
                  // LUIS is not configured, we just run the BookingDialog path with an empty BookingDetailsInstance.
                  return await stepContext.BeginDialogAsync(nameof(BookingDialog), new BookingDetails(), cancellationToken);
              }
  
              // Call LUIS and gather any potential booking details. (Note the TurnContext has the response to the prompt.)
              var luisResult = await _luisRecognizer.RecognizeAsync&lt;IntentOperations&gt;(stepContext.Context, cancellationToken);
              Console.WriteLine(luisResult.Intents);
              var list = stepContext.Values[CompaniesSelected] as List&lt;string&gt;;
  
              switch (luisResult.TopIntent().intent)
              {
                  case IntentOperations.Intent.BookTicket:
  
                                  await stepContext.ReplaceDialogAsync(className...with bot message);
  
                      // Initialize BookingDetails with any entities we may have found in the response.
                      var bookingDetails = new BookingDetails()
                      {
                          // Get destination and origin from the composite entities arrays.
                          Destination = luisResult.ToEntities.Airport,
                          Origin = luisResult.FromEntities.Airport,
                          TravelDate = luisResult.TravelDate,
                      };
  
                      // Run the BookingDialog giving it whatever details we have from the LUIS call, it will fill out the remainder.
                      return await stepContext.BeginDialogAsync(nameof(BookingDialog), bookingDetails, cancellationToken);
  
                  case IntentOperations.Intent.GetWeather:
                      // We haven't implemented the GetWeatherDialog so we just display a TODO message.
                      var getWeatherMessageText = "TODO: get weather flow here";
                      var getWeatherMessage = MessageFactory.Text(getWeatherMessageText, getWeatherMessageText, InputHints.IgnoringInput);
                      await stepContext.Context.SendActivityAsync(getWeatherMessage, cancellationToken);
                      break;
  
                  default:
                      // Catch all for unhandled intents
                      var didntUnderstandMessageText = $"Sorry, I didn't get that. Please try asking in a different way (intent was {luisResult.TopIntent().intent})";
                      var didntUnderstandMessage = MessageFactory.Text(didntUnderstandMessageText, didntUnderstandMessageText, InputHints.IgnoringInput);
                      await stepContext.Context.SendActivityAsync(didntUnderstandMessage, cancellationToken);
                      break;
              }
  
              return await stepContext.NextAsync(null, cancellationToken);
          }
  
          // Shows a warning if the requested From or To cities are recognized as entities but they are not in the Airport entity list.
          // In some cases LUIS will recognize the From and To composite entities as a valid cities but the From and To Airport values
          // will be empty if those entity values can't be mapped to a canonical item in the Airport.
          private static async Task ShowWarningForUnsupportedCities(ITurnContext context, IntentOperations luisResult, CancellationToken cancellationToken)
          {
              var unsupportedCities = new List&lt;string&gt;();
  
              var fromEntities = luisResult.FromEntities;
              if (!string.IsNullOrEmpty(fromEntities.From) &amp;&amp; string.IsNullOrEmpty(fromEntities.Airport))
              {
                  unsupportedCities.Add(fromEntities.From);
              }
  
              var toEntities = luisResult.ToEntities;
              if (!string.IsNullOrEmpty(toEntities.To) &amp;&amp; string.IsNullOrEmpty(toEntities.Airport))
              {
                  unsupportedCities.Add(toEntities.To);
              }
  
              if (unsupportedCities.Any())
              {
                  var messageText = $"Sorry but the following airports are not supported: {string.Join(',', unsupportedCities)}";
                  var message = MessageFactory.Text(messageText, messageText, InputHints.IgnoringInput);
                  await context.SendActivityAsync(message, cancellationToken);
              }
          }
  
          private async Task&lt;DialogTurnResult&gt; FinalStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
          {
              // If the child dialog ("BookingDialog") was cancelled, the user failed to confirm or if the intent wasn't BookFlight
              // the Result here will be null.
              if (stepContext.Result is BookingDetails result)
              {
                  // Now we have all the booking details call the booking service.
  
                  // If the call to the booking service was successful tell the user.
  
                  var timeProperty = new TimexProperty(result.TravelDate);
                  var travelDateMsg = timeProperty.ToNaturalLanguage(DateTime.Now);
                  var messageText = $"I have you booked to {result.Destination} from {result.Origin} on {travelDateMsg}";
                  var message = MessageFactory.Text(messageText, messageText, InputHints.IgnoringInput);
                  await stepContext.Context.SendActivityAsync(message, cancellationToken);
              }
  
              // Restart the main dialog with a different message the second time around
              var promptMessage = "What else can I do for you?";
              return await stepContext.ReplaceDialogAsync(InitialDialogId, promptMessage, cancellationToken);
          }
      }
  }
  </code></pre>
  
  <p>Just after this line :</p>
  
  <pre><code> case IntentOperations.Intent.BookTicket:
  </code></pre>
  
  <p>I want it to redirect from here with Luis Intent i.e BookTicket and Bot user message it to another class . In the documentation <a href="https://docs.microsoft.com/en-us/azure/bot-service/migration/migration-overview?view=azure-bot-service-4.0&amp;tabs=csharp" rel="nofollow noreferrer">Bot migration 3 to v4</a>.
  It is mentioned that <code>await ITurnContext.ReplaceDialogAsync</code> should be used instead of older <code>IDialogContext.Forward</code>.</p>
  
  <p>I am trying like below </p>
  
  <pre><code>await stepContext.ReplaceDialogAsync(classToBookTickets...with bot message);
  </code></pre>
  
  <p>But, I am unable to invoke className on intent match as I am not clear about the arguments. 
  Please Help.</p>
  
  <p><a href="https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/csharp_dotnetcore/13.core-bot" rel="nofollow noreferrer">GitHub project Core-Bot</a> </p>