Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // <copyright file="Plugin.cs" company="">
- // Copyright (c) 2014 All Rights Reserved
- // </copyright>
- // <author></author>
- // <date>11/20/2014 2:09:49 PM</date>
- // <summary>Implements the Plugin Workflow Activity.</summary>
- // <auto-generated>
- // This code was generated by a tool.
- // Runtime Version:4.0.30319.1
- // </auto-generated>
- //http://msdn.microsoft.com/en-us/library/microsoft.crm.sdk.messages.addlistmemberslistrequest.aspx
- //http://gonzaloruizcrm.blogspot.com/2012/07/triggering-plugins-workflows-when.html
- //http://mileyja.blogspot.com/2011/11/add-multiple-entities-members-to.html
- //http://thecrmclub.blogspot.com/2013/08/How-to-programmatically-retrieve-Marketing-List-from-inside-Plugin-Dynamics-CRM.html
- //http://nishantrana.me/2012/08/18/sample-code-to-retrieve-all-the-members-of-a-static-marketing-list-in-crm-2011/
- //http://msdn.microsoft.com/en-us/library/hh372953.aspx
- //http://msdn.microsoft.com/en-us/library/gg309252.aspx
- //http://mileyja.blogspot.com/2011/11/add-entity-member-to-marketing-list-in_16.html
- //https://community.dynamics.com/crm/b/mileyja/archive/2011/11/15/remove-an-entity-member-from-a-marketing-list-in-microsoft-dynamics-crm-2011-using-net-or-jscript.aspx
- //https://social.microsoft.com/Forums/en-US/28d8b79f-fc27-4baa-82bc-9d5fe0fcbe16/update-delete-contacts-from-static-marketing-list-through-plugin-in-mscrm-2011?forum=crmdevelopment
- //http://www.koorb.co.nz/highlights-and-updates/how-to-integrate-with-dynamics-crm-marketing-lists-with-a-plug-in/
- namespace LansingMarketingList
- {
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Globalization;
- using System.Linq;
- using System.ServiceModel;
- using Microsoft.Crm.Sdk.Messages;
- using Microsoft.Xrm.Sdk;
- using Microsoft.Xrm.Sdk.Client;
- using Microsoft.Xrm.Sdk.Query;
- using Microsoft.Xrm.Sdk.Messages;
- using System.Collections;
- /// <summary>
- /// Base class for all Plugins.
- /// </summary>
- public class Plugin : IPlugin
- {
- private IOrganizationService orgService;
- private TraceServiceWrapper tracingService;
- //For some reason, the option set contains acct, contact and lead, 1 2 and 4. 3 is Skipped.
- public enum marketingListType { None = 0, Account = 1, Contact = 2, DUMMYDONOTUSETHISVALUEISBAD = 3, Lead = 4 };
- /// <summary>
- /// Executes the plug-in.
- /// </summary>
- /// <param name="serviceProvider">The service provider.</param>
- /// <remarks>
- /// For improved performance, Microsoft Dynamics CRM caches plug-in instances.
- /// The plug-in's Execute method should be written to be stateless as the constructor
- /// is not called for every invocation of the plug-in. Also, multiple system threads
- /// could execute the plug-in at the same time. All per invocation state information
- /// is stored in the context. This means that you should not use global variables in plug-ins.
- /// </remarks>
- private static object setValueSafely(AttributeCollection collection, string key, object val)
- {
- if (!collection.ContainsKey(key))
- {
- collection.Add(key, val);
- }
- else
- {
- collection[key] = val;
- }
- return val;
- }
- Entity getEntity(Guid id, string logicalname, IOrganizationService service)
- {
- Entity r = (Entity)service.Retrieve(logicalname, id,
- new ColumnSet { AllColumns = true });
- return r;
- }
- /*
- * We are not going to include checking the Marketing Lists for Duplicates, because duplicate entries
- * are not allowed on the Data Grid.
- */
- public void Execute(IServiceProvider serviceProvider)
- {
- #region instantiation
- marketingListType listType = marketingListType.None; //Used for tracking purposes.
- Guid listGuid = new Guid(); //Holds the Guid of our marketing list.
- Guid relatedGuid = new Guid();//Holds the Guid of whatever related entity we're processing.
- Microsoft.Xrm.Sdk.IPluginExecutionContext context = (Microsoft.Xrm.Sdk.IPluginExecutionContext)
- serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));
- //Create the services that will talk to CRM.
- IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
- IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
- this.orgService = serviceFactory.CreateOrganizationService(context.UserId);
- OrganizationServiceContext ServiceContext = new OrganizationServiceContext(service);
- // The trace wrapper is a CRMPoint.net custom library for matching logging and tracing to a custom entity.
- ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
- //Create our trace service wrapper for custom logging.
- var crmTracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
- if (crmTracingService == null)
- {
- throw new InvalidPluginExecutionException("Failed to retrieve the tracing service.");
- }
- //This tells CRM which tracing configuration to log for.
- this.tracingService = new TraceServiceWrapper(this.orgService, crmTracingService, "AssociationTest");
- this.tracingService.Trace("This is a test. This is only a test.");
- if (context.Depth > 2) { return; } //For recursion. Included and VERY strictly necessary or else the plugin will fire infinitely.
- #endregion
- #region Complete logic block.
- #region associate/disassociate
- if (context.MessageName == "Associate" || context.MessageName == "Disassociate")
- {
- #region validation
- if (!context.InputParameters.Contains("Relationship"))
- {
- this.tracingService.Trace("No relationship found. Exiting plugin.");
- this.tracingService.HandleSuccess();
- return;
- }
- else
- {
- this.tracingService.Trace("Found relationship.");
- }
- ////////////////////////////////////////////////////
- if (!context.InputParameters.Contains("Target"))
- {
- this.tracingService.Trace("No target found. Exiting plugin.");
- this.tracingService.HandleSuccess();
- return;
- }
- else
- {
- this.tracingService.Trace("Found target.");
- }
- ///////////////////////////////////////////////////
- if (!context.InputParameters.Contains("RelatedEntities"))
- {
- this.tracingService.Trace("No Related entities found. Exiting plugin.");
- this.tracingService.HandleSuccess();
- return;
- }
- else
- {
- this.tracingService.Trace("Related entity found.");
- }
- #endregion
- /*
- * Declare these variables here and not in instantiation region because they're of
- * no use if we don't have all of the correct context.InputParameters passed in.
- */
- EntityReference target = (EntityReference)context.InputParameters["Target"];
- EntityReferenceCollection related = (EntityReferenceCollection)context.InputParameters["RelatedEntities"];
- Relationship relationship = (Relationship)context.InputParameters["Relationship"];
- this.tracingService.Trace("About to test for marketing list relationships: " + relationship.SchemaName);
- /*We only want the plugin to fire if one of these 3 EXACT associations is created.
- * Otherwise, exit out of the plugin alltogether.
- */
- if (relationship.SchemaName != "new_new_consolidatedmarketinglist_account" &&
- relationship.SchemaName != "new_new_consolidatedmarketinglist_contact" &&
- relationship.SchemaName != "new_new_consolidatedmarketinglist_lead")
- {
- this.tracingService.Trace("Didn't find one of the 3 necessary associations.");
- this.tracingService.Trace(relationship.SchemaName);
- this.tracingService.HandleSuccess();
- return;
- }
- else
- {
- if (relationship.SchemaName == "new_new_consolidatedmarketinglist_account")
- {
- listType = marketingListType.Account;
- }
- else if (relationship.SchemaName == "new_new_consolidatedmarketinglist_contact")
- {
- listType = marketingListType.Contact;
- }
- else if (relationship.SchemaName == "new_new_consolidatedmarketinglist_lead")
- {
- listType = marketingListType.Lead;
- }
- this.tracingService.Trace("listType set to: " + listType.ToString());
- }
- #region Populate Related Guid
- //this.tracingService.Trace("Plugin Guid: " + context.OwningExtension.Id); //This is the GUID of the plugin.
- //this.tracingService.Trace("Consolidated Marketing List Guid: " + target.Id); //YES YES YES - Guid of the Consolidated Marketing List.
- //This block was for validation of RemoveMEmber. The foreach below it was for validation on associate/disassociate.
- /*
- this.tracingService.Trace("XYZ: " + context.MessageName);
- foreach (KeyValuePair<string, object> x in context.InputParameters)
- {
- this.tracingService.Trace("PX: " + x.ToString());
- this.tracingService.Trace("AX: " + x.Key);
- this.tracingService.Trace("BX: " + x.Value);
- }
- */
- foreach (EntityReference relatedEnt in related)
- {
- //this.tracingService.Trace("Ent name: " + relatedEnt.Name);
- this.tracingService.Trace("Ent log: " + relatedEnt.LogicalName);
- this.tracingService.Trace("Ent id:" + relatedEnt.Id);
- relatedGuid = relatedEnt.Id;
- }
- foreach (KeyValuePair<string, object> x in context.InputParameters)
- {
- //this.tracingService.Trace("PX: " + x.ToString());
- }
- #endregion
- try
- {
- #region associate
- if (context.MessageName == "Associate")
- {
- Entity thisList = getEntity(target.Id, "new_consolidatedmarketinglist", service);
- QueryExpression marketingList = new QueryExpression
- {
- EntityName = "list", //was crmp_policy
- ColumnSet = new ColumnSet { AllColumns = true }
- };
- string entName = thisList.Attributes["new_name"] + "-" + listType.ToString();
- //Should look like: "Test-Line", etc...
- marketingList.Criteria = new FilterExpression(LogicalOperator.And); //Was no LO.and
- marketingList.Criteria.AddCondition("listname", ConditionOperator.Equal, entName);
- marketingList.Criteria.AddCondition("new_consolidatedmarketinglist", ConditionOperator.Equal, new Guid(target.Id.ToString()));
- EntityCollection mlCol = service.RetrieveMultiple(marketingList);
- this.tracingService.Trace("Queried for marketing lists.");
- if (mlCol.Entities.Count < 1) //No entities found.
- {
- Entity list = new Entity("list");
- //OptionSetValue osv = new OptionSetValue((int)marketingListType.Lead);
- setValueSafely(list.Attributes, "listname", entName);
- setValueSafely(list.Attributes, "type", false);//True for Dynamic, False for Static
- setValueSafely(list.Attributes, "createdfromcode", new OptionSetValue((int)listType));
- setValueSafely(list.Attributes, "new_consolidatedmarketinglist", new EntityReference("new_consolidatedmarketinglist", new Guid(target.Id.ToString())));
- //new EntityReference("new_consolidatedmarketinglist",new Guid(target.Id.ToString())));
- listGuid = service.Create(list);
- //type - two option set - static or dynamic static = 0 dynamic = 1
- //createdfromcode - acct = 1, contact = 2, lead = 3
- this.tracingService.Trace("No marketing list found. Created new one: " + entName);
- addMember(listGuid, relatedGuid, service);
- this.tracingService.Trace("Added member to list:" + relatedGuid);
- }
- else
- {
- listGuid = mlCol.Entities[0].Id;
- addMember(listGuid, relatedGuid, service);
- this.tracingService.Trace("Added member to list:");
- }
- this.tracingService.HandleSuccess();
- return; //No need to continue, we're done. :)
- }
- #endregion
- #region disassociate
- if (context.MessageName == "Disassociate")
- {
- Entity thisList = getEntity(target.Id, "new_consolidatedmarketinglist", service);
- QueryExpression marketingList = new QueryExpression
- {
- EntityName = "list", //was crmp_policy
- ColumnSet = new ColumnSet { AllColumns = true }
- };
- string entName = thisList.Attributes["new_name"] + "-" + listType.ToString();
- //Should look like: "Test-Line", etc...
- marketingList.Criteria = new FilterExpression(LogicalOperator.And); //Was no LO.and
- marketingList.Criteria.AddCondition("listname", ConditionOperator.Equal, entName);
- marketingList.Criteria.AddCondition("new_consolidatedmarketinglist", ConditionOperator.Equal, new Guid(target.Id.ToString()));
- EntityCollection mlCol = service.RetrieveMultiple(marketingList);
- this.tracingService.Trace("Queried for marketing lists.");
- if (mlCol.Entities.Count < 1) //No entities found.
- {
- this.tracingService.Trace("No Marketing List found to remove member from.");
- }
- else
- {
- //this.tracingService.Trace("h: " + mlCol.Entities[0].Id);
- //this.tracingService.Trace("i: " + relatedGuid);
- try
- {
- string type = string.Empty;
- OptionSetValue code;
- bool found = false;
- ArrayList memberGuids = new ArrayList();
- this.tracingService.Trace("About to query for list members.");
- PagingInfo pageInfo = new PagingInfo();
- pageInfo.Count = 5000;
- pageInfo.PageNumber = 1;
- QueryByAttribute query = new QueryByAttribute("listmember");
- query.AddAttributeValue("listid", new Guid(mlCol.Entities[0].Id.ToString())); //Query the marketing list to ensure our removed item is a member.
- query.ColumnSet = new ColumnSet(true);
- EntityCollection memberCollection = service.RetrieveMultiple(query);
- this.tracingService.Trace("Queried for list members.");
- if (memberCollection.Entities.Count > 0)
- {
- code = (OptionSetValue)mlCol[0].Attributes["createdfromcode"];
- }
- else
- {
- this.tracingService.Trace("Unable to retrieve marketing list. Returning.");
- return;
- }
- if (code.Value == 1) //act, cnt = 2, lead = 4
- {
- type = "account";
- }
- else if (code.Value == 2)
- {
- type = "contact";
- }
- else if (code.Value == 4)
- {
- type = "lead";
- }
- foreach (Entity member in memberCollection.Entities)
- {
- memberGuids.Add(((EntityReference)member.Attributes["entityid"]).Id);
- }
- while (memberCollection.MoreRecords)
- {
- query.PageInfo.PageNumber += 1;
- query.PageInfo.PagingCookie = memberCollection.PagingCookie;
- memberCollection = orgService.RetrieveMultiple(query);
- foreach (Entity member in memberCollection.Entities)
- {
- memberGuids.Add(((EntityReference)member.Attributes["entityid"]).Id);
- }
- }
- //acct = name, else fullname //accountid, contactid, leadid
- //foreach (Entity member in memberCollection.Entities)
- foreach(Guid id in memberGuids)
- {
- //memberGuids.Add(((EntityReference)member.Attributes["entityid"]).Id);
- if (id == relatedGuid)
- //if (memberGuids.Contains(relatedGuid))
- {
- try
- {
- removeMember(mlCol.Entities[0].Id, relatedGuid, service);
- this.tracingService.Trace("Removed member " + relatedGuid + " from list: " + mlCol.Entities[0].Id);
- }
- catch (Exception ex)
- {
- this.tracingService.Trace(ex.ToString());
- }
- found = true;
- }
- }
- if (found == false)
- {
- this.tracingService.Trace("Unable to find entity of type " + type + " with id of " + relatedGuid + "on marketing list: " + mlCol.Entities[0].Id);
- }
- //removeMember(mlCol.Entities[0].Id, relatedGuid, service);
- //this.tracingService.Trace("Removed member from list:");
- }
- catch (Exception ex)
- {
- this.tracingService.Trace("Unable to remove member: " + ex);
- }
- }
- this.tracingService.HandleSuccess();
- }
- #endregion
- }
- catch (Exception ex)
- {
- this.tracingService.Trace("Failure for: " + relationship.SchemaName);
- this.tracingService.HandleException(ex);
- }
- }
- #endregion
- #region RemoveMember block
- //this.tracingService.Trace("About to delve into REmoveMember code");
- else if (context.MessageName == "RemoveMember")
- {
- //throw new InvalidPluginExecutionException();
- Guid thisMarketListId = Guid.Empty;
- Guid removedEntityId = Guid.Empty;
- EntityReference consolidatedListRef = null;// = new EntityReference();
- #region validation - just want to ensure our input parameters are all here.
- if (!context.InputParameters.Contains("ListId"))
- {
- this.tracingService.Trace("No ListId found. Exiting plugin.");
- this.tracingService.HandleSuccess();
- return;
- }
- else
- {
- this.tracingService.Trace("Found ListId.");
- }
- ////////////////////////////////////////////////////
- if (!context.InputParameters.Contains("EntityId"))
- {
- this.tracingService.Trace("No EntityId found. Exiting plugin.");
- this.tracingService.HandleSuccess();
- return;
- }
- else
- {
- this.tracingService.Trace("Found EntityId.");
- }
- #endregion
- foreach (KeyValuePair<string, object> x in context.InputParameters)
- {
- if (x.Key == "ListId")
- {
- thisMarketListId = (Guid)x.Value;
- this.tracingService.Trace("Found Marketing List ID: " + thisMarketListId);
- }
- if (x.Key == "EntityId")
- {
- removedEntityId = (Guid)x.Value;
- this.tracingService.Trace("Found removed entity ID: " + removedEntityId);
- }
- }
- if (removedEntityId == Guid.Empty) //Unable to pull GUID out of context input.
- {
- this.tracingService.Trace("Unable to find removed entity. Exiting plugin.");
- return;
- }
- if (thisMarketListId == Guid.Empty) //Unable to pull GUID out of context input.
- {
- this.tracingService.Trace("Unable to find marketing list. Exiting plugin.");
- return;
- }
- this.tracingService.Trace("About to retrieve THIS marketing list as an entity.");
- Entity thisList = getEntity(thisMarketListId, "list", service);
- /*foreach (KeyValuePair<string, object> x in thisList.Attributes)
- {
- this.tracingService.Trace(x.Key);
- this.tracingService.Trace(x.Value.ToString());
- }
- */
- //Found our list, and have our deleted entity.
- consolidatedListRef = (EntityReference)thisList.Attributes["new_consolidatedmarketinglist"];
- Entity consolidatedList = getEntity(consolidatedListRef.Id, "new_consolidatedmarketinglist", service);
- this.tracingService.Trace("Consolidated list: " + consolidatedList.Id);
- OptionSetValue val = (OptionSetValue)thisList.Attributes["createdfromcode"]; //act = 1, cnt = 2, ld = 4
- string relationshipName = string.Empty;
- string entityTypeName = string.Empty;
- //this.tracingService.Trace("Val.Value: " + val.Value);
- if (val.Value == 1) //Account
- {
- entityTypeName = "account";
- relationshipName = "new_new_consolidatedmarketinglist_account";
- }
- else if (val.Value == 2)//Contact
- {
- entityTypeName = "contact";
- relationshipName = "new_new_consolidatedmarketinglist_contact";
- }
- else if (val.Value == 4) //Lead
- {
- entityTypeName = "lead";
- relationshipName = "new_new_consolidatedmarketinglist_lead";
- }
- List<Entity> relationships = retrieveRelationships(service, "new_consolidatedmarketinglist", consolidatedList.Id, relationshipName, entityTypeName).ToList();
- this.tracingService.Trace("Just pulled relationships.");
- foreach (Entity ent in relationships)
- {
- if (ent.Id == removedEntityId)
- {
- EntityReferenceCollection erf = new EntityReferenceCollection();
- erf.Add(new EntityReference(ent.LogicalName, ent.Id));
- service.Disassociate(consolidatedList.LogicalName, consolidatedList.Id, new Relationship(relationshipName), erf);//was ent.id and not removedetc
- this.tracingService.Trace("Record" + ent.Id + " disassociated from Consolidated Marketing list: " + consolidatedList.Id);
- }
- else
- {
- //this.tracingService.Trace("");
- }
- }
- this.tracingService.HandleSuccess();
- }
- #endregion
- #endregion
- }
- /*
- * Add member to our "base" marketing list (not consolidated). We're passing in the list id,
- * the entity id, and the organization service.
- */
- public static void addMember(Guid listGuid, Guid relatedGuid, IOrganizationService service)
- {
- AddListMembersListRequest req = new AddListMembersListRequest();
- req.ListId = listGuid;
- req.MemberIds = new System.Guid[1];
- req.MemberIds[0] = relatedGuid;
- AddListMembersListResponse resp = (AddListMembersListResponse)service.Execute(req);
- }
- /*
- * Remove member from our "base" marketing list (not consolidated). We're passing in the list id,
- * the entity id, and the organization service.
- */
- public static void removeMember(Guid listGuid, Guid relatedGuid, IOrganizationService service) //waS VOID
- {
- try
- {
- RemoveMemberListRequest req = new RemoveMemberListRequest();
- req.EntityId = relatedGuid;
- req.ListId = listGuid;
- RemoveMemberListResponse resp = (RemoveMemberListResponse)service.Execute(req);
- }
- catch (Exception ex)
- {
- throw ex;
- }
- }
- IEnumerable<Entity> retrieveRelationships(IOrganizationService service, string primaryEntity, Guid primaryEntityId, string relationshipName, string targetEntity)
- {
- //the related entity we are going to retrieve
- QueryExpression query = new QueryExpression();
- query.EntityName = targetEntity;
- query.ColumnSet = new ColumnSet { AllColumns = true };//("new_totalmonthlytext", "crmp_contract", "crmp_name");
- //the relationship that links the primary to the target
- Relationship relationship = new Relationship(relationshipName);
- relationship.PrimaryEntityRole = EntityRole.Referenced; //important if the relationship is self-referencing
- //the query collection which forms the request
- RelationshipQueryCollection relatedEntity = new RelationshipQueryCollection();
- relatedEntity.Add(relationship, query);
- //the request to get the primary entity with the related records
- RetrieveRequest request = new RetrieveRequest();
- request.RelatedEntitiesQuery = relatedEntity;
- request.ColumnSet = new ColumnSet { AllColumns = true };//("crmp_name");
- request.Target = new EntityReference(primaryEntity, primaryEntityId);
- RetrieveResponse r = (RetrieveResponse)service.Execute(request); //was service.Execute
- //query the returned collection for the target entity ids
- return r.Entity.RelatedEntities[relationship].Entities;//.Select(e => e.Id);
- }
- }
- }
- #region oldexecute
- /* //Old Execute method.
- public void Execute(IServiceProvider serviceProvider)
- {
- if (serviceProvider == null)
- {
- throw new ArgumentNullException("serviceProvider");
- }
- // Construct the Local plug-in context.
- LocalPluginContext localcontext = new LocalPluginContext(serviceProvider);
- localcontext.Trace(string.Format(CultureInfo.InvariantCulture, "Entered {0}.Execute()", this.ChildClassName));
- try
- {
- // Iterate over all of the expected registered events to ensure that the plugin
- // has been invoked by an expected event
- // For any given plug-in event at an instance in time, we would expect at most 1 result to match.
- Action<LocalPluginContext> entityAction =
- (from a in this.RegisteredEvents
- where (
- a.Item1 == localcontext.PluginExecutionContext.Stage &&
- a.Item2 == localcontext.PluginExecutionContext.MessageName &&
- (string.IsNullOrWhiteSpace(a.Item3) ? true : a.Item3 == localcontext.PluginExecutionContext.PrimaryEntityName)
- )
- select a.Item4).FirstOrDefault();
- if (entityAction != null)
- {
- localcontext.Trace(string.Format(
- CultureInfo.InvariantCulture,
- "{0} is firing for Entity: {1}, Message: {2}",
- this.ChildClassName,
- localcontext.PluginExecutionContext.PrimaryEntityName,
- localcontext.PluginExecutionContext.MessageName));
- entityAction.Invoke(localcontext);
- // now exit - if the derived plug-in has incorrectly registered overlapping event registrations,
- // guard against multiple executions.
- return;
- }
- }
- catch (FaultException<OrganizationServiceFault> e)
- {
- localcontext.Trace(string.Format(CultureInfo.InvariantCulture, "Exception: {0}", e.ToString()));
- // Handle the exception.
- throw;
- }
- finally
- {
- localcontext.Trace(string.Format(CultureInfo.InvariantCulture, "Exiting {0}.Execute()", this.ChildClassName));
- }
- }
- */
- #endregion
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement