CRM Dev Tool for Chrome

A few days ago, Sonoma Partners released a very nice Development Tool. It comes as a Google Chrome extension and it’s compatible with CRM 2011 UR11+ and with CRM 2013. It’s a nice productivity booster for CRM developers so I thought I’d share it. Here are some of the highlights:

  • View Current User Information (domain name, user Id)
  • Form information (entity name, Id, type code and some nice features like show the hidden attributes on a form)
  • Execute Fetch XML statement and view the results

How to use it?

  • Using Google Chrome, install the app from the web store
  • Navigate to a record in CRM 2013 or 2011 UR 12+
  • Press F12 to open the Chrome DevTools Panel
  • Click the CRM DevTools tab on the far right

You can read all the details about the tool on Sonoma’s blog post.

Enjoy!

Advertisements

How to change a Plugin “Run in User’s Context” Programmatically

When you design Plugins for Microsoft Dynamics CRM, you sometime need to have them run as a different user in order to perform operations that a non admin user cannot normally do. This is usually done by using the Plugin Registration tool and setting the value of the “Run in User’s Context” drop down field to a specific value (see screenshot below).

Today I want to show a way to do this programmatically. Our design is fairly simple and the overall goal is to have the appropriate impersonation user being assigned to all required plugin steps automatically without manual processing post-solution import.

  • Create Plugins and steps with the Plugin Registration Tool as usual
  • The name of each plugin that requires to run as an admin user must contain a pre-defined text (in our case [Admin])
  • After each solution is imported to CRM, a plugin fires and look for all plugin steps where the name contains [Admin]
  • Updated the Run In User’s Context field with an admin user defined as per configuration

That’s easy enough. For step 4, where you store the configuration is up to you, it could be registry, XML web resource, custom entity etc.

Here is the code to do it:

Cheers

Dynamics CRM and multi-tenancy

It’s a topic that is often discussed and after Microsoft released its whitepaper on it late last year, I thought it would be interesting to write a short summary of some of the enterprise challenges that it addresses.

Definition

Let’s take a look at a few definitions of the term “Multitenancy

Multitenancy refers to a principle in software architecture where a single instance of the software runs on a server, serving multiple client-organizations (tenants).” – Wikipedia

Multi-tenancy is an architecture in which a single instance of a software application serves multiple customers. Each customer is called a tenant. Tenants may be given the ability to customize some parts of the application, such as color of the user interface (UI) or business rules, but they cannot customize the application’s code.” – WhatIs.com

Multitenancy is a reference to the mode of operation of software where multiple independent instances of one or multiple applications operate in a shared environment. The instances (tenants) are logically isolated, but physically integrated” – Gartner IT Glossary

Relating these definitions to Microsoft Dynamics CRM, we can view the CRM Server installation as the single instance of the application and the CRM Organizations created on the CRM server as tenants. The tenants are technical groupings within the application, such as separate databases within SQL Server.

Common Enterprise Challenges and Solutions based on Multi-tenancy

Function Localization

  • Description: Provide a common core of functionality, but with local functional variations – with “proper” delegation
  • Example: Multi-national company with business models that vary based on market size, legal compliance or other factors
  • Solution: Using multi-tenancy or multiple instances allows each business area or local region to have an independent implementation with its own local variations.

Master data management

  • Description: Provide a consistent, managed core of information, perhaps distributed only Selectively and enable smooth transitions without big bang replacements
  • Example: You may have an organization that operates in multiple areas and the terms/rules differ from one place to another. These different areas may need to manage their master data independently from one another. In these types of scenarios, it is important to maintain the data that is common across the different components and particularly critical is managing changes to that data. While there are different approaches for accomplishing this goal, many scenarios benefit by having a “master” for certain data sets because it provides for change management through that central master data source (master data management, or MDM)
  • Solution: This approach requires that the central master data be synchronized to all instances so that each instance has access to the latest version of the core information

Physical distribution

  • Description: Mitigate network latency
  • Example: For business solutions that support users that are physically distributed over large distances (global deployments), using a single instance may not be suitable because of the implications (such as WAN latency) associated with the infrastructure over which the users connect.
  • Solution: Distributing instances to provide users with more local access can reduce or overcome WAN-related issues, as the access occurs over shorter network connections

