Today I will show you how we can put the Flow we created in the previous part into action.
You should complete the workflow to Generate a Word document from a template in this post before we can proceed. Our goal is to convert the Word document to a PDF document and attach it to a Note.
First, in your custom workflow activity project, create a new custom workflow with following code snippet. I’m not going to explain it as you can understand easily when you have a closer look. You just need to pay attention to the “ConvertWordToPdf” method where we send request to our Flow. I put some comments there also.
public class MyCustomWorkflowActivity : CodeActivity { protected override void Execute(CodeActivityContext executionContext) { ITracingService tracer = executionContext.GetExtension(); IWorkflowContext context = executionContext.GetExtension(); IOrganizationServiceFactory serviceFactory = executionContext.GetExtension(); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); try { Entity entity = (Entity)context.InputParameters["Target"]; // Get the last note with word attachment generated from the previous step var wordNote = GetLastWordNote(service, context.PrimaryEntityId); // send it to our Flow, convert it to pdf and attach to a note if (wordNote != null) { ConverToPdfNote(service, wordNote, context.PrimaryEntityId); } } catch (Exception e) { throw new InvalidPluginExecutionException(e.Message); } } private Entity GetLastWordNote(IOrganizationService service, Guid targetId) { QueryExpression query= new QueryExpression("annotation") { ColumnSet = new ColumnSet(true), Criteria = new FilterExpression() { Conditions = { new ConditionExpression() { AttributeName="isdocument", Operator = ConditionOperator.Equal, Values = { true } }, new ConditionExpression() { AttributeName = "objectid", Operator = ConditionOperator.Equal, Values = { targetId } } } }, Orders = { new OrderExpression() { AttributeName = "createdon", OrderType = OrderType.Descending } } }; // optional: filter for mimetype to make sure it is a word attachment var docFilter = query.Criteria.AddFilter(LogicalOperator.Or); docFilter.AddCondition("mimetype", ConditionOperator.Equal, "application/vnd.openxmlformats-officedocument.wordprocessingml.document"); docFilter.AddCondition("mimetype", ConditionOperator.Equal, "application/octet-stream"); var response = service.RetrieveMultiple(query); if (response.Entities.Count > 0) { return response.Entities.First(); } return null; } private void ConverToPdfNote(IOrganizationService service, Entity note, EntityReference targetRef) { var mime = note.Contains("mimetype") ? (string)note["mimetype"] : string.Empty; if (mime != "application/vnd.openxmlformats-officedocument.wordprocessingml.document" && mime != "application/octet-stream") { throw new InvalidPluginExecutionException("Source file is an invalid Word format"); } var fileName = note.Contains("filename") ? (string)note["filename"] : string.Empty; var noteData = note.Contains("documentbody") ? (string)note["documentbody"] : string.Empty; if (string.IsNullOrWhiteSpace(fileName) || string.IsNullOrWhiteSpace(noteData)) { throw new InvalidPluginExecutionException("Source file is invalid"); } try { // Send request to Flow var pdfData = ConvertWordToPdf(fileName, noteData); Entity pdfnote = new Entity("annotation"); pdfnote["filename"] = fileName + ".pdf"; pdfnote["documentbody"] = pdfData; pdfnote["mimetype"] = "application/pdf"; pdfnote["objectid"] = targetRef; service.Create(pdfnote); } catch (Exception ex) { throw; } } private static string ConvertWordToPdf(string filename, string base64word) { var result = string.Empty; var json = string.Format("{{'filename': '{0}', 'base64data': '{1}'}}", filename, base64word); // TODO: store api url somewhere else var apiurl = "https://prod-02.southeastasia.logic.azure.com:443/workflows/"; try { using (WebClientEx client = new WebClientEx()) { client.Timeout = 60000; client.Headers.Add(HttpRequestHeader.ContentType, "application/json"); client.Encoding = System.Text.Encoding.UTF8; result = client.UploadString(apiurl, json); } } catch (WebException exception) { string str = string.Empty; if (exception.Response != null) { using (StreamReader reader = new StreamReader(exception.Response.GetResponseStream())) { str = reader.ReadToEnd(); } exception.Response.Close(); } if (exception.Status == WebExceptionStatus.Timeout) { throw new InvalidPluginExecutionException("The timeout elapsed while attempting to issue the the PDF conversion request.", exception); } throw new InvalidPluginExecutionException(string.Format("A Web exception occurred while attempting to issue the PDF conversion request. {0}: {1}", exception.Message, str), exception); } catch { throw new InvalidPluginExecutionException("Failed to convert to PDF"); } return result; } } public class WebClientEx : WebClient { public int Timeout { get; set; } protected override WebRequest GetWebRequest(Uri address) { var request = (HttpWebRequest)base.GetWebRequest(address); request.Timeout = Timeout; // Keep-Alive set to true in the HTTP request header can cause delays upwards of 20+ seconds request.KeepAlive = false; return request; } }
Next, build and deploy the workflow to CRM.
Then, open CRM workflow to generate word document, and add a step to our custom workflow. I marked my workflow to be on-demand so I can test it easily with existing record.
And check out the result. A new PDF note is created.
That’s it. hope it helps!
P/S: if you have any suggestion regarding converting Word to PDF online or on-premise, please let me know. Cheers!
Thank you for this series. They helped me better understand the flows and how to interact with them.
LikeLike