CRM Plugin Code Structure – By functionality or by event?

When we work on CRM plugins, there is a key decision at the beginning of the development cycle when it comes to structuring your plugin code. There are two main ways of writing your plugins :  by events or by functionality. In this post, I will describe the two approaches and discuss some of their pros and cons.

Plugins can be described as handlers for events fired by Microsoft Dynamics CRM (source). There can be multiple handlers for single events.  Let’s use an example for the purpose of this post.

For the event, we’ll use the creation of a case (pre operation). We will consider that when  the case is created, there are two actions that need to be performed : generate and assign a unique case number and validate that required fields have authorized values in them.

Plugin structured based on Events

For the plugin structure based on event, it means we’ll have a single plugin registered on the Case Pre create event, and inside the plugin class we’ll have two business logic blocks of code to execute (one to generate the unique number, the validate the required fields).

SNAGHTML4e81484     SNAGHTML4e74f7f

Plugin structured based on Functionality

In this case, we’ll have two plugin classes registered on the same event (again, one plugin for unique number generation and another to validate the required fields) – Sorry, no screen shot here but you get the idea Smile.

Pros and Cons

Functionality Based Plugins

  • Pros
    • Ease to see what plugins does what when looking at Plugin Registration tool (or similar tools) because of more descriptive feature name in plugin name
    • Ability to disable specific features for various scenario (e.g. disable system integration or auto calculation plugins during data migration)
    • Unit Tests can be written against a plugin class to test one functionality
    • Provides the ability to easily write generic plugins and register on multiple events by any power user
  • Cons
    • Large amount of plugin classes
    • Large amount of registered plugin steps; can become big and hard to read/maintain

Event Based Plugins

  • Pros
    • Plugin registration is straight forward and easy to maintain
    • Ease to easily the operations performed at each event when looking at the code
    • Plugin classes are standardized : always tied to an event and single point of entry for all developer to see actions executed on the event
    • Unit tests can be written against specific Business logic methods and/or classes (even independently from the plugin execution context depending on how they are written)
  • Cons
    • Must use alternate mechanism to disable specific features if needed (e.g. configuration data element)
    • Possible timeout if executing multiple large business logic blocs (mind you, if you have a timeout in a plugin – which happens after two minutes, you probably have a design issue)
    • General  dependency to having a developer around
      • Generic business logic code blocks can be written but a developer is required to insert the business logic on additional events
      • To view the all operations performed for an event, a developer needs to look at the code

So which model should you use?

I have used both models heavily on various occasions. For me personally, the decision on which one to use comes down to a project’s needs and a coding style preference. As an example, if you know you’ll have a lot of generic features and want to have reusable plugins, you are better off using the functionality based model. The same applies if you know there are processes that require to disable specific functionality on a regular basic. On the other hand, if you project is relatively small and includes simple business logic on a few events, the event based approach can be a good choice. Feel free to add feedback in the comment section if you see other pros and cons for each of these models or want to share experience in the area.

Creating readable unique identifiers for your CRM records

A common requirement in CRM implementations is the need to have readable identification numbers auto-generated for custom attributes. There are various ways of achieving this. This article provides a few options to do that.  

Let’s use one scenario as a context. Let’s say we are building a Grants Management application and we are tracking scholarship applications in Dynamics CRM. We have an application entity which contains an Application Id field. For business reasons, we need to have a unique identifier to refer to the applications. What are out options? For starters, let’s look at some of the elements to consider when looking for an auto-numbering solution in Dynamics CRM?

  • Are you using an entity that is auto-number enabled? (e.g. Case, Quotes, Orders etc.)
  • Do you need the numbers to be sequential?
  • Do you have potential race conditions? (i.e. can the event assigning the auto-number be triggered by multiple processes simultaneously?)
  • Do the auto-numbers need to be human readable?
  • What is the format required? (numeric only, alpha-numeric, letters only, prefix, suffix etc.)
  • Can you and/or do you want to write code to generate these numbers or do you want an simple configurable solution?

Generate an unique number based on the current Date Time

Of course, this required a plugin on an event that will generate the application Id. From a technical standpoint, there are a few algorithms out there that will give you an indication as to how this can be done. The full date time and the “tick” should be use to generate the number to ensure uniqueness. But even with that, there is a very very very small chance of having race conditions depending on your application and on your (bad) luck. Also, this will not allow your to use sequential numbers.

