Although CRM Online/Dynamics 365 for Enterprise (D365E) does provide a plethora of different tools aimed at satisfying reporting requirements for users of the application, you are restricted in how data can be queried within the application. For example, you cannot just connect straight up to the applications SQL database and start writing stored procedures that perform complex data transformations or joins. Traditionally, to achieve this, you would need to look at one of the several tools in the marketplace that enable you to export your data out into a format that best pleases you; or even take the plunge and get a developer to write your own application that satisfies your integration requirements.

With the recent D365E release and in-line with Microsoft’s longstanding approach to how they approach customer data within their applications (i.e. “It’s yours! So just do what you want with it!), the parallel introduction of the Data Export Service last year further consolidates this approach and adds an arguably game-changing tool to the products arsenal. By using the service, relatively straightforward integration requirements can be satisfied in a pinch and a lot of the headache involved in setting up a backup of your organisation’s databases/LOB reporting application can be eliminated. Perhaps the most surprising and crucial aspect of all of this is that using this tool is not going to break the bank too much either.

In this week’s blog post, I’m going to take a closer look at just what the Data Export Service is, the setup involved and the overall experience of using the service from end-to-end.

What is the Data Export Service?

The Data Export Service is a new, free*, add-on for your CRM/D365E subscription, designed to accomplish basic integration requirements. Microsoft perhaps provides the best summary of what the tool is and what it can achieve via TechNet :

The Data Export Service intelligently synchronizes the entire Dynamics 365 data initially and thereafter synchronizes on a continuous basis as changes occur (delta changes) in the Microsoft Dynamics 365 (online) system. This helps enable several analytics and reporting scenarios on top of Dynamics 365 data with Azure data and analytics services and opens up new possibilities for customers and partners to build custom solutions.

The tool is compatible with versions 8.0, 8.1 and 8.2 of the application, which corresponds the following releases of CRM Online/D365E:

  • Dynamics CRM Online 2016
  • Dynamics CRM Online 2016 Update 1
  • Dynamics 365 December Update

*You will still need to pay for all required services in Azure, but the add-on itself is free to download.

The Installation Process

Getting everything configured for the Data Export Service can prove to be the most challenging – and potentially alienating – part of the entire process. For this, you will need the following at your disposal:

  • An active Azure Subscription.
  • An Azure SQL Server configured with a single database or an Azure VM running SQL Server. Microsoft recommends a Premium P1 database or better if you are using an Azure SQL database, but I have been able to get the service working without any issue on S0 tier databases. This is an important point to make, given the cost difference per month can amount to hundreds of £’s.
  • An Azure Key Vault. This is what will securely store the credentials for your DB.
  • PowerShell and access to the Azure Resource Manager (AzureRM) Cmdlets. Powershell can be installed as an OS feature on Windows based platforms, and can now be downloaded onto OS X/Linux as well. PowerShell is required to create an Azure Key Vault, although you can also use it to create your Azure SQL Server instance/Windows VM with SQL Server.

It is therefore recommended that you have at least some experience in how to use Azure – such as creating Resource Groups, deploying individual resources, how the interface works etc. – before you start setting up the Data Export Service. Failing this, you will have to kindly ask your nearest Azure whizz for assistance 🙂 Fortunately, if you know what you’re doing, you can get all of the above setup very quickly; in some cases, less than 10 minutes if you opt to script out the entire deployment via PowerShell.

For your setup with D365E, all is required is the installation of the approved solution via the Dynamics 365 Administration Centre. Highlight the instance that you wish to deploy to and click on the pen icon next to Solutions:

Then click on the Solution with the name Data Export Service for Dynamics 365 and click the Install button. The installation process will take a couple of minutes, so keep refreshing the screen until the Status is updated to Installed. Then, within the Settings area of the application, you can access the service via the Data Export icon:

Because the Data Export Service is required to automatically sign into an external provider, you may also need to verify that your Web Browser pop-up settings/firewall is configured to allow the https://discovery.crmreplication.azure.net/ URL. Otherwise, you are likely to encounter a blank screen when attempting to access the Data Export Service for the first time. You will know everything is working correctly when you are greeted with a screen similar to the below:

