コード例 #1
0
ファイル: Comparers.cs プロジェクト: probertdaniel/aimbiztalk
        /// <summary>
        /// Sorts messaging objects by their name.
        /// </summary>
        /// <param name="x">The first item to be compared.</param>
        /// <param name="y">The second item to be compared.</param>
        /// <returns>An integer indicating the comparison between x and y.</returns>
        public static int SortTargetMessagingObjectByName(MessagingObject x, MessagingObject y)
        {
            _ = x ?? throw new ArgumentNullException(nameof(x));
            _ = y ?? throw new ArgumentNullException(nameof(y));

            return(string.Compare(x.Name, y.Name, true, CultureInfo.CurrentCulture));
        }
コード例 #2
0
        /// <summary>
        /// Generates the files associated with a list of resource templates.
        /// </summary>
        /// <param name="messagingObject">The messaging object associated with the list of resource templates.</param>
        /// <param name="templatePaths">The list of source template paths.</param>
        /// <param name="conversionPathRoot">The root path for all converted files.</param>
        /// <returns></returns>
        private async Task<int> GenerateFilesAsync(MessagingObject messagingObject, IEnumerable<DirectoryInfo> templatePaths, DirectoryInfo conversionPathRoot)
        {
            var generatedFiles = 0;

            if (messagingObject.Resources.Any())
            {
                foreach (var resourceTemplate in messagingObject.Resources)
                {
                    foreach (var templateFile in resourceTemplate.ResourceTemplateFiles)
                    {
                        var foundTemplate = await GenerateFileAsync(messagingObject, resourceTemplate, templatePaths, templateFile, resourceTemplate.OutputPath, conversionPathRoot).ConfigureAwait(false);
                        if (!foundTemplate)
                        {
                            _logger.LogWarning(WarningMessages.TemplateFileNotFound, templateFile);
                        }
                        else
                        {
                            generatedFiles++;
                        }
                    }
                }
            }

            return generatedFiles;
        }
コード例 #3
0
 /// <summary>
 /// Creates a scenario stage from the messaging object,
 /// </summary>
 /// <param name="mo">The messaging object.</param>
 /// <returns>A new scenario stage.</returns>
 private static TargetScenarioStage CreateScenarioStage(this MessagingObject mo)
 {
     return(new TargetScenarioStage
     {
         Name = mo.Name,
         StageType = mo.GetType().Name,
         MessagingObject = mo
     });
 }
コード例 #4
0
        /// <summary>
        /// Initializes a scenario from a messaging object.
        /// </summary>
        /// <param name="mo">The messaging object.</param>
        /// <returns>A new scenario.</returns>
        private static TargetScenario CreateScenario(this MessagingObject mo)
        {
            var scenario = new TargetScenario
            {
                Name      = mo.Properties[ModelConstants.ScenarioName].ToString(),
                Activator = mo.CreateScenarioStage()
            };

            return(scenario);
        }