Security/privacy

  • Description: Accommodate legislative/national differences (e.g. patient confidentiality, Swiss banking, third-party use)
  • Example: This is usually a resulting of some sort of legal compliance. For example in Canada, healthcare patient information cannot be transferred from one province to another. If there was a national platform, there would have to be a way to prevent people from access data from patients living in other provinces.
  • Solution: In these types of scenarios, some or all of the data is stored locally, and potentially some of the data is stored centrally

Scalability

  • Description: Accommodate extreme volumes and/or extensive use of Service Scheduling; Provide for isolation of workloads (e.g. web site, customer kiosks)
  • Example: While a single instance of Microsoft Dynamics CRM can scale up and out to support the growth of a customer’s business, with very high data volumes or levels of complexity, there are additional considerations.
  • Solution: for scenarios in which groups of users work independently of each other in operational terms, it may be possible to host the groups on separate Microsoft Dynamics CRM instances and to use reporting to combine results across business areas for management oversight

Multi-tenancy Challenges and Solutions Patterns

The whitepapers has a full detailed section on possible solutions to the challenges introduced by multi-tenancy. These challenges come from the fact that the separation has to be managed. You may want to synchronize your metadata, or expose data from on CRM organization within a different organization.

Dynamics CRM – Year Review from my notes…

2013 has been a huge year for us all Microsoft Dynamics CRM professionals. I thought I would take a few minutes to review my blog stats and make a quick review of what has been helpful to people in the communities over the past 12 months.

The CRM development tools is one of the most popular. The idea back then was to build a CRM Solutions deployment utility to help support a development environment that resembles what MVP Gonzalo Ruiz describes on his blog post. With time, this had become a fairly popular tool available on Codeplex and I’ve received a lot of feature requests. Obviously, with all the time that I have, I was able to integrate… almost none of them J. Hopefully, 2014 will be a better year.

The other very popular article is the one about MSCRM and data archiving. It is something that almost every client will ask for prior to buying a CRM solution and there still isn’t a straight answer. It always depends on why you need to archive, how much money you want to spend on it and who is going to do the job for you. With CRM 2013 coming out and SQL 2012, I may dig into some of the new performance metric and write an update on that topic over the next year.

The CRM 2013 Client API series has been a success as well.

For 2014, I am planning to start by writing a more concise article that highlights the changes in the CRM 2013 APIs including client and server operations. I will also spend some more time evaluating ISV solutions which I cannot wait to get my hands on. In the meantime, enjoy the holidays my CRM people!

Cheers!

Managing CRM User Roles Programmatically

You often hear CRM users and admin complain about having to manage the system users’ roles too often. It can be a pain if you have a lot of movement in the company, for example people going from one business unit to another, high turnover rate or fast growing company.

I thought I would share a design idea for making user management a little bit easier for your organization. It consists of a few steps, and it requires some coding skills.

  • Define your business roles and match each of them to a set of CRM Security Roles.
Business Role CRM Security Roles
Sales Manager SalesPeron; Sales Manager
IT Manager System Customizer
  • On the “User” entity, create an Option Set field representing the business roles capture in step 1

Now the fun begins.

  • Create an XML file to map the business role option set values to a set to CRM Security Role names (see XML format in picture below)
  • Upload the XML file to CRM as a web resource
  • Switching over to the plugin side. You need to build a plugin that runs on update of a User record and that that does the following operations:
    • Read the “Business Role” field value on the User record
    • Retrieve the web resource configuration XML file based on its name or ID
    • Parse the XML to get the CRM roles corresponding to the business role selected
    • For each CRM Security Role found, assign it to the user
    • This is what my plugin code looks like:
public override void Execute(IExecutionContext context, IOrganizationService service, ITracingService tracingService)
{
 if (context.MessageName != "Update") return;

if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
 {
 Entity target = (Entity)context.InputParameters["Target"];
 if (target.Attributes.Contains("sa_userrole") && target.Attributes["sa_userrole"] != null)
 {
 SystemUser user = target.ToEntity<SystemUser>();

// Get Security Roles from Configuration
 WebResource wr = GetWebResourceByName(WebResourceName, service);
 string xmlContent = UnicodeEncoding.UTF8.GetString(Convert.FromBase64String(wr.Content));

XmlDocument config = new XmlDocument();
 config.LoadXml(xmlContent);

XmlNodeList crmRoles = config.SelectNodes("/SystemRoles/SystemRole[@ID=" + user.sa_UserRole.Value + "]/Role");
 foreach (XmlNode role in crmRoles)
 {
 Role crmRole = FindSecurityRole(user, role.InnerText, service);
 AssignSecurityRole(crmRole, user, service);
 }
 }
 }
}