Setting up an Export Profile

After accepting the disclaimer and clicking on the New icon, you will be greeted with a wizard-like form, enabling you to specify the following:

  • Mandatory settings required, such as the Export Profile Name and the URL to your Key Vault credentials.
  • Optional settings, such as which database schema to use, any object prefix that you would like to use, retry settings and whether you want to log when records are deleted.
  • The Entities you wish to use with the Export Service. Note that, although most system entities will be pre-enabled to use this service, you will likely need to go into Customizations and enable any additional entities you wish to utilise with the service via the Change Tracking option:

  • Any Relationships that you want to include as part of the sync: To clarify, this is basically asking if you wish to include any default many-to-many (N:N) intersect tables as part of your export profile. The list of available options for this will depend on which entities you have chosen to sync. For example, if you select the AccountLead and Product entities, then the following intersect tables will be available for synchronisation:

Once you have configured your profile and saved it, the service will then attempt to start the import process.

The Syncing Experience A.K.A Why Delta Syncing is Awesome

When the service first starts to sync, one thing to point out is that it may initially return a result of Partial Success and show that it has failed for multiple entities. In most cases, this will be due to the fact that certain entities dependent records have not been synced across (for example, any Opportunity record that references the Account name Test Company ABC Ltd. will not sync until this Account record has been exported successfully). So rather than attempting to interrogate the error logs straightaway, I would suggest holding off a while. As you may also expect, the first sync will take some time to complete, depending on the number of records involved. My experience, however, suggests it is somewhat quick – for example, just under 1 million records takes around 3 hours to sync. I anticipate that the fact that the service is essentially an Azure to Azure export no doubt helps in ensuring a smooth data transit.

Following on from the above, syncs will then take place as and when entity data is modified within the application. The delay between this appears to be very small indeed – often tens of minutes, if not minutes itself. This, therefore, makes the Data Export Service an excellent candidate for a backup/primary reporting database to satisfy any requirements that cannot be achieved via FetchXML alone.

One small bug I have observed is with how the application deals with the listmember intersect entity. You may get an errors thrown back that indicate records failed to sync across successfully, which is not the case upon closer inspection. Hopefully, this is something that may get ironed out and is due to the rather strange way that the listmember entity appears to behave when interacting with it via the SDK.

Conclusions or Wot I Think

For a free add-on service, I have been incredibly impressed by the Data Export Service and what it can do. For those who have previously had to fork out big bucks for services such as Scribe Online or KingswaySoft in the past to achieve very basic replication/reporting requirements within CRM/D365E, the Data Export Service offers an inexpensive way of replacing these services. That’s not to say that the service should be your first destination if your integration requirements are complex – for example, integrating Dynamics 365 with SAP/Oracle ERP systems. In these cases, the names mentioned above will no doubt be the best services to look at to achieve your requirements in a simplistic way. I also have a few concerns that the setup involved as part of the Data Export Service could be a barrier towards its adoption. As mentioned above, experience with Azure is a mandatory requirement to even begin contemplating getting setup with the tool. And your organisation may also need to reconcile itself with utilising Azure SQL databases or SQL Server instances on Azure VM’s. Hopefully, as time goes on, we may start to see the setup process simplified – so, for example, seeing the Export Profile Wizard actually go off and create all the required resources in Azure by simply entering your Azure login credentials.

The D365E release has brought a lot of great new functionality and features to the table, that has been oft requested and adds real benefit to organisations who already or plan to use the application in the future. The Data Export Service is perhaps one of the great underdog features that D365E brings to the table, and is one that you should definitely consider using if you want a relatively smooth sailing data export experience.

An oft-requested requirement as part of any Dynamics CRM/Dynamics 365 for Enterprise (D365E) deployment is a level of integration with another application system. In some of these cases, this will involve pulling through external web pages and passing them form-level attribute values, to load an external systems report, record page etc. From a CRM/D365E point of view, this can be very straightforwardly achieved thanks to some of the functionality provided as part of the Xrm.Page object model. For example. let’s assume that you have an IFrame control on your form and you wanted to load an ASP.NET web page, passing the ID of the record as a query parameter in the URL. Setup your IFrame on your form, with a random URL and set to hidden. Then, a JScript function like this on the OnLoad event would get the job done for you:

function loadIFrame() {

    //Get the current record ID

    var entityID = Xrm.Page.data.entity.getId();

    //Replace { & } with their appropriate URL counterparts in entityID

    entityID = entityID.replace("{", "%7b");
    entityID = entityID.replace("}", "%7d");

    //Create the URL

    var url = "http://myexternalwebpage.com/MyAspPage.aspx?id=" + entityID;

    //Then, update the IFrame with the new URL and make it visible on the form

    Xrm.Page.getControl("IFRAME_myiframe").setSrc(url);
    Xrm.Page.getControl("IFRAME_myiframe").setVisible(true);
}

What helps with the above is that there are well-documented code samples that assists when putting together this example, so you can be confident that the solution will work and is fully supported.

Things get a little more complicated once we are operating outside the standard CRM/D365E environment. Assume that instead of displaying this IFrame control on a form, it needs to be displayed as part of an Entity Form in Adxstudio/CRM Portals. Here is where the head scratching can commence in earnest, and you need to look at getting your hand’s dirty writing custom code to achieve your requirements. There a few hurdles to overcome in the first instance:

  • How do you access attribute values from an Entity Form, such as a record ID?
  • Once you are able to access the attribute value, how to you set this up on your Entity Form?
  • How do you embed an IFrame within an Entity Form?

Let’s take a look at one approach to the above, working on the same basis as above – an external URL that we pass the record ID to, from within an Entity Form Web Page. Things may get a bit more difficult if you need to access other entity attribute values, which may require some kind of trickery with Liquid Templates to achieve successfully.

Accessing Entity Form Record ID

When your Entity Form page is loaded on your Portal, there are a number of properties regarding the record that are exposed on the underlying web page – the name of the entity, the record ID, Status and Status Reason values. These can be accessed via a div element on the page, which can be viewed within the DOM Explorer as part of a Web Browsers developer tools (in the below example, Internet Explorer is used):

1

The id of the div class will always be the same, except for the value in the middle, which is the GUID for the Entity Form record within CRM/D365E, but without the dashes. So you don’t need to necessarily go into the DOM to get this value; as a time-saving mechanism, simply export your Entity Form record into Excel and view the first hidden column to obtain this value.

Suffice to say, because we know that this value is accessible when our Portal page loads, we can look at programmatically accessing this via a JScript function. The following snippet will do the trick:

var recordID = document.getElementById('EntityFormControl_31c41a020771e61180e83863bb350f28_EntityFormView_EntityID').value;

Now that we have a means of accessing the attribute value, our options in terms of what we can do with it greatly increase 🙂

Executing Entity Form Custom JScript Functions

There are two ways you can place custom JScript on your portal page – you can either place your functions within the Custom JavaScript field, located on the Entity Form form within CRM:

2

Functions will be added to the bottom of your Web Page when loaded, meaning they can be freely accessed after the page has loaded. The second way, which leads us nicely onto the next section, is to wrap your JScript function as a custom HTML snippet on the Web Pages Copy (HTML) field.

Embedding an IFrame on your Web Page

All Web Pages in Adxstudio/Portals – irrespective of what other content the page is loading – contain a Copy (HTML) field. This enables you to write your own bespoke text or other HTML content that is displayed on the Web Page. In the case of an Entity Form Web Page, then the content will be displayed just below the Entity Form. Thanks to the ability to access and write our own custom HTML code for this, options for bespoke development are greatly increased – simply click the Source button to switch to the underlying HTML editor:

3

Then, using a combination of the snippet we used earlier and utilising the <iframe> HTML tag, we can place the following in our Copy (HTML) to do the lot for us – get our record ID, pass it to an external web page and then load this within an IFrame:

<p>
    <script>
        function getEntityID() {
            var url = "http://myexternalwebpage.com/MyAspPage.aspx?id=";
            var entityID = document.getElementById('EntityFormControl_31c41a020771e61180e83863bb350f28_EntityFormView_EntityID').value;
            var iframeSrc = document.getElementById('myiframe').src;

            if (iframeSrc != url + "%7b" + entityID + "%7d") {

                setTimeout(function () {
                    document.getElementById('myiframe').src = url + "%7b" + entityID + "%7d";
                }, 2000);
            }
        }
    </script>
</p>
<h1>My IFrame</h1>
<p>
    <iframe width="725" height="250" id="myiframe" src="" onload="getEntityID();"></iframe>
</p>

The reason why setTimeout is used is to ensure that the entity form <div> class loads correctly, as this is one of the last things that Adxstudio/Portals loads last on the page. For obvious reasons, if this hasn’t loaded, then our JScript function will error. Putting this aside, however, the above solution gets us to where we want to be and means that we can achieve the same outcome as the CRM/D365E example demonstrated at the start of this post 🙂

Conclusions or Wot I Think

Adxstudio/Portals presents some interesting and different learning opportunities, both given its genesis as a separate product to its gradual integration as part of the CRM/D365E family. This can often mean that you have to abandon your base assumptions and ways of thinking when it comes to CRM/D365E development, and instead look at things from a more general approach. I would hope that, in time, we will begin to see the gradual introduction of common XRM object models within CRM Portals, as it is crucially important that there is a unified approach when developing Portal extensions in the future and that we are not in the situation where unsupported code becomes rampant across different Portal deployments. This latter concern would be my chief worry with the examples provided in this post, as there is currently no clear way of determining whether the approach taken is supported or considered “best practice” from an Adxstudio/Portal perspective. I would be interested in hearing from anyone in the comments below if they have any thoughts or alternative approaches that they would recommend to achieve the above requirement.

Did you know that the CRM SDK contains a WebsiteCopy tool, that can be used to backup/migrate your CRM portal website? I was surprised actually, as there is no page on the CRM Setup & Administration website that refers to it. When I initially started looking more closely at the CRM portals release as part of the Spring Wave update, one of my first questions was “OK, portals are great! But how can I deploy my development portal site out to a production system when it’s ready?”. As a best practice approach, you will always want to ensure that you have distinctly separate development and production environments for any system that your business is using, and portals are no different in this regard. At first, I was concerned that there did not appear to be any “supported” mechanism for migrating development portal content into production environments; utilising the WebsiteCopy tool helps to overcome this issue and saves you from having to manually re-create records within your production CRM environment. Let’s take a closer look at how to get the tool, use it in practice and also review some of the supported scenarios that it can potentially assist with.

How to obtain the WebsiteCopy tool

In a rather counter-intuitive step, you will need to download the Dynamics CRM 2015 SDK. This is because the tool is not available whatsoever within the 2016 SDK. This seems like a rather strange oversight, so I would expect this to eventually be addressed as part of a future SDK release. Indeed, even the official MSDN page for this tool is listed as being only applicable to CRM 2011, 2013 & 2015. The 2015 SDK can be downloaded from here. Once you’ve got it and extracted it successfully, the tool can be found in the Bin folder in the root directory:

1

It is also worth pointing out that this tool is an exact copy of the Website Copy Tool provided by Adxstudio, which is obtainable via an installation of Adxstudio portals. Users of this tool should, therefore, face no challenge using the SDK version of the tool.

Using the tool

Due to simplistic nature of the wizard tool (and the fact that there are already well-documented walkthroughs available for both import and export scenarios), I will not go into detail documenting the entire process from start to finish. However, it is worthwhile pointing out the following:

  • There appears to be a bug on the Connect to Server screen where, after specifying your credentials and hitting Enter on your keyboard, the application thinks that you are pressing the ‘Go‘ button as opposed to ‘Next‘; clearing the credentials you have entered in the process and essentially going back a step: 5 6 7It took me a good half an hour or so before I figured this out, so make sure you hit the correct button!
  • When prompted to provide a Name value when importing your portal, the value can be anything you want it to be – the Website record’s Name field will be populated with this value in CRM on import.
  • I would generally recommend exporting to XML first, and then running the wizard again to import your newly created XML That way, you can double-check to ensure that you have run the initial export correctly and obtain a backup of your entire website in the process.
  • Exporting the cmd script at the end of the wizard is recommended if you intend to run the same export/import process frequently. For example, if you are running daily backups of your in-development website, then running the script instead of the wizard each day can save you some time.
  • Be prepared to put the kettle on as the import/export process can take some time.

