简体   繁体   中英

Microsoft Dynamics CRM - Email Entity Retrieve Data - Plug In

I'm trying to write a plugin for the email entity in Microsoft Dynamics CRM Online. Let's say its called "Sample_PlugIn".

I want the plugin to retrieve the sender of the email, and write his/her email address into a field (new_samplefield) of the email.

The Plugin does some other stuff as well (and it's all working), but this part of the code is the one making problems. (My organisation service reference is called "service".)

try                
{               
    Entity email = (Entity)context.InputParameters["Target"];

    EntityCollection fromCollection = (EntityCollection)email.Attributes["from"];

    if (fromCollection != null && fromCollection.Entities.Count > 0)
    {
        Entity sender = fromCollection[0]; 
        email["new_samplefield"] = (string)sender.Attributes["internalemailaddress"];
    }

    service.Update(email);
}

Every time the plug-in is executed, I get this error:

Unexpected exception from plug-in (Execute): Sample_PlugIn.Sample_PlugIn: System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.

It'd be great if anyone could help me - thanks a lot!

In order to fix the problem you will need to understand how partylist fields work and the role of the Activity Party entity on this.

Basically, the "from" field (it also applies for the to, cc and cco fields in the email activity) can hold multiple entity references with different entity types. The Activity Party entity then, is a "wrapper" that allows you to handle all this different entities types as one. You can easily check this inspecting the fromCollection object:

在此处输入图片说明

If you go a step further and inspect the attributes of that entity, you will discover that the attributes are not the ones that you're expecting and now it's pretty obvious that the error is generated because the internalemailaddress attribute does not exist in this entity (in fact, this attribute only exists in the systemuser entity so your plugin was not taking into consideration that an account/contact/etc can be a sender too).

In the attributes of the partylist you will find two attributes that can be helpful. The partyid is the actual EntityReference to the record (systemuser/contact/account/etc.) being referenced so you would possible use this to retrieve the record and get the required field. If you only need the emailaddress, you can use the addressused attribute as in the following example:

        Entity email = (Entity)context.InputParameters["Target"];

        EntityCollection fromCollection = (EntityCollection)email.Attributes["from"];

        if (fromCollection != null && fromCollection.Entities.Count > 0)
        {
            Entity sender = fromCollection[0];
            string emailAddress = (string)sender.Attributes["addressused"];
        }

Just for the sake of completeness, this is the code that worked for me in the end. In this case, the sender is of entity systemuser. (I have registered this plug-in on "post-operation" and "Update".)

try
{
    Entity email = (Entity)context.InputParameters["Target"];

    //  Post Entity Image (since the plug-in is registered on "Update")
    Entity postImage = context.PostEntityImages["Image"];

    EntityCollection fromCollection = postImage.GetAttributeValue<EntityCollection>("from");

    if (fromCollection != null && fromCollection.Entities.Count > 0)
    {
        Entity sender = fromCollection[0];
        EntityReference partyId = sender.GetAttributeValue<EntityReference>("partyid");

        string entityType = partyId.LogicalName.ToString();

        if (entityType == "systemuser")
            {
                //  Create query using querybyattribute
                QueryByAttribute queryToSender = new QueryByAttribute("systemuser");
                queryToSender.ColumnSet = new ColumnSet("systemuserid", "internalemailaddress");

                //  Attribute to query
                queryToSender.Attributes.AddRange("systemuserid");

                //  Value of queried attribute to return
                queryToSender.Values.AddRange(partyId.Id);

                EntityCollection retrievedFromSystemuser = service.RetrieveMultiple(queryToSender);

                foreach (Entity systemuserE in retrievedFromSystemuser.Entities)
                    {
                        email["new_samplefield"] = (string)systemuserE.Attributes["internalemailaddress"];                          
                    }
            }                     
        }

    service.Update(email);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM