Monthly Archives: June 2016

Dynamics CRM: Creating navigation tabs

Once upon a time, there was a project where an attempt was made to use Dynamics CRM business process stages as navigation tabs. I think it happened, at first, because of some misunderstanding of what business processes are and how they are supposed to be utilized. Still, as I joined the team a few months ago, I could still see waves of that activity resonating through the project. Later on, as developers kept running into problems with this approach, it was decided to put that implementation on hold..

However, the idea of having tabs did look very attractive to the business users, and, a few months later, a new request came in.

So, here is a screenshot of what I ended up with. Actually, it’s not a screenshot from the real environment – instead, I’ve created a stripped version of that solution which I deployed on the trial instance of CRM online:

Tabbed navigation

 

The main disadvantage of this approach is that CRM form header will be rendered in the compatibility mode once an iframe is added there. Still, if this is something you’d like to try for your own implementation, I’m attaching a solution which might get you going.

Just follow these steps to start with:

  1. Download the solution file(this one is for CRM 2016): Tabs_1_0_0_0 and import that solution to CRM. It does not have any entities – just a couple of web resources
  2. Choose the entity you want to add tabs to and open a form in the form designer
  3. Switch to the “header”
  4. Add tcs_/tabsIframe.html web resource to the header (use 2 lines for height, no border, and “never” for scrolling).
  5. Now go back to the “Body” of the form and set labels for each of the CRM tabs on that form  – see explanations below

For the labels, just use the following format:

<CRM Form Label Caption>:<Header Tab1 Caption>,<Header Tab2 Caption>…

In other words, start with the label caption. This is what you will see as a tab label on the CRM form. Then add “:”. And, after that, provide a comma-separated list of all header tabs which should be displaying that CRM form tab.

Do it for all CRM form tabs on that form. Again, you can “add” different CRM form tabs to the same header tab.

Here is an example:

3

Now you can save the form, publish all customizations, and test it in CRM.

The web resource you put in the form header will pick up all form & header tabs automatically based on the information you have added to the crm form tab labels, and, as you keep switching through those tabs in the header, you’ll see how corresponding CRM form tabs will be changing their visibility.

PS. It is also possible to create two javascript even handlers: one to respond to the “tab selection” and another one to provide default selection so web resource could highlight one of the header tabs when you first open the form. If you wanted to use that functionality, just add tabSelected(string) and getSelectedTab functions to the form – you can use another web resource for that. For a very simple example of those two functions, have a look at the tcs_/scripts/tabbedHeader.js web resource.

 

 

 

Dynamics CRM: is it more than CRM or is it what CRM is supposed to be?

It will not come as a shock if I say that CRM stands for the customer relationship management. However, I have been wondering lately what it really means to have a tool that can facilitate customer relationships management.

First, let me clarify why the question came up at all. I am a Dynamics CRM consultant, and I have always thought that the best way to keep up with Dynamics CRM is to use it as much as possible. Then, of course, there is “eat your own dog food” approach that dictates that you should be using what you are recommending to your clients. Long story short, I started to wonder if I could use CRM for my own “consulting practice”.

Apparently, there are things I could do with Dynamics CRM, so the next question was how do I get it set up. This is where you have to keep in mind that I am an independent consultant, so I am not, really, too keen on the idea of spending extra 400-500 dollars per month just to get those 5 professional licenses and, possibly, a few extra features for CRM online. Well, I have to say Microsoft does not make it easy for the independent consultants to actually use Dynamics CRM.

Therefore, once I hit that roadblock, I figured that there are, probably, other systems I could use instead. SalesForce was not a consideration – it would be just as expensive. But, then, there are other systems like Zoho CRM, Insightly, YouDontNeedaCRM.. you name it.

That’s where I had to answer the question of what it would mean to have a CRM system that would be relevant to my work. The findings were quite frustrating, and, also, quite interesting. On the one hand, I found that none of those smaller CRM systems come close to Dynamics. On the other hand, I also found that those smaller systems are not, necessarily, that cheap. Not unless you want to stick to the basic versions.

In terms of not coming close to Dynamics, here is what I mean. Most of those systems will not have features like marketing campaigns, invoices, orders, quotes.. They might have limited customization capabilities, might have no workflows or javascripts. They might have no skype integration, no email integration, etc. You might say I’ve been spoiled by Dynamics CRM, and I would probably agree. However, that still illustrates the point: Dynamics CRM can do so much more compared to the smaller CRM systems, and, yet, all that functionality is still focused on working with the customers. It is simply taken much further than regular contact/lead management, but it is still all about customer relationship management.

Here is a very simple example. As a CRM consultant, I may have to create an invoice for my client in the end of the month. I could do it directly in Dynamics CRM or I could use 2-3 different systems if I went with Zoho, for example. So.. Does it mean Zoho is not a CRM system? Or does it mean Dynamics CRM is, actually, more than CRM?

Personally, I think Dynamics is taking it to the extreme, but, as it’s happening, that extreme is becoming the new norm. Yes, invoicing might not be part of the classic CRM. However, invoicing is still part of maintaining our relationships with the customers. Just like field service management might not be part of CRM, yet, again, it’s not something isolated from the customer relationships management. Therefore, the answer to the original question seems to be that Dynamics CRM is what CRM should look like. Including the fact that Dynamics CRM is always evolving into something more advanced.