Now that the website and all associated records are in CRM, how do you set this as your live website?

You will need to go to the configuration page for your CRM portal, and change your website record to point to your newly imported website. This is the same page you see when you first setup your portal, and can be accessed from the CRM Online Administration Center -> Applications and then Manage from your Portal Add-On subscription:

2

 

Then select your newly imported website from the Update Portal Binding drop-down:

8

Note that your changes may not take effect immediately after saving and that you will likely need to attempt the old “turning it off and back on again” trick using the Change Portal State dropdown:

3

As an additional bonus, the tool can also be used in the following scenarios:

  • Backup an Adxstudio website to a CRM Online portal deployment
  • Backup a CRM Online portal to an Adxstudio website (On-Premise/Online CRM)

To prove this, I did a test importing the ghastly looking portal, previously created as part of a previous post on Bootstrap templates. This was originally created using Adxstudio and I was able to successfully import this into CRM portals, in all its horrid glory 🙂

4

By covering both of the above scenarios, the tool instantly becomes a lot more powerful and versatile – enabling you to very quickly get your existing Adxstudio website setup as a CRM portal site. It also gives portal developers the flexibility to setup their own development Adxstudio environment, safe in the knowledge that they can straightforwardly migrate these across to CRM portals when they are production ready. Note that the above test does not confirm whether or not bespoke Adxstudio customisations via custom generated ASP.NET pages etc. will definitely migrate across 100% to CRM portals and that the steps involved in changing/modifying the bindings for Adxstudio differ significantly from CRM portals.

Conclusions or Wot I Think

CRM portals, as a product offering, is still in its early life cycle stages. As such, it is reasonable to expect that clear and broad documentation that covers the types of scenarios discussed in this blog post (e.g. managing CRM portal development environments) is not yet forthcoming and that some trial and error may be involved in figuring what to do (it wouldn’t be fun otherwise 🙂 ). What is good to know is that Microsoft has not made a conscious decision to restrict or remove some of the existing tools available for Adxstudio and that they “just work” with CRM portals. This is perhaps a rather obvious assumption, given that both products are technically identical. Nevertheless, it is good to know that those who are venturing into CRM portals for the first time can very easily get running with tools, like the WebsiteCopy Tool, when planning, developing and rolling out solutions for businesses who have taken the plunge early on with CRM portals.

I have been really excited recently, as I began working more closely with ADXstudio & CRM Portals. This was perhaps one of the more exciting new features introduced as part of the CRM 2016 Spring Wave earlier this year and presents a major step forward for the CRM product. Now, businesses can start to leverage their CRM and its data in developing professional, accessible, customer and/or partner facing websites that integrate natively with your existing CRM system and processes.

One of the first challenges when getting to grips with portals is how you go about changing the OOB design of your site – for example, how do you modify the colour for a background or a particular button? Both products utilise Bootstrap to enable portal designers to very quickly develop professional looking portals that are customised to suit particular businesses design/theming preferences. In addition to this, as outlined on ADXstudio’s website:

By using Bootstrap’s layout system, it’s possible to develop a single site that presents an appropriate interface to all devices your customers might use.

In the days where mobile responsiveness is an absolute requirement for website projects, Bootstrap provides a framework that ensures a consistent UI experience is maintained at all times for your end users. But, if you are scratching your head at just how to start working with Bootstrap (like I recently was!), it can be a major hurdle figuring out how to begin styling your portal. In this week’s blog post, I will take a closer look at what Bootstrap is, what “shortcuts” are out there that can greatly speed up developing your first Bootstrap template and how you go about applying this to your custom portal site:

What is Bootstrap?

Bootstrap was originally developed by Twitter but has since become an open-source project, on its 3rd major version. The Bootstrap website contains a nice little summary around the history of the project and its interesting journey from internal project to open-source release:

Bootstrap was created at Twitter in mid-2010 by @mdo and @fat. Prior to being an open-sourced framework, Bootstrap was known as Twitter Blueprint. A few months into development, Twitter held its first Hack Week and the project exploded as developers of all skill levels jumped in without any external guidance. It served as the style guide for internal tools development at the company for over a year before its public release, and continues to do so today.

Source: http://getbootstrap.com/about/

I was actually surprised to learn about its popularity, having not had any previous exposure to it, and its status as the almost de-facto standard in website design circles.

Creating your first Bootstrap Template

Microsoft’s article on portal theming (replicated from ADXStudios original article) suggests a few different websites to try in the first instance. We’ll take a closer look at 3 of the websites mentioned here that enable you to customise a Bootstrap template from scratch, and then at an alternative route not mentioned on either website:

Official Bootstrap Customizer

Via the official Bootstrap website, you can create your own custom bootstrap template. As pointed out in the above articles, there is no GUI interface that lets you preview your customised template; which means you have to download and apply the Bootstrap files to your website in order to get a feel for how it looks. If you’re feeling particular masochistic, then this is definitely the route for you 🙂

6

Argh, too many settings! (╯°□°)╯︵ ┻━┻

BootSwatchr

When you first start using BootSwatchr, you immediately warm to it straight away – it provides a WYSIWYG editor, enabling you to very quickly tinker around with the various settings on the default Bootstrap template, and see how they will look in a browser. VERY nice! However, I have encountered some issue using the tool on Internet Explorer/Microsoft Edge, particuarly when it comes to the most crucial bit – exporting your BootStrap template .css file using the ‘Get CSS…‘ button. This is definitely one of the tools you should check out in the first instance, but just be aware that it may not work correctly on your browser of choice.

7

Code editor? Check. WYSIWYG view? Check. Instant applying of changes to the preview? Check. Full marks!

BootTheme

What is encouraging when you first start using BootTheme is that it looks to be constructed in the same vein as BootSwatch. However, I have had real trouble figuring out how to use this tool, as it is initially quite daunting figuring out where to start. I think with some dedicated time and learning, this could be a really effective tool to use when building your Bootstrap templates, but perhaps not the best beginners tool.

8

So er, yeah, looks pretty good – where do I start? :S

PaintStrap/COLOURLovers

These tools are the ones that I have used when creating Bootstrap templates, and used in tandem, are quite effective in creating a Bootstrap template that conforms to specific branding requirements. You start off by creating a ColourLovers account, which lets you then create a “colour scheme” that can be used in PaintStrap. A “colour scheme” is essentially a collection of up to 5 different colours that you want to use on your BootStrap, which can be generated very easily using the ColourLovers website. Simply go to Create -> Palette, specify your colours, give it a descriptive name and save onto your profile:

1011 12

Once you’ve saved your COLOURLovers template, you then copy across the 6 digit code for the template into the PaintStrap 3 step wizard. This can be found within the URL of your selected template:

13

Which is then entered onto PaintStrap:

14

Then, on Step 2, you can start to customise which colours will appear where on your BootStrap – the nice thing being that you are not restricted to just the colours on your template and you can get a partial and full-screen preview of your template as you build it:

9

When you are happy with your template, click the ‘Generate CSS!’ button to download your BootStrap .css file. You will want to grab the bootstrap.min.css file; this is exactly the same as the bootstrap.css file but has been slimmed down to remove line breaks, whitespace etc.

Once you’ve got your Bootstrap, how do you apply it to your portal?

Let’s assume we are using the Basic Portal, provided as part of ADXStudio; the steps are the same for CRM Portals, rest assured:

3

Navigate to the home page of your portal, ensuring that you are logged in as a Contact that has the Administrators Web Role. On the ADX widget on the top right of your page, click on New -> Child file:

1

You’ll be greeted with the Create a new child file screen. Populate the details as follows:

  • Name: bootstrap.min.css
  • Upload File: Browse and select your bootstrap.min.css file
  • Partial URL: bootstrap.min.css
  • Hidden from Sitemap: Tick the box

It should look something like this:

2

