Sunday, October 26, 2008

Creating an ActivityParty in MS CRM 4.0

In an earlier Blog I covered creating activities, but did not cover the activityparty in depth. Each activity has a number of activityparty arrays containing lookups to the CRM systemuser, contact, lead, and account entities that are involved in that activity.

For many purposes the only attributes that need to be set in each ActivityParty are the participationtypemask and partyid. The name participationtypemask is a little misleading since it needs to be set to a picklist with a value from the ActivityPartyType rather than actually being a bitmask like the SecurityPrincipal AccessMask.

There are numerous ActivityPartyTypes used for the different ActivityParty arrays in each activity. A complete list of  these types is located here MSDN ActivityPartyType Class. The partyid is just a lookup to the appropriate systemuser, contact, lead or account.

Typically when importing activities you will be matching against an email address and/or contact or lead name. I'd included some example code that will creates an activityparty array for use in creating an activity based on email addresses. A few examples of how I would call this are the following:

thisEmail.to = CreateActivityParty(to_rfc882, ActivityPartyType.ToRecipient);
thisEmail.from = CreateActivityParty(from_rfc882, ActivityPartyType.Sender);
thisEmail.cc = CreateActivityParty(cc_rfc882, ActivityPartyType.CcRecipient);
thisEmail.bcc = CreateActivityParty(bcc_rfc882, ActivityPartyType.BccRecipient);

This shows an email entity having a number of attributes assigned an appropriate activityparty array.

This code takes the emailAddresses string from a given email and creates a list of email addresses that will be part of the ActivityParty array. Then it looks for a match for each email address against systemusers, contacts, leads and finally accounts. Notice that an ActivityParty array can consist of any combination of these entities.

/// <summary>
/// Create that list of Parties associated with each email address in the email list
/// </summary>
/// <param name="emailAddresses"></param>
/// <param name="addressType"></param>
/// <returns></returns>
private activityparty[] CreateActivityParty(string emailAddresses, int addressType)
{
    var activityPartiesPerEmail = new List<activityparty>();

    List<string> addresses = CleanEmail(emailAddresses);  // Get a clean email list from the rfc822 address line.

    //Find All Activity parties 
    
    // Pecking order System Users, Contacts, Leads, Accounts

    foreach ( var emailAddress in addresses)
    {
        BusinessEntityCollection users = FindEntitiesByAttribute(emailAddress, EntityName.systemuser.ToString(), "internalemailaddress");

        if (users.BusinessEntities.Length > 0)
        {
            foreach (systemuser user in users.BusinessEntities)
            {
                activityPartiesPerEmail.Add( new activityparty
                    {
                        participationtypemask = CrmTypes.CreatePicklist(addressType),
                        partyid = CrmTypes.CreateLookup(EntityName.systemuser.ToString(), user.systemuserid.Value)
                    }
                  );
                break;
            }
        }
        else
        {
            BusinessEntityCollection contacts = FindEntitiesByAttribute(emailAddress, EntityName.contact.ToString(), "emailaddress1");

            if (contacts.BusinessEntities.Length > 0)
            {
                foreach (contact aContact in contacts.BusinessEntities)
                {
                    activityPartiesPerEmail.Add(new activityparty
                          {
                              participationtypemask = CrmTypes.CreatePicklist(addressType),
                              partyid = CrmTypes.CreateLookup(EntityName.contact.ToString(), aContact.contactid.Value)
                          }
                        );
                    break;
                }
            }
            else
            {
                BusinessEntityCollection leads = FindEntitiesByAttribute(emailAddress, EntityName.lead.ToString(), "emailaddress1");

                if (leads.BusinessEntities.Length > 0)
                {
                    foreach (lead aLead in leads.BusinessEntities)
                    {
                        activityPartiesPerEmail.Add(new activityparty
                            {
                                participationtypemask = CrmTypes.CreatePicklist(addressType),
                                partyid = CrmTypes.CreateLookup(EntityName.lead.ToString(), aLead.leadid.Value)
                            }
                          );
                        break;
                    }
                }
                else
                {
                    BusinessEntityCollection accounts = FindEntitiesByAttribute(emailAddress, EntityName.account.ToString(), "emailaddress1");

                    if (accounts.BusinessEntities.Length > 0)
                    {
                        foreach (account anAccount in accounts.BusinessEntities)
                        {
                            activityPartiesPerEmail.Add(new activityparty
                                {
                                    participationtypemask = CrmTypes.CreatePicklist(addressType),
                                    partyid = CrmTypes.CreateLookup(EntityName.account.ToString(), anAccount.accountid.Value)
                                }
                            );
                            break;
                        }
                    }
                }
            }
        }
    }
    
    var theseParties = new activityparty[activityPartiesPerEmail.Count];

    activityPartiesPerEmail.CopyTo(theseParties);
    
    return theseParties;
}

/// <summary>
/// Returns all entities of a specified type filterd on a specified attribute and value
/// </summary>
/// <param name="emailAddress">attribute filter value</param>
/// <param name="entity">entityName</param>
/// <param name="attributeName">attribute to filter on</param>
/// <returns></returns>
public BusinessEntityCollection FindEntitiesByAttribute(string emailAddress, string entity, string attributeName)
{
    var condition = new ConditionExpression
    {
        AttributeName = attributeName,
        Operator = ConditionOperator.Equal,
        Values = new[] { emailAddress }
    };


    var filter = new FilterExpression
    {
        FilterOperator = LogicalOperator.And,
        Conditions = new[] { condition }
    };


    var query = new QueryExpression
    {
        EntityName = entity,
        ColumnSet = new AllColumns(),
        Criteria = filter
    };

    try
    {
        return service.RetrieveMultiple(query);
    }

    catch (SoapException ex)
    {
        string errormsg = String.Format("Error for FindSystemUserByEmailAddress {0} error {1}", emailAddress, ex.Detail.InnerText);

        WriteErrorFile(errormsg);
        throw;
    }
}

If you have any questions please let me know.

1 comment:

thurein said...

Dear Mark,

Please give me some suggestion,regarding the activityparty[] ,I would like the know how pass the activityparty array from the custom workflow activity as CRMoutput property.Thank you.