Answered by:
Urgent help needed understanding and correcting a custom workflow

Question
-
CRM2013
Our company retrieves multiple reports on a daily basis in xml format, for our customers which are imported into CRM entities to produce readable reports with SSRS. Currently we are manually creating PDF files and manually emailing them to customers. I have been trying to create a custom workflow that will automate the task when a record is created. In the instance below, the xml file is imported into the entity along with supporting data and lookups. I have been trying to follow several examples but am running into several problems.
Entity – “new_bacsddicreports”
With the code below, I get the following error ( at the bottom ) when running the workflow. I am currently logged onto CRA system Administrator
The entity has a lookup to account (Account – Name, new_bacsddicreport lookup field - new_licence)
This is a test report, but I would like to progress this to looking up the email address from Account (new_ReportsEmail & new_ReportsemailCC)
Once I can get to that stage, I should be able to work out how to pass a parameter to the real report
Thank you for any help in advance
Current Workflow code (I have masked the passwords etc)
// <copyright file="SendReports.cs" company="">
// Copyright (c) 2014 All Rights Reserved
// </copyright>
// <author></author>
// <date>10/9/2014 3:04:48 PM</date>
// <summary>Implements the SendReports Workflow Activity.</summary>
namespace FMAutoReports.Workflow
{
using System;
using System.Activities;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Workflow;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Crm.Sdk.Messages;
using FMAutoReports.Workflow.ReportService;
public sealed class SendReports : CodeActivity
{
/// <summary>
/// Executes the workflow activity.
/// </summary>
/// <param name="executionContext">The execution context.</param>
protected override void Execute(CodeActivityContext executionContext)
{
// Create the tracing service
ITracingService tracingService = executionContext.GetExtension<ITracingService>();
if (tracingService == null)
{
throw new InvalidPluginExecutionException("Failed to retrieve tracing service.");
}
tracingService.Trace("Entered SendReports.Execute(), Activity Instance Id: {0}, Workflow Instance Id: {1}",
executionContext.ActivityInstanceId,
executionContext.WorkflowInstanceId);
// Create the context
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
if (context == null)
{
throw new InvalidPluginExecutionException("Failed to retrieve workflow context.");
}
tracingService.Trace("SendReports.Execute(), Correlation Id: {0}, Initiating User: {1}",
context.CorrelationId,
context.InitiatingUserId);
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
try
{
// TODO: Implement your custom Workflow business logic.
// MY CODE
Guid new_bacsddicreportsId = context.PrimaryEntityId;
byte[] result = null;
FMAutoReports.Workflow.ReportService.ReportExecutionService rs = new ReportExecutionService();
// Credential to connect with CRM
rs.Credentials = new System.Net.NetworkCredential("xxxx", "xxxx", "xxx");
// Setting the URL of the Reporting Server
rs.Url = "http://xxx.xxx.xx/ReportServer/ReportExecution2005.asmx";
string reportPath = "/xxxxx_MSCRM/Facilities Management ARUDD Reconocile";
// Specify the report path from the reporting server
// Note: To get the report name, report must be published for the external use.
// To do this edit the report from CRM and publish it for external use.
// After publishing it for external use report name will be visible in the reporting server instead of the report id.
string format = "PDF";
string historyID = null;
string devInfo = @"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";
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);
String SessionId = rs.ExecutionHeaderValue.ExecutionID;
result = rs.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
//Create email activity
Entity email = new Entity();
email.LogicalName = "email";
email.Attributes.Add("regardingobjectid", new EntityReference("new_bacsddicreports", new_bacsddicreportsId));
//Creating EntityReference for from, to and cc. Need to be changed according to your requirement
// EntityReference from = new EntityReference("systemuser", senderUserId);
// EntityReference to = new EntityReference("account", );
// EntityReference cc = new EntityReference("contact", recieverCCUserId);
// EntityReference from = new EntityReference("systemuser", senderUserId);
// EntityReference to = new EntityReference("systemuser",recieverUserId);
//Creating party list
// Adding from, to and cc to the email
email.Attributes.Add("from", "me@home.co.uk");
email.Attributes.Add("to", "him@home.co.uk");
email.Attributes.Add("cc", "her@home.co.uk");
email.Attributes.Add("subject", "TEST SENDING PDF FROM CRM ");
email.Attributes.Add("description", "This is a test to email a report direct from crm when a record is created");
Guid emailID = service.Create(email); // Create the email
// Attaching Pdf Report
int NextActorID = new int();
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", "Test Report.pdf");
attachment.Attributes.Add("body", Convert.ToBase64String(result));
attachment.Attributes.Add("filesize", Convert.ToInt32(result.Length.ToString()));
attachment.Attributes.Add("mimetype", "text/plain");
attachment.Attributes.Add("attachmentnumber", NextActorID);
attachment.Attributes.Add("objectid", new EntityReference("email", new Guid(email.Id.ToString())));
attachment.Attributes.Add("objecttypecode", objecttypecode);
service.Create(attachment); //Create the attachment
// Sending email
SendEmailRequest reqSendEmail = new SendEmailRequest();
reqSendEmail.EmailId = emailID;
reqSendEmail.TrackingToken = "";
reqSendEmail.IssueSend = true;
SendEmailResponse res = (SendEmailResponse)service.Execute(reqSendEmail);
// END MY CODE
}
catch (FaultException<OrganizationServiceFault> e)
{
tracingService.Trace("Exception: {0}", e.ToString());
// Handle the exception.
throw;
}
tracingService.Trace("Exiting SendReports.Execute(), Correlation Id: {0}", context.CorrelationId);
}
}
}
Current error when running the workflow
Plugin Trace:
[FMAutoReports.Workflow: FMAutoReports.Workflow.SendReports]
[BACS Reports: ARUDD Listing]
Entered SendReports.Execute(), Activity Instance Id: 6, Workflow Instance Id: 6ccb1b04-533a-4655-a121-71a49e81b025
SendReports.Execute(), Correlation Id: 773cbd84-8542-4a9b-b86f-a6bef6d59385, Initiating User: 68413345-e5b9-e311-80b8-00155d04fa2d
Exception: System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]: The e-mail must have at least one recipient before it can be sent (Fault Detail is equal to Microsoft.Xrm.Sdk.OrganizationServiceFault).
Error Message:
Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: The e-mail must have at least one recipient before it can be sentDetail:
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
<ErrorCode>-2147218684</ErrorCode>
<ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
<Message>The e-mail must have at least one recipient before it can be sent</Message>
<Timestamp>2014-10-09T16:29:08.7600823Z</Timestamp>
<InnerFault>
<ErrorCode>-2147218684</ErrorCode>
<ErrorDetails xmlns:d3p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
<Message>The e-mail must have at least one recipient before it can be sent</Message>
<Timestamp>2014-10-09T16:29:08.7600823Z</Timestamp>
<InnerFault i:nil="true" />
<TraceText i:nil="true" />
</InnerFault>
<TraceText>[FMAutoReports.Workflow: FMAutoReports.Workflow.SendReports]
[BACS Reports: ARUDD Listing]
Entered SendReports.Execute(), Activity Instance Id: 6, Workflow Instance Id: 6ccb1b04-533a-4655-a121-71a49e81b025
SendReports.Execute(), Correlation Id: 773cbd84-8542-4a9b-b86f-a6bef6d59385, Initiating User: 68413345-e5b9-e311-80b8-00155d04fa2d
Exception: System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]: The e-mail must have at least one recipient before it can be sent (Fault Detail is equal to Microsoft.Xrm.Sdk.OrganizationServiceFault).</TraceText>
</OrganizationServiceFault>
at Microsoft.Crm.Extensibility.OrganizationSdkServiceInternal.Execute(OrganizationRequest request, CorrelationToken correlationToken, CallerOriginToken callerOriginToken, WebServiceType serviceType, Boolean checkAdminMode)
at Microsoft.Crm.Extensibility.InprocessServiceProxy.ExecuteCore(OrganizationRequest request)
at FMAutoReports.Workflow.SendReports.Execute(CodeActivityContext executionContext)
at System.Activities.CodeActivity.InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager)
at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)
Dont ask me .. i dont know
Thursday, October 9, 2014 5:47 PM
Answers
-
try this to send email and let us know if it's working.
http://worldofdynamics.blogspot.com.au/2012/04/dynamics-crm-2011-c-code-for-sending.html
- Marked as answer by Pete Newman Tuesday, January 13, 2015 10:09 PM
Saturday, October 11, 2014 10:44 PM
All replies
-
Hi Pete,
the from, to and cc attributes in an email entity are an array of ActivityParty Entities.
See the following code (sorry, just copied from VB.NET):
Dim party As New Entity("activityparty") party("partyid") = rcpt.ToEntityReference() Dim recipient As New EntityCollection({party}) mail("to") = recipient
rcpt is an Entity (account or contact) here. If you just have an email address, then use the addressused attribute of the activityparty instead of partyid.
You can also have a look here: http://msdn.microsoft.com/en-us/library/hh210217.aspx
HTH
Frank
- Edited by Frank Bursitzke Friday, October 10, 2014 11:54 AM
Friday, October 10, 2014 11:51 AM -
Hello Pete,
The error message is "The e-mail must have at least one recipient before it can be sent". I am not sure if you can declare
email.Attributes.Add("to", "him@home.co.uk");
a combination of
EntityReference from = new EntityReference("systemuser", senderUserId); EntityReference to = new EntityReference("account", accoutID?????); EntityReference cc = new EntityReference("contact", recieverCCUserId);
And approximatly
// Create the 'From:' activity party for the email ActivityParty fromParty = new ActivityParty { PartyId = new EntityReference(SystemUser.EntityLogicalName, _userId) }; // Create the 'To:' activity party for the email ActivityParty toParty = new ActivityParty { PartyId = new EntityReference(Contact.EntityLogicalName, _contactId) }; Console.WriteLine("Created activity parties."); // Create an e-mail message. Email email = new Email { To = new ActivityParty[] { toParty }, From = new ActivityParty[] { fromParty }, Subject = "SDK Sample e-mail", Description = "SDK Sample for SendEmail Message.", DirectionCode = true };
as shown in http://msdn.microsoft.com/en-us/library/hh210217.aspx
What i wish to highlight is that activityparty (from, to, cc) etc is of type activity type array. you got to fix this before the email will get processed,
Cheers,
Jithesh
Friday, October 10, 2014 11:59 AM -
Add the input parameter just at the end as
[RequiredArgument] [Input("Sender")] [ReferenceTarget("systemuser")] public InArgument<EntityReference> Sender { get; set; } [RequiredArgument] [Input("Recipient")] [ReferenceTarget("account")] public InArgument<EntityReference> Recipient { get; set; }
and use this input parameter in code as below
Guid senderUserId = Sender.Get<EntityReference>(executionContext).Id; Guid recieverUserId = Recipient.Get<EntityReference>(executionContext).Id; EntityReference from = new EntityReference("systemuser", senderUserId); EntityReference to = new EntityReference("account", recieverUserId); //Creating party list Entity fromParty = new Entity("activityparty"); fromParty.Attributes.Add("partyid", from); Entity toParty = new Entity("activityparty"); toParty.Attributes.Add("partyid", to); EntityCollection collFromParty = new EntityCollection(); collFromParty.EntityName = "systemuser"; collFromParty.Entities.Add(fromParty); EntityCollection collToParty = new EntityCollection(); collToParty.EntityName = "account"; collToParty.Entities.Add(toParty);
Muhammad Sohail
- Edited by sohail450 Friday, October 10, 2014 12:25 PM
Friday, October 10, 2014 12:21 PM -
HI,
Thank you for your help, although I am still struggling trying to get my head around this.
Please could you show an example,
The entity that the record is being added to (new_bacsddicreports) has a lookup (new_licence) to the accounts entity. The Accounts entity has 2 custom fields Reports Email and Reports Email CC
I cannot work out how to adapt your sample so that when I add a record in the new_bacsddicreport that the email is sent out to the email address in the accounts record ie
in new_bacsddicreports I add a record that has a lookup to account for customer 123456. Customer 123456 has a new_reportsemail field value of Him@home.co.uk and a new_reportsemailcc value of her@home.co.uk
thank you in advance for your help
Dont ask me .. i dont know
- Edited by Pete Newman Saturday, October 11, 2014 5:50 PM
Saturday, October 11, 2014 5:46 PM -
try this to send email and let us know if it's working.
http://worldofdynamics.blogspot.com.au/2012/04/dynamics-crm-2011-c-code-for-sending.html
- Marked as answer by Pete Newman Tuesday, January 13, 2015 10:09 PM
Saturday, October 11, 2014 10:44 PM