Press Save and then refresh your browser. Your new bootstrap will be applied to your site; and, because we have configured it on our home page, it will cascade automatically across our portal site:

4 5
Looks…err…interesting! I would not recommend or endorse creating a bootstrap that looks like this, but this example provides an excellent illustration of the versatility of Bootstrap.

Getting up to speed with Bootstrap may look quite daunting initially, but fortunately, there are lots of tools and resources available online that can get you running quickly with BootStrap. These tools can significantly ease your learning journey with ADXstudio/CRM Portals and also allows you to look like a website design whizz in the process 🙂

The ability to implement trace logging within CRM plug-ins has been around since CRM 2011, so it’s something that CRM developers should be well aware of. Writing to the trace log is useful for when a plug-in has failed or hit an exception, as within the ErrorDetails.txt file (available to download from the error message box window) will be a list of everything that has been written to the log, up to that point. One issue with this is, if a user encounters an error and does not choose to download this file, then this file is lost – not so much of an issue if the exception can be re-produced, but this may not always the case.

For those who are now working on CRM Online 2015 Update 1 or CRM 2016, then a new feature has been added which further expands this feature – the Plug-in Trace Log. Now, plug-in exceptions can be configured to write to a new system entity, containing full details of the exception, that can be accessed at any time in order to support retroactive debugging. The introduction of this feature means now is the best time to start using trace logging within your plugins, if you are not already. This weeks blog post will take a look at the feature in more detail, assessing its pros & cons and providing an example of how it works in practice.

So, before we begin, why you would want to implement tracing in the first place?

Using tracing as part of CRM Online deployments makes sense, given that your options from a debugging point of view are restricted compared to an On-Premise Deployment. It is also, potentially, a lot more straightforward then using the Plug-in Registration Tool to debug your plugins after the event, particularly if you do not have ready access to the SDK or to Visual Studio. Tracing is also useful in providing a degree of debugging from within CRM itself, by posting either your own custom error messages or feeding actual error messages through to the tracing service.

Just remember the following…

Writing to the tracing service does add an extra step that your plug-in has to overcome. Not so much of an issue if your plugin is relatively small, but the longer it gets, and more frequent you are writing to the service, means there is a potential performance impact. You should use your best judgement when writing to the service; not every time you do something within the plugin, but where there is a potential for an error to occur. Writing to the tracing log can also have an impact on your CRM storage capacity, something we will take a look at later on in this post.

Now that we have got that out of the way, lets begin by setting up an example plugin! 

To start writing to the Tracing service depends on how you are implementing your plugin. If you have used the Visual Studio template, then simply use this line of code within the “TODO: Implement your custom Plug-In business logic.” section:

ITracingService tracingService = localContext.TracingService;

Otherwise, you will need to ensure that your plugin is calling the IServiceProvider, and then use a slightly longer code snippet to implement the service. An example of the code that you’d need to use to setup this is as follows:

using System;

//Be sure to add references to Microsoft.Xrm.Sdk in order to use this namespace!

using Microsoft.Xrm.Sdk;

namespace MyPluginProject
{
    public class MyPlugin : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            //Extract the tracing service for use in debugging sandboxed plug-ins.
            
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
        }
    }
}

Once you’ve implemented the ITracingService within your code, you can then write to Trace Log at any time in your code using the following snippet:

tracingService.Trace("Insert your text here...");

Activating Tracing

Even though we have configured our plugin for tracing, this does not automatically mean that our plugin will start writing to the log. First, we must configure the Plug-in and custom workflow activity tracing setting within the System Settings page:

TracingSettings

You have three options that you can set:

  • Off – Nothing will be written to the trace log, even if the plugin encounters an exception.
  • Exception – When the plugin hits an exception, then a trace will be written to the log.
  • All – Whenever the plugin is executed and the trace log is called, then a trace log record will be created. This is equivalent to Verbose logging.

As mentioned earlier, individual records will be written to CRM whenever the tracing service is called. It is therefore recommended only to turn on ‘All’ for temporary periods; leaving it on for ‘Exception’ may be useful when attempting to initially diagnose plugin errors. Review the amount of storage available to you on your CRM Online/On-Premise deployment in order to determine the best course of action.

