Create ActivityParty in CRM without early bound Entities
Asked Answered
C

4

7

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?

Cantatrice answered 30/4, 2014 at 13:9 Comment(0)
T
21

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);
Thinner answered 30/4, 2014 at 17:57 Comment(0)
A
1

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)

Amaro answered 20/3, 2015 at 13:33 Comment(4)
thanks for the upvote :) in your code you have a mixed of early and late bound. For a full example of both styles not mixed you can check my blog: crmanswers.net/2014/08/dynamics-crm-special-data-types.htmlThinner
yes I did, becasue phonecall.To is of a type IEnumerable<ActivityParty> which causes problem with serialization (I had some error: Inner Exception: System.Runtime.Serialization.SerializationException: Type 'MyNamespace.ActivityParty' with data contract name 'ActivityParty:schemas.datacontract.org/2004/07/MyNameSpace' is not expected) and it caused me a headache. funny thing it worked on my dev machine where I have .net 4.5 and the error only occurs on test server where they still have .net 4.0). The way I did it fixed the problem. But I know it looks ugly a bit.Amaro
phonecall.To is an array of ActivityParty (or an array of Entity if you prefer)Thinner
umm.. sorry misunderstanding again, you're right I messed up - just realized that when I read it second timeAmaro
E
0

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.

Eraste answered 23/2, 2017 at 9:12 Comment(0)
F
-1

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;
}
Friedlander answered 8/10, 2015 at 10:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.