User Review
( votes)Just being customer-centric isn’t any added value that an organization has to offer anymore. It is a quintessential feature that underlines the ideals of a company. It has been proven that it is cost-effective to retain old customers and one of the best ways of doing that is taking care of them. This could mean going the extra mile, observing their consumerist (sans the ideology) behavior, predicting their requirements before they even narrate.
Now in a parallel world would require a mind-reader or a hypnotist but thank God for Microsoft Dynamics 365, you do not have to venture far.
Microsoft is like that magician who keeps on pulling out a trail of colorful kerchiefs from his hat. For a five-year-old, this is the most fascinating act but for us adults, we tend to look up his sleeve. And the sleeve doesn’t seem to disappoint either.
In 2001, Microsoft with the acquisition of I Communicate had stepped into the world of CRM and paved the path for revolutionizing the most sought-after sector of any business. Fast forward to 2018, Dynamics 365 was released combining ERP and CRM applications.
So why do we have so many organizations employing this CRM application? The reasons are plain and plenty. It is easier, flexible, scalable. With this, a company can have a unified system and the users do not have to shuffle between systems. This essentially saves time and money. All the teams, sales, marketing, service, and delivery can access the same system at one go, without the issue of restricted access.
Now when companies use CRM software, they do it to make their business lives a little less difficult. I would like to take the example of an entertainment company when talking about ease of business.
Usually, with emails that are sent to clients, the attachments must be static in nature. Such as standard boilerplate, terms and conditions documents. These kinds of documents do not need to be altered. As such, attaching and sending isn’t too much of a hassle.
However, when such a company requests for dynamic documents such as payment receipts etc. to be sent out, then it becomes the job of the developer to assist the client with the request. Although, sending varied documents isn’t a precondition that Microsoft had insisted upon, but the CRM system is scalable and can be tailormade as per the client’s requirement.
In our case, for the entertainment company, a specific code had to be written. Let’s visit some of the points that had to be covered while taking care of the request.
Prerequisite – The report needs to be created already in the CRM Organization and we need to have the report name and report guid.
Implementation stage:
- Creating the workflow and mention the triggering action.
- Creating the email body – mentioning the sender and receiver. Entering the subject and body of the email.
- Open Visual Studio and create a web reference with the report server name. example for report server name –
http://reportssrs-01/Reportserver/ReportExecution2005.asmx
- Now create a custom workflow with the following code:
1) using System; 2) using System.Linq; 3) using System.Text; 4) using System.Threading.Tasks; 5) using Microsoft.Xrm.Sdk.Workflow; 6) using Microsoft.Xrm.Sdk; 7) using Microsoft.Xrm.Sdk.Query; 8) using System.Activities; 9) using Microsoft.Xrm.Sdk.Client; 10) using System.Web.Services.Protocols; 11) using Microsoft.Crm.Sdk.Messages; 12) using System.Net; 13) 14) namespace customNamespace 15) { 16) //4077,(Contract) //4182, 17) ////http://rich-cent01/reportserver/ReportService2010.asmx?wsdl 18) public class AttachContractToEmail :CodeActivity 19) { 20) const string ReportPathFromSettings = “Report Path”; 21) const string ReportServerFromSettings = “Report Server”; 22) 23) [Input(“E-Mail”)] 24) [ReferenceTarget(“email”)] 25) 26) public InArgument<EntityReference> Email { get; set; } 27) 28) [Input(“inputParameterNeededForReport”)] 29) [ReferenceTarget(“inputparameterneededforreport “)] 30) public InArgument<string>inputParameterNeededForReport{ get; set; } 31) 32) 33) protected override void Execute(CodeActivityContextexecutionContext) 34) { 35) IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>(); 36) IOrganizationServiceFactoryservicefactory = executionContext.GetExtension<IOrganizationServiceFactory>(); 37) IOrganizationService _service = servicefactory.CreateOrganizationService(context.UserId); 38) 39) //Sample guid of contract : 4AE5200F-1000-E611-80C5-005056AA8521 40) string test = inputparameterneededforreport.Get(executionContext); 41) Entity attachment = new Entity(“activitymimeattachment”); 42) byte[] reportresult; 43) DateTimestartDate = DateTime.Now.AddMonths(-15); 44) DateTimeendDate = DateTime.Now; 45) if (test != null) 46) { 47) ParameterValue[] parameters = new ParameterValue[1]; 48) parameters[0] = new ParameterValue(); 49) parameters[0].Name = “QuoteId”; 50) parameters[0].Value = string.Format(test); 51) 52) var reportServer = //reportServerNameGoesHere 53) //example for report server name – http://reportssrs-01/Reportserver/ReportExecution2005.asmx 54) CommonMethodsrg = new CommonMethods(reportServer, new NetworkCredential(userid, password, domain)); 55) reportresult = rg.Render(reportPathGoesHere, FormatType.PDF, parameters); 56) 57) attachment[“objectid”] = Email.Get<EntityReference>(executionContext); 58) attachment[“objecttypecode”] = “email”; 59) attachment[“filename”] = //fileNameGoesHere; 60) attachment[“subject”] = //subjectgoeshere; 61) attachment[“body”] = System.Convert.ToBase64String(reportresult); 62) } 63) 64) 65) 66) 67) 68) try 69) { 70) _service.Create(attachment); 71) } 72) catch (Exception ex) 73) { 74) throw new Exception(string.Format(“Error creating attachment – {0}”, ex.Message)); 75) } 76) 77) try 78) { 79) _service.Execute(new SendEmailRequest() 80) { 81) EmailId = Email.Get<EntityReference>(executionContext).Id, 82) IssueSend = true, 83) TrackingToken = string.Empty 84) }); 85) } 86) catch (Exception ex) 87) { 88) throw new Exception(string.Format(“Error sending email – {0}”, ex.Message)); 89) } 90) } 91) } 92) } 93) 94) 95) 96) internal CommonMethods(string ServiceUrl, ICredentials credentials) 97) { 98) if (string.IsNullOrEmpty(ServiceUrl)) 99) throw new Exception(“Parameter ServiceUrl has to contain value”); 100) 101) if (credentials == null) 102) throw new Exception(“Parameter Credentials has to contain value”); 103) 104) _reportexecutionservice = new ReportExecutionService() 105) { 106) Credentials = credentials, 107) Url = ServiceUrl 108) }; 109) } 110) 111) 112) internal byte[] Render(string Report, FormatTypeformattype) 113) { 114) return this.Render(Report, formattype, new ParameterValue[] { }); 115) } 116) 117) internal byte[] Render(string Report, FormatTypeformattype, ParameterValue[] parameters) 118) { 119) byte[] result = null; 120) string format = GetFormatType(formattype); 121) string historyID = null; 122) string devInfo = @”<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>”; 123) string encoding; 124) string mimeType; 125) string extension; 126) Warning[] warnings = null; 127) string[] streamIDs = null; 128) 129) try 130) { 131) ExecutionInfoexecInfo = new ExecutionInfo(); 132) ExecutionHeaderexecHeader = new ExecutionHeader(); 133) _reportexecutionservice.ExecutionHeaderValue = execHeader; 134) execInfo = _reportexecutionservice.LoadReport(Report, historyID); 135) _reportexecutionservice.SetExecutionParameters(parameters, “en-us”); 136) result = _reportexecutionservice.Render(format, devInfo, out extension, 137) out mimeType, out encoding, out warnings, out streamIDs); 138) } 139) catch (Exception ex) 140) { 141) if (ex is SoapException) 142) { 143) SoapExceptionsexc = ex as SoapException; 144) throw new Exception(string.Format(“Error generating report – {0}”, sexc.Detail.InnerText)); 145) } 146) else 147) { 148) throw new Exception(string.Format(“Error generating report – {0}”, ex.Message)); 149) } 150) } 151) 152) return result; 153) } 154) 155) private string GetFormatType(FormatTypeformattype) 156) { 157) switch (formattype) 158) { 159) case FormatType.XML: 160) case FormatType.CSV: 161) case FormatType.IMAGE: 162) case FormatType.PDF: 163) case FormatType.MHTML: 164) case FormatType.EXCEL: 165) case FormatType.Word: 166) return formattype.ToString(); 167) case FormatType.HTML40: 168) return “HTML4.0”; 169) case FormatType.HTML32: 170) return “HTML3.2”; 171) default: 172) throw new Exception(string.Format(“Rendering type {0} is not available”, formattype)); 173) } 174) } 175) 176) 177) } 178) 179) internal enumFormatType 180) { 181) XML, CSV, IMAGE, PDF, HTML40, HTML32, MHTML, EXCEL, Word 182) }
|
- Deploying the custom workflow.
- Once the custom workflow has been deployed, we need to call the custom workflow inside the main workflow. To do it, click on add step and find the custom workflow which has just been deployed.
- Once the custom workflow has been called, you need to declare the input parameters for the workflow. The sample code has been written with one input parameter. You can modify the code to accept more input parameters.
I would like to reiterate, that one of the primary reasons that Dynamics 365 has gained leverage is because of its scalability. The future of CRM is more than maintaining customer relationships. It is the future of any business. With an application like Dynamics 365, Microsoft has revolutionized the whole industry. Now entrepreneurs don’t just yearn for gaining more customers but strive to find applied business intelligence to retain the old ones as well.
It’s fascinating to witness this kind of radical change brought to the genre of customer relationships by Microsoft. All we can do is wait with bated breath for the next revolution. And we know it’s not going to be too far.
We at AhaApps employ Microsoft’s applications to help our clients in making their business agile and seamless. To know more about our exclusive services, do contact us today
The post Attaching an SSRS Report in Dynamics 365 appeared first on CRM Software Blog | Dynamics 365.