Tracing in Practice

Now that we’ve configured tracing on our CRM and we know how to use the Tracing, lets take a look at an example plugin. The below plugin will be set to fire on the Post-Operation event of the Update message on the Account entity. It will create a new contact record, associate this Contact record to the Account and then populate the Description field on the Contact with some information from the Account record:

protected void ExecutePostAccountUpdate(LocalPluginContext localContext)
    {
        if (localContext == null)
        {
            throw new ArgumentNullException("localContext");
        }

        //Extract the tracing service for use in debugging sandboxed plug-ins.

        ITracingService tracingService = localContext.TracingService;
        tracingService.Trace("Implemented tracing service succesfully!");

        // Obtain the execution context from the service provider.

        IPluginExecutionContext context = localContext.PluginExecutionContext;

        // Get a reference to the Organization service.

        IOrganizationService service = localContext.OrganizationService;

        if (context.InputParameters.Contains("Target"))

        {
            //Confirm that Target is actually an Entity

            if (context.InputParameters["Target"] is Entity)

            {
                Guid contactID;
                string phone;

                Entity account = (Entity)context.InputParameters["Target"];
                tracingService.Trace("Succesfully obtained Account record" + account.Id.ToString());

                try

                {
                    tracingService.Trace("Attempting to obtain Phone value...");
                    phone = account["telephone1"].ToString();
                            
                }
                    
                catch(Exception error)

                {
                    tracingService.Trace("Failed to obtain Phone field. Error Details: " + error.ToString());
                    throw new InvalidPluginExecutionException("A problem has occurred. Please press OK to continue using the application.");

                }

                if (phone != "")

                {

                    //Build our contact record to create.

                    Entity contact = new Entity("contact");

                    contact["firstname"] = "Ned";
                    contact["lastname"] = "Flanders";

                    contact["parentcustomerid"] = new EntityReference("account", account.Id);

                    contact["description"] = "Ned's work number is " + phone + ".";

                    contactID = service.Create(contact);

                    tracingService.Trace("Succesfully created Contact record " + contactID.ToString());

                    tracingService.Trace("Done!");

                }

                else

                {

                    tracingService.Trace("Phone number was empty, Contact record was not created.");

                }
            }
        }
    }

After registering our plugin and with tracing configured for “All” in our CRM instance, we can now see our custom messages are being written to the Trace Log – when we both update the A. Datum Corporation (sample) record Phone field to a new value and when we clear the field value:

Plugin_1

Plugin_2

Plugin_3

Most importantly, we can also see that our test Contact record is being created successfully when we populate the Phone field with data 🙂

 

Plugin_4

Now, to see what happens when an error is invoked, I have modified the code above so that it is expecting a field that doesn’t exist on the Account entity:

Plugin_5

Now, when we attempt to update our Account record, we receive a customised Business Process Error message and window:

Plugin_6

And we can also see that the precise error message has been written to the trace log, at the point we specified:

Plugin_7

Last, but not least, for On-Premise deployments…

One thing to point out is, if you are using On-Premise CRM 2016 (both 8.0 and 8.1), then for some reason the trace log will not work if you do not run you plugin within sandbox isolation mode. I’m not the only one experiencing this, according to this post on the Dynamics CRM Community forum. Switching my test plugin to sandbox isolation resolved this issue. A bit of a strange one, and as Srikanth mentions on the post, it is not clear if this a bug or not.

Conclusions or Wot I Think

Trace logging is one of those things where time and place matter greatly. Implementing them within your code obsessively does not return much benefit, and could actually be detrimental to your CRM deployment. Used prudently and effectively though, they can prove to be incredibly useful. The scenarios where I can see them returning the most benefit is if your plugin is making a call to an external system and, if an error is encountered during this process, you can use the Trace Log to capture and store the external application error message within CRM for further investigation. Trace logging can also prove useful in scenarios where an issue cannot be readily replicated within the system, by outputting error messages and the steps leading up to them within the Trace Log.

In summary, when used in conjunction with other debugging options available to you via the SDK, Trace Logging can be a powerful weapon to add to your arsenal when debugging your code issues in CRM.