protected override void ExecuteMultipleWithRetry(List <EntityWrapper> entities, Func <EntityWrapper, OrganizationRequest> orgRequest) { var requests = new OrganizationRequestCollection(); requests.AddRange(entities.Select(wrapper => orgRequest(wrapper)).ToArray()); int cnt = 0; List <ExecuteMultipleResponseItem> responseWithResults = new List <ExecuteMultipleResponseItem>(); foreach (OrganizationRequest request in requests) { try { OrganizationResponse response = new UpsertResponse() { }; responseWithResults.Add(new ExecuteMultipleResponseItem() { Response = response, RequestIndex = cnt }); } catch (FaultException <OrganizationServiceFault> ex) { responseWithResults.Add(new ExecuteMultipleResponseItem() { Fault = ex.Detail, RequestIndex = cnt }); } cnt++; } PopulateExecutionResults(entities, responseWithResults); }
internal override OrganizationResponse Execute(OrganizationRequest orgRequest, EntityReference userRef) { var request = MakeRequest <UpsertRequest>(orgRequest); var resp = new UpsertResponse(); var target = request.Target; var entityId = db.GetEntityOrNull(target.ToEntityReferenceWithKeyAttributes())?.Id; if (entityId.HasValue) { var req = new UpdateRequest(); target.Id = entityId.Value; req.Target = target; core.Execute(req, userRef); resp.Results["RecordCreated"] = false; resp.Results["Target"] = target.ToEntityReferenceWithKeyAttributes(); } else { var req = new CreateRequest { Target = target }; target.Id = (core.Execute(req, userRef) as CreateResponse).id; resp.Results["RecordCreated"] = true; resp.Results["Target"] = target.ToEntityReferenceWithKeyAttributes(); } return(resp); }
private UpsertResponse HandleUpsert(OrganizationRequest orgRequest, EntityReference userRef) { var request = MakeRequest <UpsertRequest>(orgRequest); var resp = new UpsertResponse(); var target = request.Target; var entityId = dataMethods.GetEntityId(target.ToEntityReferenceWithKeyAttributes()); if (entityId.HasValue) { var req = new UpdateRequest(); target.Id = entityId.Value; req.Target = target; Execute(req, userRef); resp.Results["RecordCreated"] = false; resp.Results["Target"] = target.ToEntityReferenceWithKeyAttributes(); } else { var req = new CreateRequest(); req.Target = target; target.Id = (Execute(req, userRef) as CreateResponse).id; resp.Results["RecordCreated"] = true; resp.Results["Target"] = target.ToEntityReferenceWithKeyAttributes(); } return(resp); }
public OrganizationResponse Execute(OrganizationRequest request, XrmFakedContext ctx) { var upsertRequest = (UpsertRequest)request; bool recordCreated; var service = ctx.GetOrganizationService(); var entityLogicalName = upsertRequest.Target.LogicalName; var entityId = ctx.GetRecordUniqueId(upsertRequest.Target.ToEntityReferenceWithKeyAttributes(), validate: false); if (ctx.Data.ContainsKey(entityLogicalName) && ctx.Data[entityLogicalName].ContainsKey(entityId)) { recordCreated = false; service.Update(upsertRequest.Target); } else { recordCreated = true; entityId = service.Create(upsertRequest.Target); } var result = new UpsertResponse(); result.Results.Add("RecordCreated", recordCreated); result.Results.Add("Target", new EntityReference(entityLogicalName, entityId)); return(result); }
/// <summary> /// A shortcut for Upsert message. There is much more messages to create shortcut for, but this one is only useful for daily CRUD operations /// </summary> public static EntityReference Upsert(this IOrganizationService service, Entity entity) { UpsertResponse response = service.Execute <UpsertResponse>(new UpsertRequest() { Target = entity }); return(response.Target); }
public static async Task <Microsoft.Xrm.Sdk.Entity> PromptNextQuestion(IDialogContext context, IOrganizationService service, Microsoft.Xrm.Sdk.Entity cxCurrentStep, Microsoft.Xrm.Sdk.Entity cxNextStep, IMessageActivity message) { Microsoft.Xrm.Sdk.Entity cxStep = service.Retrieve(cxNextStep.LogicalName, cxNextStep.Id, new ColumnSet(true)); //update conversation to initiate any workflow triggers Microsoft.Xrm.Sdk.Entity upsConversation = new Microsoft.Xrm.Sdk.Entity("aspect_cxconversation", "aspect_conversationid", message.Conversation.Id); upsConversation["aspect_nextcxstepid"] = new EntityReference(cxNextStep.LogicalName, cxNextStep.Id); UpsertResponse upsResponse = (UpsertResponse)service.Execute(new UpsertRequest() { Target = upsConversation }); string responseText = ReplaceOutputText(service, (EntityReference)upsResponse["Target"], (string)cxStep["aspect_message"]); //Create a conversation message with outbound message Microsoft.Xrm.Sdk.Entity conversationMessageOutbound = new Microsoft.Xrm.Sdk.Entity("aspect_cxconversationmessage"); conversationMessageOutbound["aspect_cxconversationid"] = new EntityReference("aspect_cxconversation", "aspect_conversationid", message.Conversation.Id); conversationMessageOutbound["aspect_cxstepid"] = new EntityReference(cxNextStep.LogicalName, cxNextStep.Id); conversationMessageOutbound["aspect_direction"] = true; conversationMessageOutbound["aspect_name"] = message.Id; conversationMessageOutbound["aspect_message"] = responseText; service.Create(conversationMessageOutbound); //Update conversation to reflect the current step Microsoft.Xrm.Sdk.Entity upsConversation2 = new Microsoft.Xrm.Sdk.Entity("aspect_cxconversation", "aspect_conversationid", message.Conversation.Id); upsConversation2["aspect_currentcxstepid"] = new EntityReference(cxNextStep.LogicalName, cxNextStep.Id); upsConversation2["aspect_lastanswer"] = message.Text; upsConversation2["aspect_nextcxstepid"] = null; service.Execute(new UpsertRequest() { Target = upsConversation2 }); //send outbound message IMessageActivity responseMessage = context.MakeMessage(); responseMessage.Text = responseText; responseMessage.Speak = responseText; responseMessage.InputHint = Dynamics.CXGetAnswers(service, cxStep); responseMessage.Value = JsonConvert.SerializeObject(new Dynamics.CXInformation() { //CXBotId = ((Guid)(((AliasedValue)["aspect_cxbot.aspect_cxbotid"]).Value)).ToString(), CXBotName = (string)(((AliasedValue)cxCurrentStep["aspect_cxbot.aspect_name"]).Value), AudioDirectory = cxCurrentStep.Contains("aspect_cxbot.aspect_audiodirectory") ? (string)(((AliasedValue)cxCurrentStep["aspect_cxbot.aspect_audiodirectory"]).Value) : string.Empty, RecordingDirectory = cxCurrentStep.Contains("aspect_cxbot.aspect_recordingdirectory") ? (string)(((AliasedValue)cxCurrentStep["aspect_cxbot.aspect_recordingdirectory"]).Value) : string.Empty, CXStepId = cxStep.Id.ToString(), CXStepAudio = cxStep.Contains("aspect_audio") ? (string)cxStep["aspect_audio"] : string.Empty, CXText = responseText, CXAnswers = CXGetAnswers(service, cxStep), CXType = Dynamics.CXGetType((OptionSetValue)cxStep["aspect_type"]) }); await context.PostAsync(responseMessage); return(cxNextStep); }
public void ProcessUpsert(String Filename) { Console.WriteLine("Executing upsert operation....."); XmlTextReader tr = new XmlTextReader(Filename); XmlDocument xdoc = new XmlDocument(); xdoc.Load(tr); XmlNodeList xnlNodes = xdoc.DocumentElement.SelectNodes("/products/product"); foreach (XmlNode xndNode in xnlNodes) { String productCode = xndNode.SelectSingleNode("Code").InnerText; String productName = xndNode.SelectSingleNode("Name").InnerText; String productCategory = xndNode.SelectSingleNode("Category").InnerText; String productMake = xndNode.SelectSingleNode("Make").InnerText; //use alternate key for product Entity productToCreate = new Entity("sample_product", "sample_productcode", productCode); productToCreate["sample_name"] = productName; productToCreate["sample_category"] = productCategory; productToCreate["sample_make"] = productMake; UpsertRequest request = new UpsertRequest() { Target = productToCreate }; try { // Execute UpsertRequest and obtain UpsertResponse. UpsertResponse response = (UpsertResponse)_serviceProxy.Execute(request); if (response.RecordCreated) { Console.WriteLine("New record {0} is created!", productName); } else { Console.WriteLine("Existing record {0} is updated!", productName); } } // Catch any service fault exceptions that Microsoft Dynamics CRM throws. catch (FaultException <Microsoft.Xrm.Sdk.OrganizationServiceFault> ) { throw; } } // Prompts to view the sample_product entity records. // If you choose "y", IE will be launched to display the new or updated records. if (PromptForView()) { ViewEntityListInBrowser(); } }
public async void GivenAnIdentityProvider_WhenUpsertOnNonExisting_ThenIdentityProviderIsCreated() { var identityProviderToCreate = GetIdentityProvider("testnew", "audnew", "http://authnew"); var upsertResponse = new UpsertResponse <IdentityProvider>(identityProviderToCreate, UpsertOutcome.Created, "someEtag"); _controlPlaneDataStore.UpsertIdentityProviderAsync(identityProviderToCreate, null, CancellationToken.None).Returns(upsertResponse); UpsertResponse <IdentityProvider> retUpsertResponse = await _rbacService.UpsertIdentityProviderAsync(identityProviderToCreate, null, CancellationToken.None); Assert.Equal(UpsertOutcome.Created, upsertResponse.OutcomeType); VerifyIdentityProvider("testnew", "audnew", "http://authnew", "1.0", upsertResponse.Resource); }
public void GetOperationTypeWithExecuteMultipleResponseItemHavingUpsertResponse() { var response = new UpsertResponse(); var responseItem = new ExecuteMultipleResponseItem { Response = response }; OperationType actual = OperationType.Update; FluentActions.Invoking(() => actual = responseItem.GetOperationType()) .Should() .NotThrow(); actual.Should().Be(OperationType.Update); }
public static XrmResponse UpsertEntity(Entity entityRecord, IOrganizationService service) { if (entityRecord == null) { return(null); } if (service == null) { return(null); } XrmResponse xrmResponse = null; if (service != null) { UpsertRequest request = new UpsertRequest() { Target = entityRecord }; // Execute UpsertRequest and obtain UpsertResponse. UpsertResponse response = (UpsertResponse)service.Execute(request); if (response.RecordCreated) { xrmResponse = new XrmResponse { Id = response.Target.Id.ToString(), EntityName = entityRecord.LogicalName, Create = true } } ; else { xrmResponse = new XrmResponse() { Id = response.Target.Id.ToString(), EntityName = entityRecord.LogicalName, Create = false } }; } return(xrmResponse); }
private Guid CreateSdkImage(Guid stepId, XmlElement sdkstepImageNode, string messageName, IOrganizationService service) { Guid createdImageId = Guid.Empty; Entity image = new Entity("sdkmessageprocessingstepimage", new Guid(sdkstepImageNode.GetAttribute("Id"))); switch (messageName) { case "Create": image["messagepropertyname"] = "Id"; break; case "SetState": case "SetStateDynamicEntity": image["messagepropertyname"] = "EntityMoniker"; break; case "Send": case "DeliverIncoming": case "DeliverPromote": image["messagepropertyname"] = "EmailId"; break; default: image["messagepropertyname"] = "Target"; break; } Console.WriteLine("Registering the sdk image: " + sdkstepImageNode.GetAttribute("Name")); image["imagetype"] = new OptionSetValue(Convert.ToInt32(sdkstepImageNode.GetAttribute("ImageType"))); image["entityalias"] = sdkstepImageNode.GetAttribute("EntityAlias"); image["name"] = sdkstepImageNode.GetAttribute("Name"); image["attributes"] = sdkstepImageNode.GetAttribute("Attributes"); image["sdkmessageprocessingstepid"] = new EntityReference("sdkmessageprocessingstep", stepId); UpsertRequest upsertsdkImage = new UpsertRequest(); upsertsdkImage.Target = image; UpsertResponse upsertSdkImageReponse = (UpsertResponse)service.Execute(upsertsdkImage); if (upsertSdkImageReponse.RecordCreated) { createdImageId = upsertSdkImageReponse.Target.Id; } return(createdImageId); }
public async void GivenAnIdentityProvider_WhenUpsertWithValidationFailure_ThenInvalidDefintionExceptionIsThrown(string name, string authority, string audience) { var identityProviderToUpdate = Substitute.ForPartsOf <IdentityProvider>(); identityProviderToUpdate.Name.Returns(name); identityProviderToUpdate.Authority.Returns(authority); identityProviderToUpdate.Audience.Returns(new List <string> { audience }); identityProviderToUpdate.ValidateAuthority().Returns(Enumerable.Empty <ValidationResult>()); var upsertResponse = new UpsertResponse <IdentityProvider>(identityProviderToUpdate, UpsertOutcome.Updated, "someEtag"); _controlPlaneDataStore.UpsertIdentityProviderAsync(identityProviderToUpdate, null, CancellationToken.None).Returns(upsertResponse); var exception = await Assert.ThrowsAsync <InvalidDefinitionException>(() => _rbacService.UpsertIdentityProviderAsync(identityProviderToUpdate, null, CancellationToken.None)); Assert.True(exception.Issues.Count() > 0); }
private Guid RegisterWorkflowTypes(EntityReference pluginAssembly, XmlElement workflowTypeNode, IOrganizationService service) { Guid workflowTypeId = Guid.Empty; Entity pluginTypeEntity = new Entity("plugintype", new Guid(workflowTypeNode.GetAttribute("Id"))); pluginTypeEntity["typename"] = workflowTypeNode.GetAttribute("TypeName"); pluginTypeEntity["friendlyname"] = workflowTypeNode.GetAttribute("friendlyname"); pluginTypeEntity["name"] = workflowTypeNode.GetAttribute("Name"); pluginTypeEntity["pluginassemblyid"] = pluginAssembly; pluginTypeEntity["workflowactivitygroupname"] = workflowTypeNode.GetAttribute("WorkflowActivityGroupName"); pluginTypeEntity["isworkflowactivity"] = true; UpsertRequest upsertPluginTypeRequest = new UpsertRequest(); upsertPluginTypeRequest.Target = pluginTypeEntity; UpsertResponse upsertPluginTypeResponse = (UpsertResponse)service.Execute(upsertPluginTypeRequest); if (upsertPluginTypeResponse.RecordCreated) { workflowTypeId = upsertPluginTypeResponse.Target.Id; } return(workflowTypeId); }
public void RegisterPluginsFromXml(string registrationXmlPath, string pluginsDllFilePath, IOrganizationService service) { RetrievePluginTypes retrievePluginTypes = new RetrievePluginTypes(); string strPluginDllName = Path.GetFileName(pluginsDllFilePath); XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(registrationXmlPath); XmlNodeList xnList = xmlDoc.DocumentElement.SelectNodes("/Register/Solutions/Solution[@Assembly='" + strPluginDllName + "']"); foreach (XmlElement node in xnList) { var id = node.GetAttribute("Id"); UnRegisterPlugins unregisterPlugins = new UnRegisterPlugins(); Console.WriteLine("Unregistering the plugin assembly: " + strPluginDllName); unregisterPlugins.UnRegisterPluginTypes(new Guid(id), service); var sourceType = Convert.ToInt32(node.GetAttribute("SourceType").ToString()); var isolationMode = Convert.ToInt32(node.GetAttribute("IsolationMode").ToString()); Entity pluginAssembly = new Entity("pluginassembly", new Guid(id)); pluginAssembly["isolationmode"] = new OptionSetValue(isolationMode); pluginAssembly["sourcetype"] = new OptionSetValue(sourceType); pluginAssembly["content"] = Convert.ToBase64String(File.ReadAllBytes(pluginsDllFilePath)); UpsertRequest upsertpluginAssemblyRequest = new UpsertRequest(); upsertpluginAssemblyRequest.Target = pluginAssembly; UpsertResponse upsertPluginAssemblyResponse = (UpsertResponse)service.Execute(upsertpluginAssemblyRequest); node.Attributes["Id"].Value = upsertPluginAssemblyResponse.Target.Id.ToString(); pluginAssembly.Id = upsertPluginAssemblyResponse.Target.Id; XmlNodeList workflowTypeList = node.SelectNodes("WorkflowTypes/WorkflowType"); foreach (XmlElement workflowType in workflowTypeList) { Guid workflowTypeId = RegisterWorkflowTypes(new EntityReference(pluginAssembly.LogicalName, upsertPluginAssemblyResponse.Target.Id), workflowType, service); workflowType.Attributes["Id"].Value = workflowTypeId.ToString(); } XmlNodeList pluginTypeList = node.SelectNodes("PluginTypes/Plugin"); foreach (XmlElement pluginType in pluginTypeList) { Console.WriteLine("Registering the plugin type: " + pluginType.GetAttribute("TypeName")); Entity pluginTypeEntity = new Entity("plugintype", new Guid(pluginType.GetAttribute("Id"))); pluginTypeEntity["typename"] = pluginType.GetAttribute("TypeName"); pluginTypeEntity["friendlyname"] = pluginType.GetAttribute("friendlyname"); pluginTypeEntity["name"] = pluginType.GetAttribute("Name"); pluginTypeEntity["pluginassemblyid"] = new EntityReference(pluginAssembly.LogicalName, pluginAssembly.Id); UpsertRequest upsertPluginTypeRequest = new UpsertRequest(); upsertPluginTypeRequest.Target = pluginTypeEntity; UpsertResponse upsertPluginTypeResponse = (UpsertResponse)service.Execute(upsertPluginTypeRequest); if (upsertPluginTypeResponse.RecordCreated) { pluginType.Attributes["Id"].Value = upsertPluginTypeResponse.Target.Id.ToString(); } XmlNodeList sdksteps = pluginType.SelectNodes("Steps/Step"); foreach (XmlElement sdkmessageStepNode in sdksteps) { Console.WriteLine("Registering the sdk step: " + sdkmessageStepNode.GetAttribute("Name")); Entity sdkmessageProcessingStep = new Entity("sdkmessageprocessingstep", new Guid(sdkmessageStepNode.GetAttribute("Id"))); sdkmessageProcessingStep["name"] = sdkmessageStepNode.GetAttribute("Name"); sdkmessageProcessingStep["description"] = sdkmessageStepNode.GetAttribute("Description"); Guid messageId = retrievePluginTypes.GetSdkMessageId(sdkmessageStepNode.GetAttribute("MessageName"), service); sdkmessageProcessingStep["sdkmessageid"] = new EntityReference("sdkmessage", messageId); sdkmessageProcessingStep["plugintypeid"] = new EntityReference("plugintype", upsertPluginTypeResponse.Target.Id); sdkmessageProcessingStep["mode"] = new OptionSetValue(Convert.ToInt32(sdkmessageStepNode.GetAttribute("Mode"))); //0=sync,1=async sdkmessageProcessingStep["rank"] = Convert.ToInt32(sdkmessageStepNode.GetAttribute("Rank")); sdkmessageProcessingStep["stage"] = new OptionSetValue(Convert.ToInt32(sdkmessageStepNode.GetAttribute("Stage"))); //10-preValidation, 20-preOperation, 40-PostOperation sdkmessageProcessingStep["supporteddeployment"] = new OptionSetValue(Convert.ToInt32(sdkmessageStepNode.GetAttribute("SupportedDeployment"))); Guid messageFitlerId = retrievePluginTypes.GetSdkMessageFilterId(sdkmessageStepNode.GetAttribute("PrimaryEntityName"), messageId, service); sdkmessageProcessingStep["sdkmessagefilterid"] = new EntityReference("sdkmessagefilter", messageFitlerId); UpsertRequest upsertPluginStepsRequest = new UpsertRequest(); upsertPluginStepsRequest.Target = sdkmessageProcessingStep; UpsertResponse upsertPluginStepResponse = (UpsertResponse)service.Execute(upsertPluginStepsRequest); if (upsertPluginStepResponse.RecordCreated) { sdkmessageStepNode.Attributes["Id"].Value = upsertPluginStepResponse.Target.Id.ToString(); } string messageName = sdkmessageStepNode.GetAttribute("MessageName"); XmlNodeList sdkstepImages = sdkmessageStepNode.SelectNodes("Images/Image"); foreach (XmlElement sdkstepImageNode in sdkstepImages) { Guid createdImageId = CreateSdkImage(upsertPluginStepResponse.Target.Id, sdkstepImageNode, messageName, service); if (createdImageId != Guid.Empty) { sdkstepImageNode.Attributes["Id"].Value = createdImageId.ToString(); } } } } } xmlDoc.Save(registrationXmlPath); }
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)); }
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); }