In the below sample code, the report will actually be generated in two formats: Excel and PDF. These would then be attached to an e-mail specified at the workflow level. Make sure to visit Creating a Custom Workflow Activity in MS CRM 2011!
In this second article in a three part series, we’ll look at how to add an SSRS report as an attachment to an e-mail in a custom workflow in MSCRM 2011. In the below sample code, the report (in this case, a quote report) will actually be generated in two formats: Excel and PDF. These would then be attached to an e-mail specified at the workflow level. Make sure to visit Creating a Custom Workflow Activity in MS CRM 2011 to understand how to create custom workflow activities!
To implement:
- Register your compiled custom workflow activity DLL using the Plugin Registration Tool (see Creating a Custom Workflow Activity in MS CRM 2011).
- Create a new workflow process.
- Create an e-mail record.
- Add the attach quote custom workflow step (I called mine “Attach Quote”):

- Click on the step’s Set Properties.
- Set the e-mail reference to the e-mail record you created in step #3.
- Activate your workflow process.
namespace MyWorkflow
{
using System;
using System.Activities;
using System.Diagnostics;
using System.Web.Services.Protocols;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Workflow;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Crm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using WorkflowActivities.RSWebReference;
using Xrm;
public sealed class AttachQuote : CodeActivity
{
[Input("E-mail Reference")]
[ReferenceTarget(Email.EntityLogicalName)]
public InArgument<EntityReference> LookupEmail { get; set; }
protected override void Execute(CodeActivityContext executionContext)
{
try
{
// Create the tracing service
ITracingService tracingService = executionContext.GetExtension<ITracingService>();
// Create the context
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
// Create the Organization service
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
// Get the target entity from the context
Entity target = (Entity)service.Retrieve(Quote.EntityLogicalName, context.PrimaryEntityId, new ColumnSet(true));
// Prepare DataContext by using AutoGenerated cs file:
// CrmSvcUtil.exe /out:Xrm.cs /url:http<s>://<CRMSERVER>/XRMServices/2011/Organization.svc /domain:<DOMAIN> /username:<USERNAME> /password:<PASSWORD> /namespace:Xrm /serviceContextName:XrmDataContext
XrmDataContext datacontext = new XrmDataContext(service);
// Attach quote to email
AttachQuoteToEmail(service, target, LookupEmail.Get<EntityReference>(executionContext));
}
catch (SoapException ex)
{
// Add the SoapException message in event log
EventLog.WriteEntry("code error", "Error occured in " + ex.Detail.InnerText.ToString(), EventLogEntryType.Error);
}
catch (Exception exe)
{
// Add the GeneralException message in event log
EventLog.WriteEntry("code error", "Error occured in " + exe.InnerException.ToString(), EventLogEntryType.Error);
}
}
public static void AttachQuoteToEmail(IOrganizationService service, Entity quoteEntity, EntityReference emailRef)
{
byte[] result = null;
// Get email instance
Email emailInstance = new Email();
Entity emailEntity = service.Retrieve(Email.EntityLogicalName, emailRef.Id, new ColumnSet(true));
emailInstance.ActivityId = emailEntity.Id;
ReportExecutionService rs = new ReportExecutionService();
rs.Credentials = new System.Net.NetworkCredential("username", "password", "domain");
rs.Url = "http://localhost/ReportServer/ReportExecution2005.asmx";
string reportPath = "/<REPORT PATH>/Quote - Standard";
string historyID = null;
string devInfo = @"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";
ParameterValue[] parameters = new ParameterValue[1];
parameters[0] = new ParameterValue();
parameters[0].Name = "P1";
parameters[0].Value = string.Format("select [quote0].* from FilteredQuote as "quote0" WHERE QuoteId = '{0}'", quoteEntity.Id);
string encoding;
string mimeType;
string extension;
Warning[] warnings = 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[] formats = {
"PDF",
"Excel"
};
for (int i = 0; i < formats.Length; i++)
{
// Get data for report
try
{
result = rs.Render(formats[i], devInfo, out extension, out mimeType, out encoding, out warnings, out streamIDs);
}
catch (Exception err)
{
throw new Exception(err.Message.ToString());
}
// Create attachment for generated format
ActivityMimeAttachment attachment = new ActivityMimeAttachment();
attachment.Subject = "Report";
attachment.ObjectId = new EntityReference(Email.EntityLogicalName, emailInstance.Id);
attachment.ObjectTypeCode = emailInstance.LogicalName;
attachment.FileName = quoteEntity.Attributes["quotenumber"].ToString() + "." + extension;
attachment.Body = Convert.ToBase64String(result);
attachment.MimeType = mimeType;
attachment.AttachmentNumber = i;
service.Create(attachment);
}
service.Update(emailInstance);
}
}
}