locked
Updating the Email entity RRS feed

  • Question

  • When I try to update the email entity I get this error, can someone tell me where i'm going wrong?

    Thanks

    Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: System.ArgumentException: This lookup can only display one item. Lookup ID = Detail:
    <OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
      <ErrorCode>-2147220970</ErrorCode>
      <ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
      <Message>System.ArgumentException: This lookup can only display one item. Lookup ID = </Message>
      <Timestamp>2014-08-18T16:20:11.0586257Z</Timestamp>
      <InnerFault i:nil="true" />
      <TraceText i:nil="true" />
    </OrganizationServiceFault>

    and here's the code

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Text.RegularExpressions;
    using Microsoft.Xrm.Sdk;
    using Microsoft.Xrm.Sdk.Client;
    
    namespace EmailReadReceipt
    {
        public class EMailReadReceipt : IPlugin
        {
            public void Execute(IServiceProvider serviceProvider)
            {
                var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
                IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
    
                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
                {
                    Entity email = (Entity)context.InputParameters["Target"];
    
    
                    if (email.LogicalName == "email")
                    {
                        string ReadReceiptInput = "False";
                        ReadReceiptInput = email["new_readreceiptrequired"].ToString();
    
                        //tracingService.Trace("Read Receipt Requested by User =" + ReadReceiptInput);
                        if (ReadReceiptInput == "True")
                        {
    
                            IOrganizationService service = factory.CreateOrganizationService(context.UserId);
                            OrganizationServiceContext orgContext = new OrganizationServiceContext(service);
    
                            email["readreceiptrequested"] = true;
                            service.Update(email);
                            
                        }
                        else
                        {
                            //service.Update(entity);
                            //tracingService.Trace("Read Receipt not requested");
                        }
                    }
                    else
                    {
                        throw new InvalidPluginExecutionException(
                           "EmailReadReceipt Error");
                    }
                }
            }
        }
    }
    
    


    Pete

    Monday, August 18, 2014 4:22 PM

Answers

  • The main problem with the code is that you are passing the whole Target InputParameter to the Update method. This means that CRM will assume you are trying to update every attribute in the Target InputParameter, and some of these may not be updatable.

    As you only want to update a couple of fields, create a new entity instance for this:

    Entity emailUpdate = new Entity("email");
    emailUpdate.Id = context.PrimaryEntityId;
    emailUpdate["readreceiptrequested"] = true;
    emailUpdate["subject"] = "test subject and read receipt updated";
    service.Update(emailUpdate);
    

    Re the state of the email; once an email is completed, many fields are not editable (the regardingobjectid is, but not much else) for good reason - e.g. there's not a lot of point setting readreceiptrequested after an email has been sent.

    You can get around this in most cases by running the plugin on a pre-stage, as per the previous post


    Microsoft CRM MVP - http://mscrmuk.blogspot.com/ http://www.excitation.co.uk

    • Marked as answer by Pete.CRM Monday, September 1, 2014 9:12 AM
    Wednesday, August 27, 2014 8:23 AM
    Moderator
  • Hi Pete,

    See if this code works? if you are calling the plugin on pre-validate or pre-operation, the following code is all required. no need to use update service. use service if it is a post-operation or async plugin step

    Regards,

    Jithesh

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.Text.RegularExpressions;
    using Microsoft.Xrm.Sdk;
    using Microsoft.Xrm.Sdk.Client;
    
    namespace EmailReadReceipt
    {
        public class EMailReadReceipt : IPlugin
        {
            public void Execute(IServiceProvider serviceProvider)
            {
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
                IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
    
                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
                {
                    // Obtain the target entity from the input parameters.
                    Entity email = (Entity)context.InputParameters["Target"];
    
                    if (email.LogicalName == "email")
                    {
                        string ReadReceiptInput = "False";
                        ReadReceiptInput = email["new_readreceiptrequired"].ToString();
    
                        if (ReadReceiptInput == "True")
                        {
                            try
                            {
                                // Check if the attribute us already there, if not add.
                                if (email.Attributes.Contains("readreceiptrequested"))
                                {
                                    email["readreceiptrequested"] = true;
                                }
                                else
                                {
                                    email.Attributes.Add("readreceiptrequested", true);
                                }
                                email["subject"] = "test subject and read receipt updated"; //Subject is mandatory - so will be there in the attributes
                                
                            }
                            catch (FaultException<OrganizationServiceFault> ex)
                            {
                                throw new InvalidPluginExecutionException("An error occurred in the Email Read Receipt plug-in.", ex);
                            }
    
                            catch (Exception ex)
                            {
                                tracingService.Trace("Email Read Receipt: {0}", ex.ToString());
                                throw;
                            }
    
                        }
                        else
                        {
                            return;
                        }
                    }
                    else
                    {
                        throw new InvalidPluginExecutionException(
                           "EmailReadReceipt Error");
                    }
                }
            }
        }
    }


    • Marked as answer by Pete.CRM Monday, September 1, 2014 9:12 AM
    Tuesday, August 26, 2014 11:31 AM