コード例 #5
0
        /// <summary>
        /// Generates a template file by loading, rendering and saving the file to the conversion path
        /// if it is a .liquid file, otherwise just copy the file.
        /// </summary>
        /// <param name="messagingObject">The messaging object associated with the list of resource templates.</param>
        /// <param name="resourceTemplate">The resource template for this render.</param>
        /// <param name="templatePaths">The list of source template paths.</param>
        /// <param name="templateFile">The template file.</param>
        /// <param name="templateOutputPath">The output path for template files.</param>
        /// <param name="conversionPathRoot">The root path for all converted files.</param>
        /// <returns></returns>
        private async Task<bool> GenerateFileAsync(MessagingObject messagingObject, TargetResourceTemplate resourceTemplate, IEnumerable<DirectoryInfo> templatePaths, string templateFile, string templateOutputPath, DirectoryInfo conversionPathRoot)
        {
            var foundTemplate = false;

            foreach (var templatePath in templatePaths)
            {
                var templateFilePath = new FileInfo(Path.Combine(templatePath.FullName, templateFile));
                if (_fileRepository.DoesFileExist(templateFilePath.FullName))
                {
                    // Check extension
                    if (templateFilePath.Extension.ToUpperInvariant() == ".liquid".ToUpperInvariant())
                    {
                        _logger.LogTrace(TraceMessages.LoadingTemplate, templateFilePath.FullName);

                        // Load template
                        var templateContent = await _repository.LoadTemplateAsync(templateFilePath.FullName).ConfigureAwait(false);

                        _logger.LogDebug(TraceMessages.RenderingTemplate, templateFilePath.FullName);

                        // Render template
                        var renderedContent = await _renderer.RenderTemplateAsync(templateContent, Model, messagingObject, resourceTemplate).ConfigureAwait(false);

                        // Set output file path
                        var outputFilePath = new FileInfo(Path.Combine(conversionPathRoot.FullName, templateOutputPath, Path.GetFileNameWithoutExtension(templateFilePath.Name)));

                        _logger.LogTrace(TraceMessages.SavingTemplate, outputFilePath.FullName);

                        // Save rendered template
                        await _repository.SaveTemplateAsync(outputFilePath.FullName, renderedContent).ConfigureAwait(false);
                    }
                    else
                    {
                        // Set output file path
                        var outputFilePath = new FileInfo(Path.Combine(conversionPathRoot.FullName, templateOutputPath, templateFilePath.Name));

                        _logger.LogDebug(TraceMessages.CopyingTemplate, templateFilePath.FullName, outputFilePath.FullName);

                        // Create output path if some directories don't exist
                        if (!_fileRepository.DoesDirectoryExist(outputFilePath.FullName))
                        {
                            _fileRepository.CreateDirectory(outputFilePath.DirectoryName);
                        }

                        // Just a normal file, copy it to output path
                        _fileRepository.CopyFile(templateFilePath.FullName, outputFilePath.FullName);
                    }

                    foundTemplate = true;
                }
            }

            return foundTemplate;
        }
コード例 #6
0
 /// <summary>
 /// Renders the properties of the messaging object.
 /// </summary>
 /// <param name="containerNode">The HTML container to render into.</param>
 /// <param name="messagingObject">The messaging object.</param>
 private static void RenderMessagingObjectProperties(HtmlNode containerNode, MessagingObject messagingObject)
 {
     containerNode.AppendChild(CreateNodeWithSnippetContent(string.Format(CultureInfo.CurrentCulture, HtmlResources.AnalysisSnippetHeading, HtmlResources.AnalysisHeadingProperties)));
     if (messagingObject.Properties == null || messagingObject.Properties.Count == 0)
     {
         // Add a placeholder if there are no relationships.
         containerNode.AppendChild(
             CreateNodeWithSnippetContent(
                 string.Format(
                     CultureInfo.CurrentCulture,
                     HtmlResources.AnalysisSnippetInformationMessage,
                     HtmlResources.AnalysisMessageNoProperties)));
     }
     else
     {
         RenderMessagingObjectPropertyDictionary(containerNode, messagingObject.Properties, string.Empty);
     }
 }
コード例 #7
0
 /// <summary>
 /// Writes the messages associated with the item.
 /// </summary>
 /// <param name="containerNode">The HTML container to render into.</param>
 /// <param name="messagingObject">The messaging object.</param>
 private static void RenderMessagingObjectMessages(HtmlNode containerNode, MessagingObject messagingObject)
 {
     containerNode.AppendChild(CreateNodeWithSnippetContent(string.Format(CultureInfo.CurrentCulture, HtmlResources.AnalysisSnippetHeading, HtmlResources.AnalysisHeadingMessages)));
     if (messagingObject.ReportMessages == null || messagingObject.ReportMessages.Count == 0)
     {
         // Add a placeholder if there are no report messages.
         containerNode.AppendChild(CreateNodeWithSnippetContent(string.Format(CultureInfo.CurrentCulture, HtmlResources.AnalysisSnippetInformationMessage, HtmlResources.AnalysisMessageNoMessages)));
     }
     else
     {
         foreach (var item in messagingObject.ReportMessages)
         {
             if (item.Severity == MessageSeverity.Error)
             {
                 containerNode.AppendChild(
                     CreateNodeWithSnippetContent(
                         string.Format(
                             CultureInfo.CurrentCulture,
                             HtmlResources.AnalysisSnippetErrorMessage,
                             item.Message)));
             }
             else if (item.Severity == MessageSeverity.Warning)
             {
                 containerNode.AppendChild(
                     CreateNodeWithSnippetContent(
                         string.Format(
                             CultureInfo.CurrentCulture,
                             HtmlResources.AnalysisSnippetWarningMessage,
                             item.Message)));
             }
             else
             {
                 containerNode.AppendChild(
                     CreateNodeWithSnippetContent(
                         string.Format(
                             CultureInfo.CurrentCulture,
                             HtmlResources.AnalysisSnippetInformationMessage,
                             item.Message)));
             }
         }
     }
 }
コード例 #8
0
        public void SortTargetMessagingObjectByNameXYEqual(MessagingObject x, MessagingObject y, int result)
        {
            "Given a resource x"
            .x(() => x = new DocumentMessage()
            {
                Name = "z"
            });

            "And a resource relationship to compare to"
            .x(() => y = new DocumentMessage()
            {
                Name = "z"
            });

            "When comparing x and y"
            .x(() => result = Comparers.SortTargetMessagingObjectByName(x, y));

            "Expect x to be less than y"
            .x(() => {
                result.Should().Be(0);
            });
        }
コード例 #9
0
 /// <summary>
 /// Writes the links associated with the item.
 /// </summary>
 /// <param name="containerNode">The HTML container to render into.</param>
 /// <param name="messagingObject">The messaging object.</param>
 private static void RenderMessagingObjectLinks(HtmlNode containerNode, MessagingObject messagingObject)
 {
     containerNode.AppendChild(CreateNodeWithSnippetContent(string.Format(CultureInfo.CurrentCulture, HtmlResources.AnalysisSnippetHeading, HtmlResources.AnalysisHeadingLinks)));
     if (messagingObject.ReportLinks == null || messagingObject.ReportLinks.Count == 0)
     {
         // Add a placeholder if there are no relationships.
         containerNode.AppendChild(CreateNodeWithSnippetContent(string.Format(CultureInfo.CurrentCulture, HtmlResources.AnalysisSnippetInformationMessage, HtmlResources.AnalysisMessageNoReferenceLinks)));
     }
     else
     {
         foreach (var link in messagingObject.ReportLinks)
         {
             containerNode.AppendChild(
                 CreateNodeWithSnippetContent(
                     string.Format(
                         CultureInfo.CurrentCulture,
                         HtmlResources.AnalysisSnippetTargetReportLink,
                         link,
                         link)));
         }
     }
 }
コード例 #10
0
 /// <summary>
 /// Writes the resources associated with the item.
 /// </summary>
 /// <param name="containerNode">The HTML container to render into.</param>
 /// <param name="messagingObject">The messaging object.</param>
 private static void RenderMessagingObjectResources(HtmlNode containerNode, MessagingObject messagingObject)
 {
     containerNode.AppendChild(CreateNodeWithSnippetContent(string.Format(CultureInfo.CurrentCulture, HtmlResources.AnalysisSnippetHeading, HtmlResources.AnalysisHeadingResources)));
     if (messagingObject.Resources == null || messagingObject.Resources.Count == 0)
     {
         // Add a placeholder if there are no relationships.
         containerNode.AppendChild(CreateNodeWithSnippetContent(string.Format(CultureInfo.CurrentCulture, HtmlResources.AnalysisSnippetInformationMessage, HtmlResources.AnalysisMessageNoResources)));
     }
     else
     {
         foreach (var resource in messagingObject.Resources)
         {
             containerNode.AppendChild(
                 CreateNodeWithSnippetContent(
                     string.Format(
                         CultureInfo.CurrentCulture,
                         HtmlResources.AnalysisSnippetTargetResource,
                         ResourceFormatter.GetTargetResourceIconFromType(resource.ResourceType),
                         ResourceFormatter.GetTargetResourceFriendlyName(resource.ResourceType),
                         resource.ResourceName)));
         }
     }
 }
