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)
        {
            try
            {

                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;

                try
                {
                result = rs.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out
                streamIDs);
                }

                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";
                collFromParty.Entities.Add(fromParty);

                EntityCollection collToParty = new EntityCollection();
                collToParty.EntityName = "systemuser";
                collToParty.Entities.Add(toParty);

                EntityCollection collccParty = new EntityCollection();
                collccParty.EntityName = "systemuser";
                collccParty.Entities.Add(ccParty);

                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);

                service.Create(attachment);

                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());
            }

        }

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

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

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

    }
}
 


 

27 comments:

  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.

    ReplyDelete
  2. where is the ReportService namespace?

    ReplyDelete
    Replies
    1. SendReport.ReportService;
      ReportService is web refernce

      Delete
  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.

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

    ReplyDelete
    Replies
    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";

      Delete
  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??

    thanks

    Fabian

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

      Delete
  6. Hi,

    Would this work for CRM online?

    ReplyDelete
    Replies
    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 ??
      http://gustafwesterlund.blogspot.com/2012/04/workflow-activities-in-crm-online.html

      Delete
  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?

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

      Delete
    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 "

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

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

      Delete
  9. Does this work for CRM 2011 online now?

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

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

    ReplyDelete
  12. @jeeva:
    did u find solution?

    ReplyDelete
  13. This was so helpful. Thanks for posting!

    ReplyDelete
  14. using SendReport.ReportService;

    where do we find this

    ReplyDelete
    Replies
    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

      Delete
    2. by adding the webreference it is showing this error

      Value cannot be null.
      Parameter name: discoveryError & mexError

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

      k.o.n.c.i.s@inbox.lv

      Delete