All replies

  • the message doesn't look related to this code, there are other plugins attached to the update message for email entity?

    and which is the status of the email you are trying to update?

    and the code you posted, at which message is attached?


    My blog: www.crmanswers.net - Rockstar 365 Profile

    Monday, August 18, 2014 4:38 PM
  • This is the only plugin on this entity, it only fails when it does the update of the readreceiptrequested field to true

    I.e this line of code

    service.Update(email);

    If you comment this line out the code runs ok, but obviously doesn't update the record as I need.


    Thanks


    Pete

    Tuesday, August 19, 2014 9:00 AM
  • I managed to get this slightly update code to run async but not sync, and only async when the email is draft, not completed.

    Any ideas how I get this to run sync?

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.Text.RegularExpressions;
    using Microsoft.Xrm.Sdk;
    using Microsoft.Xrm.Sdk.Client;
    
    namespace EmailReadReceipt
    {
        public class EMailReadReceipt : IPlugin
        {
            public void Execute(IServiceProvider serviceProvider)
            {
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
                IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
    
                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
                {
                    // Obtain the target entity from the input parameters.
                    Entity email = (Entity)context.InputParameters["Target"];
    
                    if (email.LogicalName == "email")
                    {
                        string ReadReceiptInput = "False";
                        ReadReceiptInput = email["new_readreceiptrequired"].ToString();
    
                        if (ReadReceiptInput == "True")
                        {
                            try
                            {
                                // Obtain the organization service reference.
                                IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
    
                                email["readreceiptrequested"] = true;
                                email["subject"] = "test subject and read receipt updated";
                                service.Update(email);
                            }
                            catch (FaultException<OrganizationServiceFault> ex)
                            {
                                throw new InvalidPluginExecutionException("An error occurred in the Email Read Receipt plug-in.", ex);
                            }
    
                            catch (Exception ex)
                            {
                                tracingService.Trace("Email Read Receipt: {0}", ex.ToString());
                                throw;
                            }
    
                        }
                        else
                        {
                            return;
                        }
                    }
                    else
                    {
                        throw new InvalidPluginExecutionException(
                           "EmailReadReceipt Error");
                    }
                }
            }
        }
    }
    
    


    Pete

    Tuesday, August 19, 2014 9:25 AM
  • Do you have any Real Time workflows on the e-mail entity?

    I have had the same problem. This was resulted by a Real Time updating the email.

    Tuesday, August 26, 2014 7:07 AM
  • Hi Pete,

    See if this code works? if you are calling the plugin on pre-validate or pre-operation, the following code is all required. no need to use update service. use service if it is a post-operation or async plugin step

    Regards,

    Jithesh

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.Text.RegularExpressions;
    using Microsoft.Xrm.Sdk;
    using Microsoft.Xrm.Sdk.Client;
    
    namespace EmailReadReceipt
    {
        public class EMailReadReceipt : IPlugin
        {
            public void Execute(IServiceProvider serviceProvider)
            {
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
                IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
    
                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
                {
                    // Obtain the target entity from the input parameters.
                    Entity email = (Entity)context.InputParameters["Target"];
    
                    if (email.LogicalName == "email")
                    {
                        string ReadReceiptInput = "False";
                        ReadReceiptInput = email["new_readreceiptrequired"].ToString();
    
                        if (ReadReceiptInput == "True")
                        {
                            try
                            {
                                // Check if the attribute us already there, if not add.
                                if (email.Attributes.Contains("readreceiptrequested"))
                                {
                                    email["readreceiptrequested"] = true;
                                }
                                else
                                {
                                    email.Attributes.Add("readreceiptrequested", true);
                                }
                                email["subject"] = "test subject and read receipt updated"; //Subject is mandatory - so will be there in the attributes
                                
                            }
                            catch (FaultException<OrganizationServiceFault> ex)
                            {
                                throw new InvalidPluginExecutionException("An error occurred in the Email Read Receipt plug-in.", ex);
                            }
    
                            catch (Exception ex)
                            {
                                tracingService.Trace("Email Read Receipt: {0}", ex.ToString());
                                throw;
                            }
    
                        }
                        else
                        {
                            return;
                        }
                    }
                    else
                    {
                        throw new InvalidPluginExecutionException(
                           "EmailReadReceipt Error");
                    }
                }
            }
        }
    }


    • Marked as answer by Pete.CRM Monday, September 1, 2014 9:12 AM
    Tuesday, August 26, 2014 11:31 AM
  • The main problem with the code is that you are passing the whole Target InputParameter to the Update method. This means that CRM will assume you are trying to update every attribute in the Target InputParameter, and some of these may not be updatable.

    As you only want to update a couple of fields, create a new entity instance for this:

    Entity emailUpdate = new Entity("email");
    emailUpdate.Id = context.PrimaryEntityId;
    emailUpdate["readreceiptrequested"] = true;
    emailUpdate["subject"] = "test subject and read receipt updated";
    service.Update(emailUpdate);
    

    Re the state of the email; once an email is completed, many fields are not editable (the regardingobjectid is, but not much else) for good reason - e.g. there's not a lot of point setting readreceiptrequested after an email has been sent.

    You can get around this in most cases by running the plugin on a pre-stage, as per the previous post


    Microsoft CRM MVP - http://mscrmuk.blogspot.com/ http://www.excitation.co.uk

    • Marked as answer by Pete.CRM Monday, September 1, 2014 9:12 AM
    Wednesday, August 27, 2014 8:23 AM
    Moderator
  • cool, Thank you David.

    regards,

    Jithesh

    Wednesday, August 27, 2014 9:11 AM