Exemplo n.º 1
0
        public void CreatePipeline()
        {
            var target = new Xrm.Sdk.Entity("account");

            target.Id = Guid.NewGuid();

            // Arrange
            using (var pipeline = new PluginPipeline(FakeMessageNames.Create, FakeStages.PreOperation, target))
            {
                pipeline.Depth = 10;

                pipeline.FakeService.ExpectRetrieve((entityName, id, columnSet) => {
                    var returned     = new Entity("account");
                    returned["name"] = "123";
                    return(returned);
                });

                var plugin = new AccountPlugin();
                // Act & Assert
                pipeline.Execute(plugin);
                // Assert
                Assert.AreEqual("123", target.GetAttributeValue <string>("name"));
                Assert.AreEqual(10, pipeline.PluginExecutionContext.Depth);
                pipeline.FakeService.AssertExpectedCalls();
            }
        }
Exemplo n.º 2
0
        public virtual async Task <HttpResponseMessage> Post([FromBody] Activity activity)
        {
            // check if activity is of type message
            if (activity != null && activity.GetActivityType() == ActivityTypes.Message)
            {
                await Conversation.SendAsync(activity, () => new EchoDialog());
            }

            if (activity.GetActivityType() == ActivityTypes.ConversationUpdate)
            {
                // Handle conversation state changes, like members being added and removed
                // Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
                // Not available in all channels
                IConversationUpdateActivity iConversationUpdated = activity as IConversationUpdateActivity;
                ConnectorClient             connector            = new ConnectorClient(new System.Uri(activity.ServiceUrl));
                if (iConversationUpdated != null)
                {
                    if ((string)activity.Text == "Address" || (activity.From.Name == "User" && iConversationUpdated.MembersAdded.Where(m => m.Id == iConversationUpdated.Recipient.Id).Count() > 0))
                    {
                        //Initialize the CRM connection
                        IOrganizationService service = Dynamics.GetService();

                        //Extract the direct line address (if applicable)
                        CXAddress address = JsonConvert.DeserializeObject <CXAddress>(activity.Value != null ? (string)activity.Value : "{}");
                        if (address.Address == null)
                        {
                            address.Address = "3145783471";
                            address.Message = "Initialize Conversation";
                            address.Bot     = "Default Bot";
                        }



                        //get bot
                        EntityCollection botResults = service.RetrieveMultiple(new FetchExpression(string.Format(@"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false' no-lock='true'>
                                        <entity name='aspect_cxbot'>
                                        <attribute name='aspect_cxbotid' />
                                        <attribute name='aspect_name' />
                                        <attribute name='createdon' />
                                        <order attribute='aspect_name' descending='false' />
                                        <filter type='and'>
                                            <filter type='or'>
                                            <condition attribute='aspect_name' operator='eq' value='{0}' />
                                            <condition attribute='aspect_default' operator='eq' value='1' />
                                            </filter>
                                        </filter>
                                        </entity>
                                    </fetch>", address.Bot == null ? string.Empty : address.Bot)));

                        if (botResults.Entities.Count() == 0)
                        {
                            var responseMessage = activity.CreateReply();
                            responseMessage.Text  = "There is currently no default CX bot configured in your environment or the bot speicified does not exist.";
                            responseMessage.Speak = "There is currently no default CX bot configured in your environment or the bot speicified does not exist.";
                            ResourceResponse msgResponse = connector.Conversations.ReplyToActivity(responseMessage);
                            return(new HttpResponseMessage(System.Net.HttpStatusCode.Accepted));
                        }

                        Xrm.Sdk.Entity cxBot           = botResults.Entities[0];
                        var            namedMatchedBot = (from b in botResults.Entities where (string)b["aspect_name"] == address.Address select b);
                        if (namedMatchedBot.Count() > 0)
                        {
                            cxBot = namedMatchedBot.First();
                        }



                        //get first step
                        Xrm.Sdk.Entity cxCurrentStep = service.RetrieveMultiple(new FetchExpression(string.Format(@"<fetch mapping='logical' version='1.0' distinct='false' output-format='xml-platform' no-lock='true'>
                                        <entity name='aspect_cxstep'>
                                        <all-attributes />
                                        <link-entity name='aspect_cxbot' to='aspect_cxbotid' from='aspect_cxbotid' alias='aspect_cxbot'>
                                            <all-attributes />
                                        </link-entity>
                                        <order descending='false' attribute='aspect_name' />
                                        <filter type='and'>
                                            <condition value='1' attribute='aspect_root' operator='eq' />
                                            <condition value='{0}' attribute='aspect_cxbotid' operator='eq' />
                                        </filter>
                                        </entity>
                                    </fetch>", cxBot.Id))).Entities[0];


                        //create initial conversation
                        Xrm.Sdk.Entity cxConversation = new Xrm.Sdk.Entity("aspect_cxconversation", "aspect_conversationid", activity.Conversation.Id);
                        cxConversation["aspect_name"]            = activity.Conversation.Id;
                        cxConversation["aspect_from"]            = address.Address;
                        cxConversation["aspect_lastanswer"]      = address.Message;
                        cxConversation["aspect_cxbotid"]         = new EntityReference(cxBot.LogicalName, cxBot.Id);
                        cxConversation["aspect_currentcxstepid"] = new EntityReference(cxCurrentStep.LogicalName, cxCurrentStep.Id);
                        UpsertResponse cxConversationResponse = (UpsertResponse)service.Execute(new UpsertRequest()
                        {
                            Target = cxConversation
                        });

                        if (!string.IsNullOrEmpty(address.Message))
                        {
                            //Create a conversation message with the initial
                            Xrm.Sdk.Entity conversationClient = new Xrm.Sdk.Entity("aspect_cxconversationmessage");
                            conversationClient["aspect_cxconversationid"] = new EntityReference("aspect_cxconversation", "aspect_conversationid", activity.Conversation.Id);
                            conversationClient["aspect_cxstepid"]         = new EntityReference(cxCurrentStep.LogicalName, cxCurrentStep.Id);
                            conversationClient["aspect_direction"]        = false;
                            conversationClient["aspect_name"]             = activity.Conversation.Id;
                            service.Create(conversationClient);
                        }


                        //ROUTE TO NEXT QUESTION
                        while (cxCurrentStep != null)
                        {
                            //FIRE ENTRY SEARCHES
                            Dynamics.ExecuteSearch(service, (EntityReference)cxConversationResponse.Results["Target"], new EntityReference(cxCurrentStep.LogicalName, cxCurrentStep.Id), true);

                            //FIRE ENTRY WORKFLOW
                            Dynamics.FireWorkflow(service, cxCurrentStep, false);


                            switch (Dynamics.CXGetType((OptionSetValue)cxCurrentStep["aspect_type"]))
                            {
                            case "MESSAGE":
                                var cxNextStep = await Dynamics.PromptInitialQuestion(activity
                                                                                      , connector
                                                                                      , service
                                                                                      , new Xrm.Sdk.Entity(((EntityReference)cxConversationResponse.Results["Target"]).LogicalName)
                                {
                                    Id = ((EntityReference)cxConversationResponse.Results["Target"]).Id
                                }
                                                                                      , cxCurrentStep);

                                if (cxNextStep != null)
                                {
                                    cxCurrentStep = service.RetrieveMultiple(new FetchExpression(string.Format(@"<fetch mapping='logical' version='1.0' distinct='false' output-format='xml-platform' no-lock='true'>
                                                            <entity name='aspect_cxstep'>
                                                            <all-attributes />
                                                            <link-entity name='aspect_cxbot' to='aspect_cxbotid' from='aspect_cxbotid' alias='aspect_cxbot'>
                                                                <all-attributes />
                                                            </link-entity>
                                                            <filter type='and'>
                                                                <condition value='{0}' attribute='aspect_cxstepid' operator='eq' />
                                                            </filter>
                                                            </entity>
                                                        </fetch>", cxNextStep.Id))).Entities[0];
                                }
                                break;

                            case "QUESTION":
                            case "MENU":
                            case "RECORD":
                            case "TRANSFER":
                                if (cxCurrentStep != null)
                                {
                                    await Dynamics.PromptInitialQuestion(activity
                                                                         , connector
                                                                         , service
                                                                         , new Xrm.Sdk.Entity(((EntityReference)cxConversationResponse.Results["Target"]).LogicalName)
                                    {
                                        Id = ((EntityReference)cxConversationResponse.Results["Target"]).Id
                                    }
                                                                         , cxCurrentStep);

                                    cxCurrentStep = null;
                                }
                                break;
                            }
                        }
                    }
                }

                await HandleSystemMessage(activity);
            }
            else
            {
                await HandleSystemMessage(activity);
            }

            return(new HttpResponseMessage(System.Net.HttpStatusCode.Accepted));
        }
Exemplo n.º 3
0
        public async Task MessageReceivedAsync(IDialogContext context, IAwaitable <IMessageActivity> argument)
        {
            var message = await argument;


            IOrganizationService service = Dynamics.GetService();


            //Get the current and next step
            Xrm.Sdk.Entity  cxCurrentStep = Dynamics.GetCXCurrentStepEntityByConversationId(service, message.Conversation.Id);
            EntityReference cxNextStep    = cxCurrentStep.Contains("aspect_nextcxstepid") ? (EntityReference)cxCurrentStep["aspect_nextcxstepid"] : null;


            //Create a conversation message with the users response
            Xrm.Sdk.Entity conversationClient = new Xrm.Sdk.Entity("aspect_cxconversationmessage");
            conversationClient["aspect_cxconversationid"] = new EntityReference("aspect_cxconversation", "aspect_conversationid", message.Conversation.Id);
            conversationClient["aspect_cxstepid"]         = new EntityReference(cxCurrentStep.LogicalName, cxCurrentStep.Id);
            conversationClient["aspect_direction"]        = false;
            conversationClient["aspect_name"]             = message.Id;
            conversationClient["aspect_message"]          = message.Text;
            service.Create(conversationClient);


            //TODO: Check global utterances
            Xrm.Sdk.Entity globalUtterance = service.RetrieveMultiple(new FetchExpression(string.Format(@"<fetch mapping='logical' version='1.0' distinct='false' output-format='xml-platform' no-lock='true'>
                                                      <entity name='aspect_cxglobalutterance'>
                                                        <attribute name='aspect_cxglobalutteranceid' />
                                                        <attribute name='aspect_cxstepid' />
                                                        <attribute name='aspect_answers' />
                                                        <order descending='false' attribute='aspect_name' />
                                                        <filter type='and'>
                                                          <condition value='%{0}%' attribute='aspect_answers' operator='like' />
                                                        </filter>
                                                      </entity>
                                                    </fetch>", HttpUtility.UrlEncode(message.Text)))).Entities.FirstOrDefault();


            if (globalUtterance != null)
            {
                cxNextStep = (EntityReference)globalUtterance["aspect_cxstepid"];
            }
            else
            {
                //validate user input
                string utteranceMatch = UtteranceMatch(message.Text, (string)(cxCurrentStep.Contains("aspect_answers") ? (string)cxCurrentStep["aspect_answers"] : null));
                if (Dynamics.CXGetType((OptionSetValue)cxCurrentStep["aspect_type"]) == "MENU")
                {
                    Xrm.Sdk.EntityCollection cxStepAnswers = service.RetrieveMultiple(new FetchExpression(string.Format(@"<fetch mapping='logical' version='1.0' distinct='false' output-format='xml-platform' no-lock='true'>
                                                    <entity name='aspect_cxstepanswer'>
                                                    <all-attributes />
                                                    <order descending='false' attribute='aspect_name' />
                                                    <filter type='and'>
                                                        <condition value='{0}' attribute='aspect_cxstepid' operator='eq' />
                                                    </filter>
                                                    </entity>
                                                </fetch>", cxCurrentStep.Id)));

                    foreach (Xrm.Sdk.Entity e in cxStepAnswers.Entities)
                    {
                        utteranceMatch = UtteranceMatch(message.Text, e.Contains("aspect_answers") ? (string)e["aspect_answers"] : null);
                        if (!string.IsNullOrEmpty(utteranceMatch))
                        {
                            cxNextStep = e.Contains("aspect_nextcxstepid") ? (EntityReference)e["aspect_nextcxstepid"] : null;
                            break;
                        }
                    }
                }

                if (utteranceMatch == null)
                {
                    string         noMatchMessage  = string.Format("I'm sorry, I didn't understand '{0}'.", message.Text); //TODO make this message come from CX Bot
                    Xrm.Sdk.Entity noMatchResponse = new Xrm.Sdk.Entity("aspect_cxconversationmessage");
                    conversationClient["aspect_cxconversationid"] = new EntityReference("aspect_cxconversation", "aspect_conversationid", message.Conversation.Id);
                    conversationClient["aspect_cxstepid"]         = new EntityReference(cxCurrentStep.LogicalName, cxCurrentStep.Id);
                    conversationClient["aspect_direction"]        = true;
                    conversationClient["aspect_name"]             = message.Id;
                    conversationClient["aspect_message"]          = noMatchMessage;
                    service.Create(conversationClient);

                    IMessageActivity responseNoMatchMessage = context.MakeMessage();
                    responseNoMatchMessage.Text  = string.Format(noMatchMessage);
                    responseNoMatchMessage.Value = message.Value;
                    await context.PostAsync(responseNoMatchMessage);

                    context.Wait(MessageReceivedAsync);
                    return;
                }
            }


            //Update the last answer in the conversation
            Microsoft.Xrm.Sdk.Entity upsConversation2 = new Microsoft.Xrm.Sdk.Entity("aspect_cxconversation", "aspect_conversationid", message.Conversation.Id);
            upsConversation2["aspect_lastanswer"] = message.Text;
            UpsertResponse cxConversationResponse = (UpsertResponse)service.Execute(new UpsertRequest()
            {
                Target = upsConversation2
            });


            int maxLoopCount     = 10;
            int currentLoopCount = 0;


            //EXECUTE EXIT SEARCH
            Dynamics.ExecuteSearch(service, (EntityReference)cxConversationResponse.Results["Target"], new EntityReference(cxCurrentStep.LogicalName, cxCurrentStep.Id), false);

            //FIRE EXIT WORKFLOW
            Dynamics.FireWorkflow(service, cxCurrentStep, false);

            //REFRESH THE NEXT CX STEP IN CASE A SEARCH/WORKFLOW ALTERED IT
            Xrm.Sdk.Entity rerouteCXStep = Dynamics.GetCXNextStepEntityByConversationId(service, message.Conversation.Id, cxNextStep);

            if (rerouteCXStep != null)
            {
                cxNextStep = new EntityReference(rerouteCXStep.LogicalName, rerouteCXStep.Id);
            }

            while (cxNextStep != null && currentLoopCount <= maxLoopCount)
            {
                if (currentLoopCount > 0)
                {
                    //EXECUTE EXIT SEARCH
                    Dynamics.ExecuteSearch(service, (EntityReference)cxConversationResponse.Results["Target"], new EntityReference(cxCurrentStep.LogicalName, cxCurrentStep.Id), false);

                    //FIRE EXIT WORKFLOW
                    Dynamics.FireWorkflow(service, cxCurrentStep, false);

                    //REFRESH THE NEXT CX STEP IN CASE A SEARCH/WORKFLOW ALTERED IT
                    rerouteCXStep = Dynamics.GetCXNextStepEntityByConversationId(service, message.Conversation.Id, cxNextStep);
                }

                //EXIT IF THERE IS NO NEXT STEP
                if (cxNextStep == null)
                {
                    return;
                }

                //FIRE ENTRY WORKFLOW
                Dynamics.FireWorkflow(service, rerouteCXStep, true);

                //EXECUTE ENTRY SEARCH
                Dynamics.ExecuteSearch(service, (EntityReference)cxConversationResponse.Results["Target"], new EntityReference(rerouteCXStep.LogicalName, rerouteCXStep.Id), true);


                //process question
                switch (Dynamics.CXGetType((OptionSetValue)rerouteCXStep["aspect_type"]))
                {
                case "MESSAGE":
                    await Dynamics.PromptNextQuestion(context, service, cxCurrentStep, rerouteCXStep, message);

                    cxCurrentStep = Dynamics.GetCXCurrentStepEntityByConversationId(service, message.Conversation.Id);
                    cxNextStep    = cxCurrentStep.Contains("aspect_nextcxstepid") ? (EntityReference)cxCurrentStep["aspect_nextcxstepid"] : null;
                    if (cxNextStep == null)
                    {
                        //if the path ended with a search but no default next step execute the exit workflows
                        //EXECUTE EXIT SEARCH
                        Dynamics.ExecuteSearch(service, (EntityReference)cxConversationResponse.Results["Target"], new EntityReference(cxCurrentStep.LogicalName, cxCurrentStep.Id), false);
                        //REFRESH THE NEXT CX STEP IN CASE A SEARCH/WORKFLOW ALTERED IT
                        rerouteCXStep = Dynamics.GetCXNextStepEntityByConversationId(service, message.Conversation.Id, cxNextStep);
                        if (rerouteCXStep != null && rerouteCXStep.Id != cxCurrentStep.Id)
                        {
                            cxNextStep = new EntityReference(rerouteCXStep.LogicalName, rerouteCXStep.Id);
                        }
                    }
                    currentLoopCount++;
                    break;

                case "QUESTION":
                case "MENU":
                case "RECORD":
                case "TRANSFER":
                    await Dynamics.PromptNextQuestion(context, service, cxCurrentStep, rerouteCXStep, message);

                    cxNextStep = null;
                    break;
                }
            }

            context.Wait(MessageReceivedAsync);
        }