PS. Unfortunately, in terms of choosing a CRM for my own work this kind of answer is not making it any easier since I have to choose between a great system which is relatively expensive and a much more basic system which is much less expensive. That is a tricky situation – I have a feeling it is going to be all or nothing in my case.

Dynamics CRM: detecting cascade delete in the plugins

If you have a plugin that runs on “delete”, and if you need to detect whether that’s part of a “cascade delete” (in which case you might not want to update some sort of summary information on the parent entity), here is how it can be done:

if (context.ParentContext == null || context.ParentContext.MessageName == “Delete” && context.ParentContext.PrimaryEntityName != “{PARENT_ENTITY_NAME}”)

{

//Your “delete” processing goes here

}

In some cases, you might just want to know that it’s part of a cascade delete without really checking for the specific parent entity name, in which case you might have a slightly different condition:

if (context.ParentContext == null || context.ParentContext.MessageName == “Delete” && context.ParentContext.PrimaryEntityName != context.PrimaryEntityName)

To illustrate the difference, let’s imagine you have an entity with many different lookup fields, yet all those lookup relationships are configured to “cascade all” for the delete operation. In that case, “delete” can be cascaded from different parent entities, and, depending on how you want to handle it, you might either need to know what that parent entities is (first condition above), or you might just be interested to know that it is a cascade delete(second condition).

 

Dynamics CRM: Associate & Disassociate messages in the plugins

I have seen  a few examples of how to handle associate/disassociate messages in the plugins, and I have done it myself multiple times; however, some of those examples don’t work as is, and, more often than not, I have to spend more time than I’d like to on this kind of plugins.

The code below is fresh from the Visual Studio, having been tested in CRM 2013 just now (yes, it is not the latest version.. keep that in mind if something there does not work when you copy-paste it to your plugin and try to use for CRM 2015/2016).

Once the code has been compiled, use PluginRegistrationTool to register the plugin and to create a step for “Associate” and/or for “Disassociate” messages. You won’t be able to define an entity for those messages, so it’s important to verify the name of the relationships in the plugin code before doing anything else.

public class AssociateDisassociate : IPlugin
{

public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

if (context.MessageName == “Associate” || context.MessageName == “Disassociate”)
{

if (context.InputParameters.Contains(“Relationship”))
{

Relationship rel = (Relationship)context.InputParameters[“Relationship”];

if (rel.SchemaName != “{RELATIONSHIP NAME}”)
{
return;
}

if (context.InputParameters.Contains(“Target”) && context.InputParameters[“Target”] is EntityReference)
{
targetEntity = (EntityReference)context.InputParameters[“Target”];
if (context.InputParameters.Contains(“RelatedEntities”) && context.InputParameters[“RelatedEntities”] is EntityReferenceCollection)
{

relatedEntities = context.InputParameters[“RelatedEntities”] as EntityReferenceCollection;
relatedEntity = relatedEntities[0];
}

//check both relatedEntity and targetEntity – they might switch sides depending on what message is being handled and from where it came from

}
}
}

}
}

The not-so-obvious side of Ottawa IT job market

I have been living in Ottawa for almost a year, and one difference I have noticed here is the UNION. Not a SQL union, not that one.. a labour union. Honestly, this is the first time in my not so short IT career where I see a labour union in action, and it is actually huge in Ottawa, since, as I understand it, every government IT employee would be a member of the union, and Ottawa IT jobs exist mostly in the government.

Now, why am I writing about it? I guess it is a bit of a cultural shock:) Nowhere else, not in a single company I worked for, neither in Canada nor in Russia there was a union I would be a member of. Not because I would not join if there were a union – maybe I would.. but there never was a union. Well, this is not to say that I am a member of the union now. No. I work alongside government employees, but I work as a subcontractor.

So, just at a glance, what makes unionized IT employment different here?

Well, first of all I guess it makes certain sense for a union to be around since there is no way the government can effectively deal with every individual employee. Dealing with a union that represents all those employees is, probably, more efficient.

However, as the union contract is negotiated, all union members become covered by exactly the same terms and conditions. Which makes it a somewhat interesting disposition since there is not a lot in terms of what every individual union member can negotiate when accepting a position that is covered by such a contract. Of course, different positions will have different terms in the contract, but, in general, there will be a limited number of positions defined by such a contract.

On the other hand, there are quite a few perks coming with union membership since unions are fighting tough for those. In a way, they are fighting to survive, since they cannot afford to become less attractive to their members. For example, how about having 15 sick leave days per year that you can accumulate over the years? Or how about the rule that new positions should be advertised internally first so that union members could take them before they are advertised to the general public..

That last one, by the way, is, likely, the reason why you will not find a lot of government employees on LinkedIn, or, if you find some of them, their profiles will often look very simple. There is, basically, no need for LinkedIn membership since public sector (“government”) recruitment process is quite different. This is a funny thing to say, btw, since “private” sector looks much more open/public in that sense.

Whether unionized employment is somehow better than non-unionized I don’t know. There are quite a few bright people I met over the last year, and they seem to be happy with their jobs. There are, also, quite a few equally bright people who did not seem so happy. In that sense, it’s not that different from how things look like in any other place, but, apparently, there is some difference in the internal mechanics.. and I will leave it at that – if you are coming to Ottawa for work, be aware of the unions:)