/// <summary>
/// Retrieves a CRM Web resource by name
/// </summary>
private WebResource GetWebResourceByName(string webResourceName, IOrganizationService service)
{
 QueryByAttribute requestWebResource = new QueryByAttribute
 {
 EntityName = WebResource.EntityLogicalName,
 ColumnSet = new ColumnSet(true),
 };
 requestWebResource.Attributes.AddRange("name");
 requestWebResource.Values.AddRange(webResourceName);

EntityCollection webResourceCollection = service.RetrieveMultiple(requestWebResource);
 return (WebResource)webResourceCollection.Entities.FirstOrDefault();
}

/// <summary>
/// Find a Security Role by name and business unit
/// </summary>
private Role FindSecurityRole(SystemUser user, string roleName, IOrganizationService service)
{

if (user.BusinessUnitId == null || user.BusinessUnitId.Id == Guid.Empty)
 {
 SystemUser retrieveUser = service.Retrieve(user.LogicalName, user.Id, new ColumnSet("businessunitid")).ToEntity<SystemUser>();
 user.BusinessUnitId = retrieveUser.BusinessUnitId;
 }

// Retrieve a role from CRM.
 QueryExpression query = new QueryExpression
 {
 EntityName = Role.EntityLogicalName,
 ColumnSet = new ColumnSet("roleid"),
 Criteria = new FilterExpression
 {
 Conditions =
 {
 new ConditionExpression
 {
 AttributeName = "name",
 Operator = ConditionOperator.Equal,
 Values = {roleName}
 },

 new ConditionExpression
 {
 AttributeName = "businessunitid",
 Operator = ConditionOperator.Equal,
 Values = { user.BusinessUnitId.Id }
 }
 }
 }
 };

return service.RetrieveMultiple(query).Entities.Cast<Role>().FirstOrDefault();
}

/// <summary>
/// Assign Security Role to a CRM User
/// </summary>
private void AssignSecurityRole(Role securityRole, SystemUser user, IOrganizationService service)
{
 service.Associate("systemuser",
 user.Id,
 new Relationship("systemuserroles_association"),
 new EntityReferenceCollection() { securityRole.ToEntityReference() });
}

At this point, all you have to do is change that field on your users’ form and the plugin will handle assigning the security roles automatically. You may want to implement a way to handle the security roles assigned to users before the business role is changed. If you are planning to use this design or something similar, here are some key takeaways:

  • The same logic cannot be processed at the creation of the “User” record. That is because before being able to assign security roles to a user, the system needs additional information that gets created after the user record is created.
  • The plugin must run as an administrator or a user who has enough privileges to create and assign security roles to a user
  • The configuration is stored in a XML web resource but it could be stored anywhere (CRM entity, external database, flat file etc.)
  • Also note that Security Roles are copied to each business unit, so when looking a Security Role in CRM based on its name, it is important to search in the same business unit as the user’s
  • CRM does not allow to edit multiple user records at the same time

Have fun with this!

Microsoft Dynamics CRM Data Archiving Solutions

As Dynamics CRM consultants, one of the questions that we often get from clients is “how do we archive CRM data when it’s no longer needed”? I’ve seen companies that had to keep all of their data for a certain amount of years for legal reasons. In any case, if you are using Dynamics CRM as a service management tool for a busy call center for example, chances are you are creating a LOT of records at a very fast pace. Imagine having to retain all of the data you created in the past 5 to 10 years on the same system. The size of the database can grow to become extremely large, making every single query a long one and impacting directly the users experience and their trust in the system.

Before I go into details about the available options that I can talk to, here is a quick recap of what Microsoft officially said a while ago about archiving Dynamics CRM data.

  1. Archiving implies moving records from one location, storing those records for possible retrieval in another location, and deleting the archived records from the original location.” Given the complexity of the relationships in CRM, archiving as defined in the previous sentence can be very risky and must imply extensive thought, design and knowledge of the CRM application and database.
  2. An arching solution should not be implemented with the goal of improving system performance.
  3. Instead of deleting records, it is recommended to deactivate them when they are no longer required.
  4. The Dynamics CRM application can support very large databases, it is important to make sure that the hardware and database are configured in order to get optimal performance before looking at Archiving.