コード例 #11
0
        public void RenderTemplateAsyncWithMissingMessagingObjectWithWarning(ITemplateRenderer renderer, AzureIntegrationServicesModel model, MessagingObject messagingObject, string templateContent, string renderedContent, Exception e)
        {
            "Given a template renderer"
            .x(() => renderer = new LiquidTemplateRenderer(_mockLogger.Object));

            "And a model"
            .x(() => model = _model);

            "And a missing messaging object"
            .x(() => messagingObject = new TopicChannel("MissingChannel")
            {
                Key = "MessageBus:MissingApp:MissingChannel"
            });

            "And a template content"
            .x(() => templateContent = _templateChannelContent);

            "When rendering the template"
            .x(async() => e = await Record.ExceptionAsync(async() => renderedContent = await renderer.RenderTemplateAsync(templateContent, model, messagingObject)));

            "Then the render should succeed"
            .x(() => e.Should().BeNull());

            "And the rendered content should not have expected values from the model"
            .x(() =>
            {
                renderedContent.Should().NotBeNull().And.Be("").And.NotContainAny("{{").And.NotContainAny("}}");

                // Verify warning was raised
                _mockLogger.Verify(l => l.Log(
                                       It.Is <LogLevel>(l => l == LogLevel.Warning),
                                       It.IsAny <EventId>(),
                                       It.Is <It.IsAnyType>((v, t) => v.ToString().Contains("does not appear in the target model", StringComparison.CurrentCultureIgnoreCase)),
                                       It.IsAny <Exception>(),
                                       It.Is <Func <It.IsAnyType, Exception, string> >((v, t) => true)), Times.Once);
            });
        }
コード例 #12
0
        public void RenderTemplateAsyncWithResourceTemplateWithSuccess(ITemplateRenderer renderer, AzureIntegrationServicesModel model, MessagingObject messagingObject, TargetResourceTemplate resourceTemplate, string templateContent, string renderedContent, Exception e)
        {
            "Given a template renderer"
            .x(() => renderer = new LiquidTemplateRenderer(_mockLogger.Object));

            "And a model"
            .x(() => model = _model);

            "And a messaging object"
            .x(() => messagingObject = model.FindMessagingObject("ContosoMessageBus:System:FtpReceive").messagingObject);

            "And a resource template object"
            .x(() => resourceTemplate = new TargetResourceTemplate()
            {
                ResourceName = "endpointFtpReceiveLogicAppConsumption"
            });

            "And a template content"
            .x(() => templateContent = _templateResourceTemplateContent);

            "When rendering the template"
            .x(async() => e = await Record.ExceptionAsync(async() => renderedContent = await renderer.RenderTemplateAsync(templateContent, model, null, resourceTemplate)));

            "Then the render should succeed"
            .x(() => e.Should().BeNull());

            "And the rendered content should have expected values from the model"
            .x(() =>
            {
                renderedContent.Should().NotBeNull().And.ContainAny("endpointFtpReceiveLogicAppConsumption").And.NotContainAny("{{").And.NotContainAny("}}");
            });
        }
コード例 #13
0
        public void RenderTemplateAsyncWithIntermediaryWithSuccess(ITemplateRenderer renderer, AzureIntegrationServicesModel model, MessagingObject messagingObject, string templateContent, string renderedContent, Exception e)
        {
            "Given a template renderer"
            .x(() => renderer = new LiquidTemplateRenderer(_mockLogger.Object));

            "And a model"
            .x(() => model = _model);

            "And a messaging object"
            .x(() => messagingObject = model.FindMessagingObject("ContosoMessageBus:System:MessageAgent").messagingObject);

            "And a template content"
            .x(() => templateContent = _templateIntermediaryContent);

            "When rendering the template"
            .x(async() => e = await Record.ExceptionAsync(async() => renderedContent = await renderer.RenderTemplateAsync(templateContent, model, messagingObject)));

            "Then the render should succeed"
            .x(() => e.Should().BeNull());

            "And the rendered content should have expected values from the model"
            .x(() =>
            {
                renderedContent.Should().NotBeNull().And.ContainAny("MessageAgent").And.NotContainAny("{{").And.NotContainAny("}}");
            });
        }
