Monday, January 2, 2012

CRM 2011 Custom Email with Pdf report attachment

After migration from CRM 4 to CRM 2011 my plugin written for custom email with PDF report won't work anymore so i rebuild my previous solution from CRM 4 with necessary changes for new CRM 2011:

using System;
using System.Activities;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Workflow;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Crm.Sdk.Messages;
using SendReport.ReportService;
using Microsoft.Crm.Sdk;
using Microsoft.Xrm.Sdk.Query;

namespace SendReport
    public class SendReport : CodeActivity

        protected override void Execute(CodeActivityContext executionContext)

                IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
                IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

                Guid incidentId = context.PrimaryEntityId;

                byte[] result = null;

                ReportService.ReportExecutionService rs = new ReportExecutionService();
                rs.Credentials = new System.Net.NetworkCredential("username", "password", "domain");
                rs.Url = "http://crmserver/ReportServer/ReportExecution2005.asmx";

                string reportPath = "/Reports/reportname";
                string format = "PDF";
                string historyID = null;
                string devInfo = @"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";

                ParameterValue[] parameters = new ParameterValue[1];
                parameters[0] = new ParameterValue();
                parameters[0].Name = "incidentid";
                parameters[0].Value = incidentId.ToString();

                DataSourceCredentials[] credentials = null;
                string showHideToggle = null;
                string encoding;
                string mimeType;
                string extension;
                Warning[] warnings = null;
                ParameterValue[] reportHistoryParameters = null;
                string[] streamIDs = null;

                ExecutionInfo execInfo = new ExecutionInfo();
                ExecutionHeader execHeader = new ExecutionHeader();
                rs.ExecutionHeaderValue = execHeader;
                execInfo = rs.LoadReport(reportPath, historyID);
                rs.SetExecutionParameters(parameters, "en-us");
                String SessionId = rs.ExecutionHeaderValue.ExecutionID;

                result = rs.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out

                catch (Exception err)
                    throw new Exception(err.Message.ToString());

                Entity email = new Entity();
                email.LogicalName = "email";

                EntityReference regardingObject = new EntityReference("incident", incidentId);
                email.Attributes.Add("regardingobjectid", regardingObject);

                Guid senderUserId = Sender.Get<EntityReference>(executionContext).Id;
                Guid recieverUserId = Recipient.Get<EntityReference>(executionContext).Id;
                Guid recieverCCUserId = RecipientCC.Get<EntityReference>(executionContext).Id;
                EntityReference from = new EntityReference("systemuser", senderUserId);
                EntityReference to = new EntityReference("contact", recieverUserId);
                EntityReference cc = new EntityReference("contact", recieverCCUserId);

                Entity fromParty = new Entity("activityparty");
                fromParty.Attributes.Add("partyid", from);

                Entity toParty = new Entity("activityparty");
                toParty.Attributes.Add("partyid", to);

                Entity ccParty = new Entity("activityparty");
                ccParty.Attributes.Add("partyid", cc);

                EntityCollection collFromParty = new EntityCollection();
                collFromParty.EntityName = "systemuser";

                EntityCollection collToParty = new EntityCollection();
                collToParty.EntityName = "systemuser";

                EntityCollection collccParty = new EntityCollection();
                collccParty.EntityName = "systemuser";

                var entity = service.Retrieve("incident", incidentId, new ColumnSet(new[] { "ticketnumber", "customerid", "title"}));
                var ticket = entity.GetAttributeValue<string>("ticketnumber");
                var customer = entity.GetAttributeValue<EntityReference>("customerid");
                var customername = customer.Name;
                var title = entity.GetAttributeValue<string>("title");

                email.Attributes.Add("from", collFromParty);
                email.Attributes.Add("to", collToParty);
                email.Attributes.Add("cc", collccParty);

                email.Attributes.Add("subject", "Here goes subject message.. : " + ticket);

                email.Attributes.Add("description", "Here goes description text..");

                Guid emailID = service.Create(email);

                // Attaching Pdf report
                CrmNumber crmNextActorID = new CrmNumber();

                RetrieveEntityRequest request = new RetrieveEntityRequest();
                request.LogicalName = "email";

                RetrieveEntityResponse response = (RetrieveEntityResponse)service.Execute(request);
                int objecttypecode = response.EntityMetadata.ObjectTypeCode.Value;               

                Entity attachment = new Entity("activitymimeattachment");

                attachment.Attributes.Add("subject", "Report");
                attachment.Attributes.Add("filename", "Report.pdf");
                attachment.Attributes.Add("body", Convert.ToBase64String(result));
                attachment.Attributes.Add("filesize", new CrmNumber(Convert.ToInt32(result.Length.ToString())));
                attachment.Attributes.Add("mimetype", "text/plain");
                attachment.Attributes.Add("attachmentnumber", crmNextActorID.Value);

                attachment.Attributes.Add("objectid", new EntityReference("email", new Guid(email.Id.ToString())));
                attachment.Attributes.Add("objecttypecode", objecttypecode);


                SendEmailRequest reqSendEmail = new SendEmailRequest();
                reqSendEmail.EmailId = emailID;
                reqSendEmail.TrackingToken = "";
                reqSendEmail.IssueSend = true;

                SendEmailResponse res = (SendEmailResponse)service.Execute(reqSendEmail);


            catch (Exception err)
                throw new Exception(err.ToString());


        [Input("Sender input")]
        public InArgument<EntityReference> Sender { get; set; }

        [Input("Recipient input")]
        public InArgument<EntityReference> Recipient { get; set; }

        [Input("RecipientCC input")]
        public InArgument<EntityReference> RecipientCC { get; set; }




  1. Thanks a lot for such a great post on CRM 2011 Custom Email with Pdf report attachment. This is very helpful for a newbie like me.

  2. where is the ReportService namespace?

    1. SendReport.ReportService;
      ReportService is web refernce

  3. Thanks for wonderfulpost. Is there anyway i can avoid hard coded password for rs.Credentials
    I tried default and it is not working.
    I want the CRM user password username and credentials to be passed and able to run report.

  4. Hello, how to do to connect my report in reporting services and send email with pdf result?

    1. Hi Veronica, if I understand you correctly you have to upload your report rdl file to report server and then set path to it in your solution like in my example string reportPath = "/Reports/reportname";

  5. Hi,

    i tried your code with our crm but i am experiencing problems when setting the parameters.

    without performing the
    rs.SetExecutionParameters(parameters, "en-us");
    the report is working. but when i want to set it the following error occurs:

    Workflow paused due to error: Unhandled Exception: System.Xml.XmlException: There are multiple root elements. Line 1, position 98.
    at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
    at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
    at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)
    at System.Xml.XmlDocument.Load(XmlReader reader)
    at Microsoft.Crm.SharedUtil.CreateXmlDocument(String xml)
    at Microsoft.Crm.CrmException.ExtractPluginTraceFromSoapException(SoapException exception)
    at Microsoft.Crm.CrmException.ConvertPluginException(Exception originalException, Boolean isAsync, Boolean unwrapTargetInvocationException)
    at Microsoft.Crm.Workflow.ActivityHostBase.AddPluginTrace(Activity customActivity, Exception exception, ICommonWorkflowContext context)
    at Microsoft.Crm.Workflow.ActivityHostBase.OnWorkflowTerminated(WorkflowApplicationUnhandledExceptionEventArgs args, WorkflowApplication activityInstance, ICommonWorkflowContext context)
    at System.Activities.WorkflowApplication.UnhandledExceptionEventHandler.OnStage1Complete(IAsyncResult lastResult, WorkflowApplication instance, Exception exception, Activity source, String sourceInstanceId)
    at System.Activities.WorkflowApplication.UnhandledExceptionEventHandler.Run(WorkflowApplication instance, Exception exception, Activity exceptionSource, String exceptionSourceInstanceId)
    at System.Activities.WorkflowApplication.OnNotifyUnhandledException(Exception exception, Activity exceptionSource, String exceptionSourceInstanceId)

    do you have any idea where the problem is??



    1. Hi Fabian! I think you have to check the lines where report parameters are set

  6. Hi,

    Would this work for CRM online?

    1. Hi, Paul
      I hope that it's already possible to do this in CRM online if they released Q2 Service Update or in Q4 ??

  7. Thank you for this post. It is really helpful. I am trying out your code, but getting the following.

    The type or namespace name 'CrmNumber' could not be found (are you missing a using directive or an assembly reference?)

    I am referencing microsoft.crm.sdk.proxy. Not sure why i am getting the error. Any ideas?

    1. Have you find a resolution to this err? :/

    2. still error. already replace it with int. now the error is "'int' does not contain a definition for 'Value' and no extension method 'Value' accepting a first argument of type 'int' could be found "

  8. Can someone provide the updated code? i cannot get it to work?
    are we using a Service Reference or Web Reference

    1. use Web Reference like this http://your server name/ReportServer/ReportExecution2005.asmx

  9. Does this work for CRM 2011 online now?

  10. hi,
    could you tell me how can I use it in crm 2011?I'm new at crm

  11. For Online 2015 how to add web reference as ReportService???

  12. @jeeva:
    did u find solution?

  13. This was so helpful. Thanks for posting!

  14. using SendReport.ReportService;

    where do we find this

    1. SendReport in this example is namespace name (there will be yours) and ReportService is name of web refference which you have to add in your project (also give your name) ashttp://crmserver/ReportServer/ReportExecution2005.asmx

    2. by adding the webreference it is showing this error

      Value cannot be null.
      Parameter name: discoveryError & mexError

    3. send me please screenshot of your project, i need to see this error message