Create a record of an auto-numbering CRM entity

If you are *not* using one of the CRM auto-numbering enabled entities (for example, Campaign), this solution is have a plugin (or a Workflow) on your triggering event that will create a Campaign record. This campaign will automatically be assigned a unique number based on your CRM configuration (image below). You can re-use that number as the unique ID for your record and delete the Campaign record that was created. While this is a simple method that can be implemented without coding, the numbers are not really sequential, “garbage” records are created at a cost (create/delete transactions time, what happens if you want/need to use that entity in the future?..). To be honest, it feels like a quick-and-dirty way of doing things, but it works.

The advantage here is that because the auto-numbers are platform generated, so you do not have to worry about race conditions in theory.


Use a model based on CRM Synchronous Workflow + Custom Auto-Number entity

I will not go too much into details about this one. There are lots of articles on the topic. A few “how-to” articles for reference:

Bottom line, this is a great solution if you cannot write any code and don’t want to spend any money for something that should be standard in the platform (yes, I’m ranting, can’t help it). That being said, it you have race conditions, I’m sure you can have a few duplicated numbers with this solution.

Using a 3rd Party Tool

There are plenty of options out there. Some are more flexible than others. Some explicitly guarantee uniqueness, some don’t really mention it. Some are free, some are not.

These are just a few, a research will allow you find more of these and decide the one that fits your needs the best.

Build your own solution

At this point, you can do it anyway you want.

  • If you have access to an external database, a CRM plugin that create a record in the database with an identity column will guarantee to always have unique and sequential numbers. This comes at a cost obviously (external database dependency, speed)
  • There is also a smart way of doing robust auto-numbering suggested by Ken Heiman of Green Beacon here. Good read, smart idea.
  • Some enterprises already have Auto-Numbering web services, you can simply consume that web service from a CRM plugin as well (same cost as database, dependency, speed)
  • I have also seen the idea of using the Guid as a unique identifier, by copying the value into a text field with a plugin. I don’t think it’s readable, but definitely unique.

 

It had been too long. Happy CRM’ing ! 

Selecting your Dynamics CRM developer(s) setup

If you are ever involved in a very large CRM implementation project, one of the decision that you need to make early is how to setup/structure your development environments and workstations. Not that I think it’s not as import on smaller project, but it is more critical in larger project.

First let’s start by defining what I mean by a large project (this is a completely personal):

  • Large development team (4+ people)
  • Multiple complex customizations pieces (plugins/custom activities/JavaScript/HTML) and/or integration points
  • Project length: variable, usually 6-8+ months

Last year, I wrote about how to setup your Dynamics CRM/Source Control environment properly for Dynamics CRM projects. Today, I want to focus more on the Development Machines setup and what I have found to be useful for decision making process to set them up.

In the typical CRM project, you will find a Dev CRM organization used for doing system configuration and basic customization. Then, for plugin/JavaScript development, we typically recommend to have either a dedicated VM with CRM installed for each developer, or a dedicated CRM Organization. The reason why we make this recommendation is very simple: development Isolation.

When you are developing say a web site or a mobile app, you don’t deploy your content on the test server or device that everyone uses until it’s ready to be tested. The same applies for CRM. If you have a primary development organization, why would you want developers to deploy work in progress on a regular basis? Plus, if they are working on the same module, they might overwrite each other’s code all the time. The loss of productivity will be at two levels

  • Deployed code that’s not finalized will cause bugs and people won’t be able to continue working, test in the CRM organization normally
  • Developers will likely overwrite each other if they are working on similar or dependent tasks which will result in a major loss of time and productivity

Now that I have sold you on the development isolation idea, here is a list of pros and cons that will help you decide whether you should go the individual CRM Organization way or the individual VM + CRM route.

Individual CRM Organization

  • Pros:
    • Easy to setup
    • (possibly) Part of your corporate domain which makes the access easier for developer and possibly other people if needed
    • Provides isolation for development
  • Cons
    • Developers lack control over the servers (i.e. can’t do IIS reset or restart services etc.)
    • Depending on how powerful your infrastructure is, sharing CRM/SQL Servers with multiple users, the servers might be overloaded quickly and you find yourself with an issue related to sharing your server resources
    • Removes the ability to debug the old fashion way by attaching to IIS/sandbox/async processes
    • Ongoing maintenance of the CRM/SQL server(s) hosting the organizations