コード例 #14
0
        /// <summary>
        /// Populates the target resources from configuration for the specified messaging object.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="config">The YAML configuration set.</param>
        /// <param name="messagingObject">The messaging object.</param>
        private void PopulateTargetResources(AzureIntegrationServicesModel model, IEnumerable <YamlStream> config, MessagingObject messagingObject)
        {
            if (messagingObject.ResourceMapKey != null)
            {
                _logger.LogDebug(TraceMessages.LoadingTargetResources, messagingObject.Key);

                // Find resource map
                var resourceKeyList = FindResourcesForMap(config, messagingObject.ResourceMapKey);
                if (resourceKeyList != null)
                {
                    foreach (var resourceKeyNode in resourceKeyList)
                    {
                        var resourceKey = (YamlScalarNode)resourceKeyNode;

                        _logger.LogTrace(TraceMessages.LookingForTemplatesForResource, resourceKey.Value);

                        // Find targets for resource
                        var targetsList = FindTargetsForResource(config, resourceKey.Value);
                        if (targetsList != null)
                        {
                            _logger.LogDebug(TraceMessages.FilteringResourcesByTarget, model.MigrationTarget.TargetEnvironment);

                            foreach (var targetNode in targetsList)
                            {
                                var target = (YamlMappingNode)targetNode;

                                // Get target name
                                var targetNameNode = (YamlSequenceNode)target.Children["target"];
                                var targetNames    = targetNameNode.Select(t => ((YamlScalarNode)t).Value.ToUpperInvariant());
                                if (targetNames.Contains(model.MigrationTarget.TargetEnvironment.ToString("G").ToUpperInvariant()))
                                {
                                    if (target.Children.ContainsKey("templates"))
                                    {
                                        _logger.LogTrace(TraceMessages.FoundTemplatesForTarget, model.MigrationTarget.TargetEnvironment, resourceKey.Value);

                                        // Get templates
                                        var templateKeyList = target.Children["templates"] as YamlSequenceNode;

                                        // Check if we have any templates
                                        if (templateKeyList != null)
                                        {
                                            foreach (var templateKeyNode in templateKeyList)
                                            {
                                                var templateKey = (YamlScalarNode)templateKeyNode;

                                                var templateNode = FindTemplate(config, templateKey.Value);
                                                if (templateNode != null)
                                                {
                                                    // Create target resource
                                                    var targetResourceTemplate = CreateTargetResourceTemplate(model, templateKey, templateNode);
                                                    messagingObject.Resources.Add(targetResourceTemplate);
                                                }
                                            }
                                        }
                                    }
                                    else
                                    {
                                        _logger.LogTrace(TraceMessages.NoTemplatesForTarget, model.MigrationTarget.TargetEnvironment, resourceKey.Value);
                                    }

                                    if (target.Children.ContainsKey("snippets"))
                                    {
                                        _logger.LogTrace(TraceMessages.FoundSnippetsForTarget, model.MigrationTarget.TargetEnvironment, resourceKey.Value);

                                        // Get snippets
                                        var snippetKeyList = (YamlSequenceNode)target.Children["snippets"];

                                        foreach (var snippetKeyNode in snippetKeyList)
                                        {
                                            var snippetKey = (YamlScalarNode)snippetKeyNode;

                                            var snippetNode = FindSnippet(config, snippetKey.Value);
                                            if (snippetNode != null)
                                            {
                                                // Create target resource
                                                var targetResourceSnippet = CreateTargetResourceSnippet(model, snippetKey, snippetNode);
                                                messagingObject.Snippets.Add(targetResourceSnippet);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        _logger.LogTrace(TraceMessages.NoSnippetsForTarget, model.MigrationTarget.TargetEnvironment, resourceKey.Value);
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    _logger.LogWarning(WarningMessages.ResourceMapMissingInConfiguration, messagingObject.ResourceMapKey, messagingObject.Name);
                }
            }
            else
            {
                _logger.LogDebug(TraceMessages.ResourceMapKeyNotSpecified, messagingObject.Name, messagingObject.Type);
            }
        }
コード例 #15
0
        /// <summary>
        /// Renders a template using a Liquid template engine.
        /// </summary>
        /// <param name="templateContent">The template content to render.</param>
        /// <param name="model">The model used to provide properties to Liquid templates.</param>
        /// <param name="messagingObject">An optional messaging object to add to the variable context, accessible to templates.</param>
        /// <param name="resourceTemplate">An optional resource template object to add to the variable context, accessible to templates.</param>
        /// <returns>The rendered template content.</returns>
        public async Task <string> RenderTemplateAsync(string templateContent, AzureIntegrationServicesModel model, MessagingObject messagingObject = null, TargetResourceTemplate resourceTemplate = null)
        {
            _ = model ?? throw new ArgumentNullException(nameof(model));
            _ = templateContent ?? throw new ArgumentNullException(nameof(templateContent));

            // Create variables on script object, to be accessible to Liquid templates
            var scriptObject = new ScriptObject
            {
                ["model"] = model
            };

            // Is there a messaging object?
            if (messagingObject != null)
            {
                var messagingObjects = model.FindMessagingObject(messagingObject.Key);
                if (messagingObjects.messageBus != null)
                {
                    scriptObject["message_bus"] = messagingObjects.messageBus;

                    if (messagingObjects.application != null)
                    {
                        scriptObject["application"] = messagingObjects.application;
                    }

                    if (messagingObjects.messagingObject != null)
                    {
                        scriptObject["messaging_object"] = messagingObjects.messagingObject;

                        switch (messagingObjects.messagingObject.Type)
                        {
                        case MessagingObjectType.Message:
                            scriptObject["message"] = (Message)messagingObjects.messagingObject;
                            break;

                        case MessagingObjectType.Channel:
                            scriptObject["channel"] = (Channel)messagingObjects.messagingObject;
                            break;

                        case MessagingObjectType.Intermediary:
                            scriptObject["intermediary"] = (Intermediary)messagingObjects.messagingObject;
                            break;

                        case MessagingObjectType.Endpoint:
                            scriptObject["endpoint"] = (Endpoint)messagingObjects.messagingObject;
                            break;
                        }
                    }
                }
                else
                {
                    // Should never happen, unless the messaging object is not attached to the target model
                    _logger.LogWarning(WarningMessages.MessagingObjectMissingInModel, messagingObject.Key);
                }
            }

            // Is there a resource template?
            if (resourceTemplate != null)
            {
                scriptObject["resource_template"] = resourceTemplate;
            }

            // Push variables onto the context
            _context.PushGlobal(scriptObject);

            try
            {
                // Render template
                var template        = Template.ParseLiquid(templateContent);
                var renderedContent = await template.RenderAsync(_context).ConfigureAwait(false);

                return(renderedContent);
            }
            finally
            {
                // Pop model from context stack
                _context.PopGlobal();
            }
        }
コード例 #16
0
        /// <summary>
        /// Analyzes the response path of a two way send port to build the route back to the topic channel.
        /// </summary>
        /// <param name="intermediaryKeyPrefix">The prefix for the intermediary key.</param>
        /// <param name="sourceApplication">The application object in the source model.</param>
        /// <param name="targetApplication">The application object in the target model.</param>
        /// <param name="sendPortSource">The send port source.</param>
        /// <param name="sendPort">The send port resource item.</param>
        /// <param name="endpointAdapter">The endpoint adapter which triggers the response.</param>
        private void AnalyzeSendPortResponse(string intermediaryKeyPrefix, ResourceItem sourceApplication, Application targetApplication, SendPort sendPortSource, ResourceItem sendPort, MessagingObject endpointAdapter)
        {
            _logger.LogDebug(TraceMessages.SendPortIsTwoWay, RuleName, sendPort.Name);

            // Format the keys.
            var applicationName = targetApplication.Name.FormatKey();
            var sendPortName    = sendPort.Name.FormatKey();

            // Set the scenario name on the endpoint adapter.
            endpointAdapter.Properties.Add(ModelConstants.ScenarioName, $"{applicationName}.{sendPortName}.Response");

            var route = new List <MessagingObject>
            {
                endpointAdapter
            };

            // Create the intermediaries for the pipeline
            route.AddRange(CreateReceivePipelineIntermediaries(intermediaryKeyPrefix, sourceApplication, sendPortSource.ReceivePipeline, sendPortSource.ReceivePipelineCustomConfiguration));

            // If there is a map, create the intermediary
            if (sendPortSource.InboundTransforms != null && sendPortSource.InboundTransforms.Any())
            {
                // Find map resource items
                var transforms = sendPort.FindRelatedResourcesByType(Model, ResourceRelationshipType.ReferencesTo, ModelConstants.ResourceMap);

                // Add to route
                var intermediary = CreateMapIntermediary(intermediaryKeyPrefix, targetApplication, transforms);
                if (intermediary != null)
                {
                    route.Add(intermediary);
                }
            }
            else
            {
                _logger.LogTrace(TraceMessages.NoReceiveMapSpecifiedOnSendPort, RuleName, sendPortSource.Name);
            }

            // Create the message agent intermediaries
            route.AddRange(CreateMessageAgentIntermediaries(intermediaryKeyPrefix, _messageBoxChannelKey, false, null));

            // Binds the route by adding routing slip router intermediaries between the intermediaries in the response from the send port
            var boundRoute = BindResponseRoute(intermediaryKeyPrefix, targetApplication, sendPortSource, route);

            // Binds the channels between the endpoint and intermediaries up to the message box (topic channel)
            BindResponseChannels(intermediaryKeyPrefix, targetApplication, sendPortSource, boundRoute);
        }