Question

As a requirement I cannot use the early bound context created with "CrmSvcUtil". The problem is that a new phonecall activity expects two fields ('from' and 'to') which are Entities of type activityparty. The standard XRM/CRM namespace does not contain a class similar to ActivityParty created with the Utility.

I tried filling it with an EntityCollection but then the field will be empty. Next I tried to recreate the structure of a working phonecall activity. EntityCollection "activityparty" -> with one Entity "activityparty" -> with EntityReference attribute "partyid" -> the entity ref (e.g. "contact" and the contact's id). But it simply does not work.

How can I create an ActivityParty (or better a phonecall Activity) with the "normal" Entitiy classes?

Was it helpful?

Solution

If I'm right you don't need to use an EntityCollection but an array of Entity

To create a phone call with late bound syntax will be:

Entity from1 = new Entity("activityparty");
Entity to1 = new Entity("activityparty");
Entity to2 = new Entity("activityparty"); // two contacts inside the to field

from1["partyid"]= new EntityReference("systemuser", userId);
to1["partyid"]= new EntityReference("contact", contact1Id);
to2["partyid"]= new EntityReference("contact", contact2Id);

Entity phonecall = new Entity("phonecall");

phonecall["from"] = new Entity[] { from1 };
phonecall["to"] = new Entity[] { to1, to2 };
// other phonecall fields

Guid phonecallId = service.Create(phonecall);

OTHER TIPS

Even though I upvoted the answer but I had simmilar problem with serialization of ActivityParty. I came to solution that doesn't require you to give up on early bound entities.

what you need to do is something like this:

IEnumerable<ActivityParty> party = new [] { new ActivityParty { PartyId="", EntityLogicalName="..." } }; 
phonecall["to"] = new EntityCollection(party.Select(x => x.ToEntity<Entity>).ToList());

(I didn't test the code and wrote it from the air but you should feel the idea)

I vote for TrN because i was looking for any kind of example, and it's the only early bound example that i could find.

His example Actually helped me create an PhoneCall entity that had the Attribute "From" pointing to the Lead that actually made the call. I never fully understood the IEnumerable<ActivityParty> enumerator. Thanks to TrN i understand it enough to use it.

Here is my code regarding the PhoneCall activity that I've tested and it works. Everytime an existing Lead calls. The PhoneCall activity gets saved with the correct Attribute values linked to the correct Lead.

IEnumerable<ActivityParty> party = new[] { new ActivityParty { LogicalName = ActivityParty.EntityLogicalName , PartyId = eref2  } };


                    Console.WriteLine("Logging activity to {0}", firstName);
                    Console.WriteLine("... \n" );
                    PhoneCall newCall = new PhoneCall { Description = "Missed phone call from this lead", DirectionCode = true, RegardingObjectId = eref2,
                        Subject = "Missed Call", PhoneNumber = MissedCall, OwnerId = User, From = party };



                    Guid newCallId = service.Create(newCall);

                Console.WriteLine("Log successfully created \n \n ");

As i said, For Kirschi this isnt the real solution given his requirement of not having any context. But anyone who wants/can use provided context and is curious how the IEnumerable<ActivityParty> works, this might help them to create a proper PhoneCall Activity.

Here is working code for the same. Feel free to reach out if anyone faces any issue.

private static void fetchRelatedPhoneCalls(IPluginExecutionContext context, IOrganizationService service, Guid yourGuid, Entity opp)
{
    string strFetchPhoneCalls = string.Format(FetchQuery.bringFetchQueryForPhoneCalls(),yourGuid);
    EntityCollection entPhoneCalls = (EntityCollection)service.RetrieveMultiple(new FetchExpression(strFetchPhoneCalls));

    if (entPhoneCalls != null && entPhoneCalls.Entities.Count > 0)
    {
        for (int i = 0; i < entPhoneCalls.Entities.Count; i++)
        {
            Entity entPhoneCall = (Entity)entPhoneCalls.Entities[i];

            string[] strAttributesPCtoRemove = new string[] { "createdon", "createdbyname", "createdby"
                            ,"modifiedon", "modifiedby" ,"regardingobjectid","owninguser"
                            ,"activityid", "instancetypecode", "activitytypecode" // PhoneCall Skip
            };

            Entity entNewPhoneCall = this.CloneRecordForEntity("phonecall", entPhoneCall, strAttributesPCtoRemove);
            entNewPhoneCall["regardingobjectid"] = new EntityReference(context.PrimaryEntityName, context.PrimaryEntityId);
            entNewPhoneCall["to"] = this.getActivityObject(entNewPhoneCall, "to");
            entNewPhoneCall["from"] = this.getActivityObject(entNewPhoneCall, "from");

            service.Create(entNewPhoneCall);
        }
    }
}

private static Entity CloneRecordForEntity(string targetEntityName, Entity sourceEntity, string[] strAttributestoRemove)
{
    Entity clonedEntity = new Entity(targetEntityName);
    AttributeCollection attributeKeys = sourceEntity.Attributes;
    foreach (string key in attributeKeys.Keys)
    {
        if (Array.IndexOf(strAttributestoRemove, key) == -1)
        {
            if (!clonedEntity.Contains(key))
            {
                clonedEntity[key] = sourceEntity[key];
            }
        }
    }
    return clonedEntity;
}

private static EntityCollection getActivityObject(Entity entNewActivity, string activityFieldName)
{
    Entity partyToFrom = new Entity("activityparty");
    partyToFrom["partyid"] = ((EntityReference)((EntityCollection)entNewActivity[activityFieldName]).Entities[0].Attributes["partyid"]);

    EntityCollection toFrom = new EntityCollection();
    toFrom.Entities.Add(partyToFrom);

    return toFrom;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top