clip_image002

Individual VM with CRM/SQL installed

  • Pros:
    • Provides developer with great control over the environment in which they develop
    • Provide isolation for development
    • Provide isolation for Hardware utilization (depending on how VMs are setup)
    • Easy to setup (build a VM once, create a capture and provision on need)
    • All development tools can be installed on the VM and isolated from workstation
    • Easy to do plugin/custom activities debugging by attaching to IIS/sandbox/async processes
    • Easier to perform integration test in an isolated VM
    • Relatively light use hardware resource if the VMs are hosted on developers’ workstations
  • Cons:
    • Possibly Windows OS Server license issue (each developer needs one license)
    • Network configuration can be tricky depending on your environment or Enterprise context (e.g. accessing TFS from VM, expose VM to the internet)
    • Heavy use of hardware resources (especially if you have VM Host server(s))
    • Ongoing maintenance of the VM host server and VMs

SNAGHTMLec1ea7

It’s worth noting that individual VMs can be created on a host server or on developers’ local workstations (laptops or desktop). You may or may not decide to join the VMs to the corporate domain, you could even setup your development environment in the cloud on a Virtual Network which we have done multiple times including for my company. 

Lastly, as noted by Darly Labar, if your project is with CRM Online, running VMs locally will prevent you from having a same version of Dynamics CRM in your developer VMs (CRM Online and On-prem are very similary, but not the same and not always in sync). The same applies for the individual developer CRM organization unless you have a CRM Online Sandbox for each developer or other instances of CRM Online they can use for development purpose.

There you have it. The great thing is that you always have options. From there, it’s making sure you select the one that is appropriate for your needs.

If you need help and guidance throughout this process, feel free to reach out to us at SADAX Technology. We offer “Hour Bucket” packages from 5 to 30 hours for Dynamics CRM and Azure consulting services. Request a quote here!

 

Exchanging data between CRM Forms and IFRAMEs

One of the most common requirements when we add content in IFRAMEs or Web Resourses in CRM is to have the ability to communicate with the calling or source CRM form to perform all sorts of operation. This article explains how this can be achieved using the postMessage JavaScript messaging mechanism.

What does postMessage do?

It’s a JavaScript method which was initially created to facilitate cross-origin communication between web pages. There are often valid scenario in which we need to display a page from another website in a new window or in an IFRAME. That’s the easy part. The more complicated part is when there is a requirement to perform some operations on the source page based on a action that occurs on the external page in the new window or IFRAME.

In the example below, consider we have a contact form that displays an external page in an IFRAME. When a button in clicked in the IFRAME, information (example, a lookup value) is passed to the CRM form, the value is set on the screen and the form is saved.

Step 1 – Write methods for the CRM Form: Register Listener, Message Handler  

The code below contains two methods, the first one (RegisterListener) sets a method that will be called if the postMessage is invoked (UpdateContactLookup). 