Here are some possible approaches that can be used to archive your Microsoft Dynamics CRM data. Before going down that path, make sure this is something you really need, don’t just build an archiving solution because you want to improve your system performance. Do your homework first!

Archiving Method How it work Pros Cons
1 – Create a copy of the database It requires a strong DBA with knowledge of the CRM database to make a copy of the DB, copy all the records that need to be archived to the new DB and finally delete them from their original location. Sounds easy for a DB expert I assume (I’m not!)
  • It’s one of the less expensive solution as it only requires a strong DB developer with knowledge of CRM and an available SQL Server database
  • Not supported nor recommended by Microsoft
  • A DBA with knowledge of the Dynamics CRM database is always required to retrieve data from the archive database
2 – Create a new instance of Dynamics CRM
  • Create new organization or new CRM installation and install the same solution as the one in production
  • Create a mechanism to copy records from the production environment to the new archiving organization and delete them from their original location. This can be done with :
    • A custom .NET application using the CRM SDK
    • Scribe, Microsoft’s CRM 2011 Instance Adapter or other third party providers routines
    • Database scripting (unsupported)
  • The archived records are easy to retrieve (same UI as prod)
  • Access to these records can be controlled by the Dynamics CRM security model
  • Can be done in a supported way
  • Expensive solution that may requires additional hardware, server and/or user licenses for CRM or SQL Server
  • Company ends up maintaining more than one CRM organizations in the long run
3 – Deactivated unwanted records and tweak database Indexes
This is easily the number 1 choice from Microsoft’s perspective. To me, this should be one of the drivers in the CRM application design. The lifecycle of all records that are created (except for master data) should always be to:

  • create record (with active state obviously)
  • do work
  • deactivate record after the job is complete (set state to inactive)

In many systems that I have seen, some records just remain active forever, even though they are old and on longer required in the active records view.

Also, it is important to create SQL indexes to enable a faster retrieval of active records.

 

  • This method does not involve the deleting on any record from the CRM database which is what MS recommends
  • It forces the application to be designed with best practice for records lifecycle management
I could write down that the down side is that records remain in the CRM database but again, you are not archiving simply because you want to reduce the size of your database…
4 – Create and store custom archive reports This is an interesting one. I’ve personally recommended using this solution to capture the history of successful workflows execution prior to deleting them from the system.
The idea is to create custom reports containing information from the records that are no longer needed in the system. Once the reports have been created, they can be stored in a document management system or sent by email. After that, then the records can be deleted from the CRM database.
There are many ways to create reports in CRM so I won’t spend time discussion that topic here. A simple Google (or should I say Bing searchJ) will give you plenty of starting points.
  • Lots of options for reports creation and execution (3rd party software, SSRS, scheduling jobs, custom workflow activities etc.)
  • Can be done in a supported way
  • What used to be CRM records are now lines of text in different reports
  • Records must be saved in a managed location (example: doc management system with redundancy instead of external hard drive for the system admin…)
  • Access to the reports must be controlled
  • Ability to search for archived information can be limited and/or very painful in flat files
  • Building the reports can be expensive :
    • Report design can take time
    • Development cost depends on the tool used (SSRS, 3rd party…)
5 – Create a custom Archive Database
This is very similar to option 2. The difference would be instead of creating a new instance of CRM, you can create a custom database where you would only keep the information that you need. This database would be populated by a custom .NET app, third party data migration tool routine or database scripting.
Optionally, a custom UI can be developed to enable administrators to search through the custom database.
  • Tailored archiving solution, enables for more granularity and focus on retaining only the information that is required
  • If done well and if CRM solution(s) doesn’t evolve too much over time, it’s a one effort and maintenance should be easier than maintaining 2 CRM instances
  • Can be done in a supported way
  • Expensive to build (requires deep analysis and development time)
  • Custom database must be maintained
  • Security is no longer controlled by the Dynamics CRM application

I personally like solution 5 better but it’s only because I’m a developer and I’d enjoy having to design the new database and the archiving tool. Of course, every company has its own preferences and resources with different set of skills. This should all be taken into consideration prior to deciding what solution to use. These are only the ones that I came up with, there are certainly other options out there.

Hope this helps!