Hi Andrew, code for one of the workflow activities below:
//
{
using System;
using System.Activities;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Workflow;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Messages;
using System.Linq;
using System.Xml;
using System.IO;
using CSkills.CRM.LevyGrant.ProcessBulkJobs;
using System.Net.Http;
//using log4net;
public sealed class ProcessAssessmentBulkMailing : CodeActivity
{
// Workflow inputs/outputs
[Input("Levy Year")]
[RequiredArgument]
[ReferenceTarget("cs_levyyear")]
public InArgument<EntityReference> LevyYearId { get; set; }
[Input("Bulk Mail Type")]
[RequiredArgument]
public InArgument<String> BulkMailType { get; set; }
[Input("Retrieve Query")]
[RequiredArgument]
public InArgument<String> RetrieveQuery { get; set; }
[Input("Return Date")]
[RequiredArgument]
public InArgument<DateTime> ReturnDate { get; set; }
[Input("Job Mode")]
[RequiredArgument]
public InArgument<Boolean> JobMode { get; set; }
[Output("Step Executed Successfully")]
public OutArgument<Boolean> IsWorkflowResultOk { get; set; }
[Output("Workflow Result Message")]
public OutArgument<string> WorkflowResultMessage { get; set; }
private ProcessBulkJobs.LevyReturnsUtils lrUtils = new CSkills.CRM.LevyGrant.ProcessBulkJobs.LevyReturnsUtils();
private ProcessBulkJobs.LevyReturnCommonObjects lrCommonObjects = new CSkills.CRM.LevyGrant.ProcessBulkJobs.LevyReturnCommonObjects();
//private static ILog log = ProcessBulkJobs.Log4NetWrapper.GetLog4Net(System.Reflection.MethodBase.GetCurrentMethod().GetType());
/// <summary>
/// Executes the workflow activity.
/// </summary>
/// <param name="executionContext">The execution context.</param>
protected override void Execute(CodeActivityContext executionContext)
{
ITracingService tracingService = executionContext.GetExtension<ITracingService>();
String workflowResultMessage = String.Empty;
XmlWriter writer = null;
XmlWriterSettings writersettings = new XmlWriterSettings();
writersettings.OmitXmlDeclaration = true;
writersettings.Indent = true;
//Creating memory stream for XML writer to store data
string fileName = "LevyAssessmentNotices";
MemoryStream stream = new MemoryStream();
stream.Position = 0;
tracingService.Trace("Just Entered...");
// Create the tracing service
if (tracingService == null)
{
throw new InvalidPluginExecutionException("Failed to retrieve tracing service.");
}
tracingService.Trace("Entered ProcessAssessmentBulkMailing.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("ProcessAssessmentBulkMailing.Execute(), Correlation Id: {0}, Initiating User: {1}",
context.CorrelationId,
context.InitiatingUserId);
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
Xrm.XrmServiceContext xrm = new Xrm.XrmServiceContext(service);
try
{
// TODO: Implement your custom Workflow business logic.
//string workflowResultMessage = string.Empty;
Boolean allInputsResolved = true;
// check we have the correct mailing type
if (BulkMailType.Get<String>(executionContext).ToString().Trim().ToLower() != "levy assessment notice bulk mailing")
{
throw new InvalidPluginExecutionException("Invalid bulk mailing type.");
}
// determine the output file path
//String outputFile = lrUtils.GetOutputFilePath("LevyAssessmentNotices");
//if (String.IsNullOrEmpty(outputFile))
//{
// throw new InvalidPluginExecutionException("Unable to determine the output file LevyAssessmentNotices.");
//}
lrCommonObjects.InitialiseValues();
// Retrieve the FetchXML from the User Query
// Xrm.XrmServiceContext xrm = new Xrm.XrmServiceContext(service);
// get the Levy year name
String levyYear = lrUtils.RetrieveLevyYear(xrm, LevyYearId.Get<EntityReference>(executionContext).Id);
// determine job mode
bool jobModeLive = JobMode.Get<Boolean>(executionContext);
//CR96 Fields
Xrm.cs_config configEmp = null;
var emailaddress = string.Empty;
var phonenumber = string.Empty;
// only create files if live mode
if (jobModeLive)
{
// create the output file
writer = XmlWriter.Create(stream, writersettings);
writer.WriteStartDocument();
writer.WriteStartElement("LevyAssessments");
}
// Check if User Cancelled the Job
if (!lrUtils.RetrieveCancelJob(context.PrimaryEntityId, xrm, ref workflowResultMessage, executionContext))
{
tracingService.Trace("Start Time : " + lrCommonObjects.DateStartTime);
tracingService.Trace("Retrieve Query : " + RetrieveQuery.Get<String>(executionContext));
tracingService.Trace("Levy Year Id : " + LevyYearId.Get<EntityReference>(executionContext).Id.ToString());
tracingService.Trace("Bulk Mail Type : " + BulkMailType.Get<String>(executionContext));
tracingService.Trace("Return Date : " + ReturnDate.Get<DateTime>(executionContext).ToLocalTime());
tracingService.Trace("Job Mode : " + JobMode.Get<Boolean>(executionContext));
var queryFetchXml = lrUtils.RetrieveSavedQueryFetchXml(xrm, RetrieveQuery.Get<String>(executionContext));
var configQueryFetchXml = lrUtils.RetrieveSavedQueryFetchXml(xrm,"Current Active Config Settings");
if (queryFetchXml != null)
{
tracingService.Trace("Retrieve Query exists");
tracingService.Trace("RetrieveQuery.FetchXml : " + queryFetchXml);
while (true)
{
var returnRegisteredEmployersCollection = lrUtils.GetRegisteredEmployersFromSavedQuery(queryFetchXml, service,
ref workflowResultMessage, lrCommonObjects.FetchCount, lrCommonObjects.PageNumber, xrm, executionContext);
var configurationCollection = lrUtils.GetConfigSettingsFromSavedQuery(configQueryFetchXml, service,
ref workflowResultMessage, lrCommonObjects.FetchCount, lrCommonObjects.PageNumber, xrm, executionContext);
if (configurationCollection != null)
{
foreach (var configEntity in configurationCollection.Entities)
{
configEmp = lrUtils.GetConfigSettings(configEntity.Attributes["cs_configid"].ToString(), xrm, ref workflowResultMessage, executionContext);
emailaddress = configEntity.Attributes["cs_emailaddress"].ToString();
phonenumber = configEntity.Attributes["cs_phonenumber"].ToString();
}
}
if (returnRegisteredEmployersCollection != null)
{
if (returnRegisteredEmployersCollection.Entities.Count > 0)
{
lrCommonObjects.TotalCount = returnRegisteredEmployersCollection.Entities.Count;
tracingService.Trace("Total Registered Employers : " + lrCommonObjects.TotalCount);
foreach (var entity in returnRegisteredEmployersCollection.Entities)
{
// Get the registered employer data that is required
Xrm.Account regEmp = lrUtils.GetRegisteredEmployerData(entity.Attributes["accountid"].ToString(), xrm, ref workflowResultMessage, executionContext);
// Get the levy return
var levyReturn = lrUtils.GetLevyReturnForAssessments(entity.Attributes["accountid"].ToString(),
LevyYearId.Get<EntityReference>(executionContext).Id.ToString(), xrm, ref workflowResultMessage, executionContext);
EntityCollection assessments = null;
// Get the assessments
if (levyReturn != null && levyReturn.Attributes.Contains("cs_levyreturnid"))
{
assessments = lrUtils.GetAssessments(entity.Attributes["accountid"].ToString(), levyReturn.Attributes["cs_levyreturnid"].ToString(), xrm, ref workflowResultMessage, executionContext);
}
bool recordOK = true;
// BUG #836 19/06/12 AJG
// Check if the Bulk Assessment Block flag is set
if (lrUtils.CheckIfBulkAssessmentBlock(regEmp, ref workflowResultMessage))
{
// block is set so record error and do not process
ErrorWithRecord(entity.Attributes["cs_registrationnumber"].ToString(), "The Bulk Assessment Block flag is Set", executionContext);
recordOK = false;
}
else
{
// check the levy return is present
if (levyReturn == null || !levyReturn.Attributes.Contains("cs_name"))
{
// No Levy Return Exists
ErrorWithRecord(entity.Attributes["cs_registrationnumber"].ToString(), "No Levy Return Exists for the given Levy Year", executionContext);
recordOK = false;
}
else
{
// Check the levy return status
if (!levyReturn.Attributes.Contains("statuscode") || ((Microsoft.Xrm.Sdk.OptionSetValue)(levyReturn.Attributes["statuscode"])).Value != ProcessBulkJobs.LevyReturn.StatusCode.ASSESSED)
{
// wrong status code - ignore record, but do not report it
recordOK = false;
}
}
}
if (recordOK)
{
// Check the assessment name is present - this is now the only field used from the assessment (for the letter subject)
if (assessments == null || assessments.Entities.Count == 0 || !assessments.Entities[0].Contains("cs_name"))
{
// should not get to here as the levy return status is assessed, but put in just in case
// assessment name not present
ErrorWithRecord(entity.Attributes["cs_registrationnumber"].ToString(), "There is no Assessment or the assessment name is not set", executionContext);
recordOK = false;
}
}
//// Check the Bulk Assessment Block flag is set
//if (recordOK && lrUtils.CheckIfBulkAssessmentBlock(regEmp, ref workflowResultMessage))
//{
// if (((Microsoft.Xrm.Sdk.OptionSetValue)assessments.Entities[0].Attributes["cs_assessmenttype"]).Value != ProcessBulkJobs.AssessmentType.BONAFIDE)
// {
// // assessment set and not BonaFide
// ErrorWithRecord(entity.Attributes["name"].ToString(), "Bulk Assessment Block is Set and the assessment type is not Bona Fide");
// recordOK = false;
// }
//}
if (recordOK)
{
// record Ok, so can create the letter activity
if (lrUtils.CreateLetterActivity(new Guid(entity.Attributes["accountid"].ToString()),
"Levy Assessment " + assessments.Entities[0].Attributes["cs_name"].ToString(), jobModeLive, service, ref workflowResultMessage, executionContext))
{
tracingService.Trace(entity.Attributes["cs_registrationnumber"].ToString() + " : " + "Letter Activity created successfully");
// Write the record to the output file
//lrUtils.WriteAssessmentFile(entity.Attributes["accountid"].ToString(), levyYear, lrCommonObjects.SharedServicesPhoneNumber,
// lrCommonObjects.SharedServicesEmailAddress, writer, regEmp, (Xrm.cs_levyreturn)levyReturn,
// jobModeLive, ReturnDate.Get<DateTime>(executionContext), xrm, ref workflowResultMessage);
//CR96
lrUtils.WriteAssessmentFile(entity.Attributes["accountid"].ToString(), levyYear, phonenumber, emailaddress,
writer, regEmp, (Xrm.cs_levyreturn)levyReturn,jobModeLive, ReturnDate.Get<DateTime>(executionContext),
xrm, ref workflowResultMessage, service, executionContext);
tracingService.Trace(entity.Attributes["cs_registrationnumber"].ToString() + " : " + "Added to output file");
lrCommonObjects.SuccessCount = lrCommonObjects.SuccessCount + 1;
}
else
{
allInputsResolved = false;
lrCommonObjects.ErrorCount = lrCommonObjects.ErrorCount + 1;
tracingService.Trace(entity.Attributes["cs_registrationnumber"].ToString() + " : " + "Error while creating activity/updating file, Check the stacktrace on server logs");
lrCommonObjects.strErrors += lrUtils.AppendLine(entity.Attributes["cs_registrationnumber"].ToString() + " : " + "Check the stacktrace on server logs");
}
}
}
lrCommonObjects.DateFinishTime = DateTime.Now;
lrCommonObjects.strMessages += lrUtils.AppendLine(lrCommonObjects.DateStartTime + " " + "Job Started");
lrCommonObjects.strMessages += lrUtils.AppendLine(lrCommonObjects.DateFinishTime + " " + "Job Finished for " + lrCommonObjects.SuccessCount + " " + "records");
lrCommonObjects.strMessages += lrUtils.AppendLine("--");
lrCommonObjects.strMessages += lrUtils.AppendLine("Total records per page : " + lrCommonObjects.TotalCount);
lrCommonObjects.strMessages += lrUtils.AppendLine(lrCommonObjects.SuccessCount + " Records processed");
lrCommonObjects.strMessages += lrUtils.AppendLine(lrCommonObjects.ErrorCount + " Errors");
lrCommonObjects.strMessages += lrUtils.AppendLine("--");
//lrCommonObjects.strMessages += lrUtils.AppendLine("Output File : " + outputFile);
// Check for morerecords, if it returns 1.
if (returnRegisteredEmployersCollection.MoreRecords)
{
// Retrieve Cancel Job value from Recurring Job
if (!lrUtils.RetrieveCancelJob(context.PrimaryEntityId, xrm, ref workflowResultMessage, executionContext))
{
tracingService.Trace("Update Recurring Job");
// Update Recurring Job
lrUtils.UpdateRecurringJob(lrCommonObjects.SuccessCount, lrCommonObjects.ErrorCount, lrCommonObjects.strMessages,
lrCommonObjects.strErrors, context.PrimaryEntityId, service, ref workflowResultMessage, executionContext);
// Increment the page number to retrieve the next page.
lrCommonObjects.PageNumber++;
}
else
{
tracingService.Trace("User Cancelled the Job");
lrCommonObjects.strMessages += lrUtils.AppendLine("User Cancelled the Job");
// Update Recurring Job
lrUtils.UpdateRecurringJob(lrCommonObjects.SuccessCount, lrCommonObjects.ErrorCount, lrCommonObjects.strMessages,
lrCommonObjects.strErrors, context.PrimaryEntityId, service, ref workflowResultMessage, executionContext);
break;
}
}
else
{
lrUtils.UpdateRecurringJob(lrCommonObjects.SuccessCount, lrCommonObjects.ErrorCount, lrCommonObjects.strMessages,
lrCommonObjects.strErrors, context.PrimaryEntityId, service, ref workflowResultMessage, executionContext);
// If no more records in the result nodes, exit the loop.
break;
}
}
else
{
tracingService.Trace("No records found for the System Query");
// Update Message with no records found
lrCommonObjects.strMessages += lrUtils.AppendLine("No records found for the System Query");
lrUtils.UpdateRecurringJob(lrCommonObjects.SuccessCount, lrCommonObjects.ErrorCount, lrCommonObjects.strMessages,
lrCommonObjects.strErrors, context.PrimaryEntityId, service, ref workflowResultMessage, executionContext);
}
}
else
{
tracingService.Trace("Error while converting FetchXML to QueryExpression");
// Update Message with no records found
lrCommonObjects.strMessages += lrUtils.AppendLine("Error while converting FetchXML to QueryExpression");
lrUtils.UpdateRecurringJob(lrCommonObjects.SuccessCount, lrCommonObjects.ErrorCount, lrCommonObjects.strMessages,
lrCommonObjects.strErrors, context.PrimaryEntityId, service, ref workflowResultMessage, executionContext);
}
}
}
if (lrCommonObjects.MaxErrorCount == ProcessBulkJobs.LevyReturnCommonObjects.MAX_ERROR_COUNT)
{
lrCommonObjects.strErrors += lrUtils.AppendLine("There are more than " + ProcessBulkJobs.LevyReturnCommonObjects.MAX_ERROR_COUNT.ToString() + " errors, please check stacktrace on server logs");
lrUtils.UpdateRecurringJob(lrCommonObjects.SuccessCount, lrCommonObjects.ErrorCount, lrCommonObjects.strMessages,
lrCommonObjects.strErrors, context.PrimaryEntityId, service, ref workflowResultMessage, executionContext);
}
}
else
{
tracingService.Trace("User Cancelled the Job");
lrCommonObjects.strMessages += lrUtils.AppendLine("User Cancelled the Job");
// Update Recurring Job
lrUtils.UpdateRecurringJob(lrCommonObjects.SuccessCount, lrCommonObjects.ErrorCount, lrCommonObjects.strMessages,
lrCommonObjects.strErrors, context.PrimaryEntityId, service, ref workflowResultMessage, executionContext);
}
// Set workflow output messages
WorkflowResultMessage.Set(executionContext, workflowResultMessage);
IsWorkflowResultOk.Set(executionContext, allInputsResolved);
}
catch (FaultException<OrganizationServiceFault> e)
{
//log.Error("ProcessAssessmentBulkMailing --> " + e);
workflowResultMessage = lrUtils.AppendLine("ProcessAssessmentBulkMailing --> " + e.StackTrace);
// Set workflow output messages
WorkflowResultMessage.Set(executionContext, workflowResultMessage);
// Set Workflow result
IsWorkflowResultOk.Set(executionContext, false);
tracingService.Trace("Exception: {0}", e.ToString());
// Handle the exception.
throw;
}
finally
{
if (writer != null)
{
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Close();
string sConnectionString = "";
string sContainer = "";
string WebHookUrl = "";
var configQueryFetchXml = lrUtils.RetrieveSavedQueryFetchXml(xrm, "Current Active Config Settings");
var configurationCollection = lrUtils.GetConfigSettingsFromSavedQuery(configQueryFetchXml, service,
ref workflowResultMessage, lrCommonObjects.FetchCount, lrCommonObjects.PageNumber, xrm, executionContext);
if (configurationCollection != null)
{
foreach (var configEntity in configurationCollection.Entities)
{
sConnectionString = configEntity.Attributes["fuj_azurestorageconnectionstring"].ToString();
sContainer = configEntity.Attributes["fuj_containername"].ToString();
WebHookUrl = configEntity.Attributes["fuj_logicapphttpwebhook"].ToString();
}
}
stream.Seek(0, SeekOrigin.Begin);
UploadAzureBlob.UploadStream(sConnectionString, sContainer, stream, fileName);
stream.Dispose();
stream.Close();
//using (HttpClient httpClient = new HttpClient())
//{
// // var retryPolicy = Policy.Handle<HttpRequestException>().WaitAndRetry(5, attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)));
// var httpResponseMessage = retryPolicy.Execute(() => httpClient.GetAsync(WebHookUrl).Result);
//}
}
}
tracingService.Trace("Exiting ProcessAssessmentBulkMailing.Execute(), Correlation Id: {0}", context.CorrelationId);
}
/// <summary>
/// Sets up the error detail for the record
/// </summary>
/// <param name="name"></param>
/// <param name="errorMsg"></param>
private void ErrorWithRecord(String name, String errorMsg, CodeActivityContext executionContext)
{
ITracingService tracingService = (ITracingService)executionContext.GetExtension<ITracingService>();
tracingService.Trace(name + " : " + errorMsg);
lrCommonObjects.ErrorCount = lrCommonObjects.ErrorCount + 1;
if (lrCommonObjects.ErrorCount > ProcessBulkJobs.LevyReturnCommonObjects.MAX_ERROR_COUNT)
{
lrCommonObjects.MaxErrorCount = ProcessBulkJobs.LevyReturnCommonObjects.MAX_ERROR_COUNT;
}
else
{
lrCommonObjects.strErrors += lrUtils.AppendLine(name + " : " + errorMsg);
}
}
}
}