SADAX.Contact =
{
   RegisterListener: function () {

     if (window.addEventListener) {
       window.addEventListener('message', SADAX.Contact.UpdateContactLookup, false);
     }
     else { // IE8 or earlier
       window.attachEvent('onmessage', SADAX.Contact.UpdateContactLookup);
     }
   },

   UpdateContactLookup: function (event) {

     var origin = "";
     if (event.domain) origin = event.domain; // IE
     else if (event.origin) origin = event.origin; // FireFox - Chrome

     if ("https://source" == origin) {

       if (event.data != null) {

         var entity = SadaxJSON.parse(event.data);
         if (entity) {

           var value = new Array();
           value[0] = new Object();
           value[0].id = entity.Id;
           value[0].entityType = entity.LogicalName;

           var lookup = Xrm.Page.getAttribute("sadax_referencecontactid");
           lookup.setValue(value);
Xrm.Page.data.save();
}
}
else
{
alert("This message has been posted by an unknown source ('" + origin + "', expected 'https://source').");
return;
}
} 
}

Step 2 – Register the listener on Form’s OnLoad event

image

Step 3 – Write Code for the IFRAME to post the Message from the IFRAME

After the business logic execution, the postMessage method is called on the parent CRM form as follows:

function SetContactLookup(entityReference)
{
   var entity = {};
   entity.Id = entityReference.id;
   entity.LogicalName = entityReference.entityType;

   window.parent.postMessage(SadaxJSON.stringify(entity), "https://source");
}

Comments / Wrap up

At step 3, using the postMessage on the window.parent will cause the SADAX.Contact.UpdateContactLookup method to be fired on the parent CRM form. Notice that the method receives an event object as a parameter. The content of the object slightly differs based on the browser being used (IE vs rest of the world). Mostly, you should pay attention to the event.domain or event.origin attributes. This is used to validate the website that posted the message is safe (i.e. the one you are expecting).

There is also an event.data attribute that contains parameters that are sent from one page to another. In this case, we are using a renamed JSON library to stringify our custom object types. Passing an object without stringifying it would work, but we found it didn’t work well in all browsers/version. The reason for the renamed JSON library is again browser compatibility reasons. If IE8 is out of scope for you, you probably do not need this.

Notes:

  • This also work for web resources opened in a different window using window.open or Xrm.Utility.openWebResource
  • IE8 doesn’t allow to postMessage to other windows, only to iframes.
  • I haven’t tried this in CRM Online so you can try it by yourself if need be.

Custom User Interface in CRM – HTML5/JavaScript or ASP.NET Web application?

Lots of times on CRM projects, we are required to build and display custom screens inside of Dynamics CRM. There are a lot of factors that come into play in the choice how we build these custom user interfaces. It is a very key decision to make because it can sets the standard technologies and tools that you use for custom screens on project (among other things). I thought I’d share some key points to consider in your decision making process to determine what technologies and tools to use.

The need for custom user interface

First, it is important to know and understand when it is required to build custom UI as part of your CRM solution implementation. As a wrote a few years ago, we sometimes find ourselves in situations where we can come up with a complex data model and we feel like the out of the box UI capabilities won’t be user friendly enough to drive user adoption. Situations like that create the need to build more user friendly interfaces to simply make people’s lives easier when they start using the CRM/XRM application. Some examples are

  • Custom calendar view for timekeeping
  • Tree view to display a complex hierarchy
  • Interactive Bing or Google maps views of CRM data
  • Editable grids
  • Complex grids with aggregates, grouping functionalities
  • Integrated views to other systems

And the list goes on. The needs are very different depending on the nature of the enterprise looking to implement a CRM/XRM solution.

Most common technology choices

From experience, I have seen a lot of custom screens built using the following tools/technologies:

  • Silverlight
  • ASP.NET / ASP.NET MVC
  • HTML/HTML5 + JavaScript + CSS

The screens are usually displayed in web resources or in an IFRAMES inside CRM on forms or as standalone modules (open from a button, display in sitemap area). I will not cover Silverlight since Microsoft announced its end of life and continued support for a few additional years, plus the world has started to move on.

ASP.NET / ASP.NET MVC

  • Pros
    • Flexible server side business logic
    • Easily integration with external systems (web services, databases etc.)
    • Can be very quick to develop depending on the requirements, expertise and accelerators (advanced controls provided by Telerik, Infragistics or others can speed up development time significantly)
    • Develop with a familiar programming language (C# + Visual Studio) – this of course depends on your development background
  • Cons
    • Requires the deployment and maintenance of a hosted web application
    • You have to deal with the weight of ASP.NET (ViewState, Postbacks etc.)
    • Not a great fit with CRM Online and cloud offerings in general (cloud deployment, cross origin web sites, integrations etc)
    • Required additional configuration in CRM + JavaScript to set the IFRAME’s sources (URL)
    • Effort for developing custom web applications is often under-evaluated

HMTL(5)/JavaScript

  • Pros
    • Usually, a much lighter solution and if done properly, custom UI components can be very responsive and provide great user experience
    • All components are in CRM Web Resources (html pages, JavaScript files, images…)
    • Custom screens are CRM Solution aware and there is no need for deploying and maintaining an additional web site on a web server
    • A definite plus for cloud based Dynamics CRM implementations
    • Can be very quick to develop depending on the requirements, expertise and accelerators (Kendo UI controls or others can speed up development time significantly; other frameworks like Knockout JS, Bootstrap can also be useful)
    • Leverage trending technologies and tools
    • Use any IDE you want (no obligation to use Visual Studio, even if you should J)
  • Cons
    • Possibly additional complexity if you need to display information from an external system
    • If not structured properly, JavaScript code can become massive and hard to navigate/maintain
    • For non-web developers, might be a steep learning curve
    • Need to establish good project structure and standards (e.g. use TypeScript or Script Sharp)

What else to consider?

There are other factors to take into account, some being specific to each organization. A few examples:

  • What is the expertise or your resource pool?
  • Do we have people to build and maintain what we deploy?
  • Are we in CRM Online or planning to move to CRM online?
  • Are we, as a company, trying to get into HTML/JavaScript more?

This is good food for thoughts for starters. If you want more guidance, feel free to reach out to us.

How to show SharePoint document list on main CRM form

When you enable the SharePoint integration for CRM, you get the ability to view a document list view by navigating to the document area on the form. Often, users want have this list of document available directly on the main form and not have to navigate to another page. Here is one way to do it, applicable for the “old fashion” SharePoint integration using the SharePoint List Component for CRM. It does not apply to server-based SharePoint integration with CRM. This is an unsupported customization, use at your own risk. 

What you need

  • SharePoint integration enabled and configured for the target entity (i.e. list component installed, existing SharePoint Site & folder)
  • an IFrame on the form
  • a way to get the full URL of SharePoint folder associated to your record (could be a field that you automatically populate on the entity with a plugin, could be retrieving the SharePoint Document Location records using JavaScript when for form loads, etc.)

How it works

When the document view is loaded, there is a URL pattern used by the system to display the list component with the documents:

http://sharepointdev/crm/crmgrid/crmgridpage.aspx?langId=en-US&locationUrl={document location url}&pageSize=250

What you can deduct from the URL above:

{SharePoint Root Site}/crmgrid/crmgridpage.aspx?langId={Language}&locationUrl={Document Location Url}&pageSize={Page Size}

Grabbing that Url with the correct parameters and pasting in browser will display the list of document for the target CRM record. In short, all you have to do is display that Url constructed properly inside an iFrame on your CRM form (see illustration below). Please note that this can have a performance impact on how quickly the form loads (this component can take longer to be loaded and displayed.

image

Code snippet

Javascript Method to load the content


var documentSiteUrl = ""; /* Find a way to get this information – can be read from a hidden field on the form. */
var parentSite = ""; /* Find a way to get this information – can be read from a hidden field on the form. */

if (documentSiteUrl == "" || parentSite == "") {
   return;
}

// Build document location URL - Set IFRAME target
var docViewUrl = parentSite;
if (!StrEndsWith(docViewUrl, "/")) {
   docViewUrl = docViewUrl + "/";
}

var userLanguage = "en-US";
if (Xrm.Page.context.getUserLcid() == "1036") {
   userLanguage = "fr-FR"
}

docViewUrl = docViewUrl + "crmgrid/crmgridpage.aspx?langId=" + userLanguage + "&locationUrl=" + documentSiteUrl + "&pageSize=250";

var documentIFrame = Xrm.Page.ui.controls.get("IFRAME_Documents");
if (documentIFrame != null) {
   Xrm.Page.ui.tabs.get("Documents").setVisible(true);
   documentIFrame.setSrc(docViewUrl);
}
else {
   Xrm.Page.ui.tabs.get("Documents").setVisible(false);
}

Developer Focus – CRM Solution Manager Review

I’ve been using the CRM Solution Manager for a few months now and I thought I’d provide some insights on the product in case you are considering making the investment.

What is it the CRM Solution Manager?

CRM Solution Manager is a productivity tool for CRM Developer that integrates with Visual Studio and Dynamics CRM. The idea is for a CRM developer who writes plugins, custom workflow activities, JavaScript and HTML web resources to be able to do his/her development and manage deployments of the development components to CRM all from Visual Studio in a user friendly way.

The product comes as a Visual Studio Extension file (.vsix) and currently supports Visual Studio 2010, 2012, 2013 and 2015, that means it very likely supports the version you are currently using (I really hope so!). There is a free 30 day trial available to try.

After the installation, when you run Visual Studio, you are presented with a screen to log onto CRM:


When the connection is completed, you can create your projects (Class Libraries for plugins and custom workflow activities, and Empty Web project for web resources). Once your projects are created, the fun can start.

Plugins and Custom Workflow Activities Development

For server side development, the tool brings a lot to the table.

If you have a class library project not linked to CRM or not containing anything at related to CRM, right clicking on the project will give you the possibility to either add the Plugin Assembly to CRM or create Proxy Classes.


For a Plugin Assembly that’s already linked to CRM, you get a menu that give you the ability do a little more:


  • Build and Publish: This will build the Project, and update or publish the Plugin Assembly in your the CRM Organization you are connected to
  • Add Proxy Classes to Project: This will open a window for you to selected the entities you want to generate proxy classes for, as well as other settings such as the path (folder in which you want the classes to be created/updates), and which naming convention you want to use for your entities and fields (Display Names or Schema/Logical names)


  • Edit Plugin Assembly Details: Allows changes to Plugins Assembly details such as Location, Isolation Mode. Also gives the ability to configure ILMerge for merging multiple assembles at build time. This is helpful if you are used to creating ILMerge post-build event all the time.


  • Edit Plugins and Steps: This will give you a screen that looks very similar to the Plugin Registration Tool with options to add plugins, register/edit/disable steps, add and edit plugin images etc. Basically you get the same content as the Plugins Registration Tool directly from Visual Studio


  • Download all linked Items from CRM: This option will force a download of all the items that are linked to CRM. In this case, we are talking about the Proxy Classes that were generated using the feature described above.
  • Update all items: This will update CRM with the content of the project, in this case, it will update the plugin assembly using the latest build

Worth nothing, all the configuration (linked items to CRM, CRM connection etc.) is saved in an Xml file that resides in your solution root folder. If you need and want to carry your CRM Solution Manager configuration across multiple environments and for multiple developers, make sure you include it in your source control (it is not done automatically).

Client-Side (JavaScript/HTML) Development

The experience is very similar with to what we get on the server side. Right clicking on the right button will give you a CRM option with a few options.


  • Add Items to Project: Given that it is a web project in this case, the items that can be added to the project are a bit different than what we had in the Plugin project. You can select a CRM Solution, and from there you can download the Charts, Images, JavaScript, Sitemap, Web Files (HTML), as well as generate JavaScript and TypeScript Intellisense files for selected entities.


  • The other options are similar to what we had in the section above:
    • Downloading all linked items from CRM will update all web resources by getting the latest version from CRM
    • Update all items will update CRM with the items in your Visual Studio project
  • Worth noting, individual web resource files in the VS project are linked to their CRM counterpart which means you can publish single web resources by right clicking on them in the VS project and selecting Publish file to CRM


Wrap-up

The Good

  • The product is really not too intrusive. It doesn’t add any project creation template that your solution becomes dependant on. It doesn’t create any additional cumbersome toolbox that you need to open to manage your CRM related operations (no point intended)
  • It is a HUGE productivity booster. One can easily get used to having proxy classes easily regenerated on demand, as well as JavaScript Intellisence. One can also really get used to deploying web resources and plugin assembly without opening CRM or the plugin registration tool
  • The support team is very reactive, I have received an answer to all my inquiries within a day
  • The product is being actively maintained and updated to support the latest versions of Dynamics CRM and Visual Studio

The Bad

  • If you are using CRM Solution Manager for specific things (e.g. creating Proxy classes and Option Set Enumerators), it means one of two things. Either all of your developers need to be equipped with the add-on in case the classes need to be regenerated  or the entire team dependent on one person to regenerate the entities classes when required. If you are the only developer on the project, it will work well for you. However if you are a consultant and need to hand-off the code when you are done, you may not want to us it to generate the proxy classes as people who will maintain the code might not have it to generate identical classes in the future.
  • The price point is a bit high. At $209.95 US per license (with volume pricing available), it is almost as expensive as some of the excellent and proven productivity tools such as Resharper ($300), Coderush ($250). That makes your development environment a bit expensive to set up. Pricey also considering there are free tools like the CRM Developer Toolkit (for which we are still waiting for a new version for VS2015, CRM 2015/2016), some of the tools in the XRM Toolbox and also the CRM Developer Extension developed by fellow CRM MVP Jason Latimer. The latter is a must try, the feature set is impressive and extremely complete! I haven’t had a chance to work with it yet but I will make sure to review it once I do.

All in all, I would recommend the CRM Solution Manager if you are an Organization with Dynamics CRM deployed internally with multiple developers writing code that targets the platform. If you are a solution integrator or a consulting shop, make sure you don’t create too much of a dependency with the tool, because your clients won’t necessarily have access to the add-on.

Hope this help!

For further questions and assistance with your CRM Development tools and environment, or other Dynamics CRM related inquiry, feel free to reach out to us!