Monthly Archives: October 2017

Trying Xamarin (with Dynamics, of course.. but not there yet): Broken AVD system path

As far as mobile development is concerned, I’m an absolute newbie at this point.. So, this might be something obvious for those who have been doing mobile development for a while, but, since I have no idea what’s normal what’s not, maybe this post will help somebody else to get things going a little faster.

I kept getting the following error when trying to start an android virtual device:

Starting emulator for AVD ‘MyPhone’
PANIC: Broken AVD system path. Check your ANDROID_SDK_ROOT value [C:\Software\Android\sdk]!

image

I did some googling, I did some thinking.. I did some cursing, I guess.. none of that was very helpful till I noticed that I had two different SDK folders:

image

image

Aha.. From there, it was straightforward. Update ANDROID_SDK_ROOT system variable:

image

Restart AVD manager, and start the emulator. Back in business we are:

image

Bug or Feature? System administrators can’t see all forms

For a little while now I’ve been wondering if it’s a bug or if it’s a feature that, at least in the more recent versions of Dynamics, System Administrators won’t be able to choose those entity forms that were not assigned to the “System Administrator” security role?

It seems it was different in 2011, and, maybe, in 2013.. But it’s been a while.

Here is an example. There are 3 main forms in the account entity:

image

That MoCa form is assigned to the “Field Service – Resource” security role only:

image

So, even while logged in as a System Administrator, I cannot choose that form:

image

But, if I add System Administrator role to the form:

image

I can, now, choose that form when looking at the account record:

image

This is a bit of a unique situation for System Admins, since, I think, we have access to almost everything else in Dynamics by default (well, another example of where sys admins powers are limited would be personal views/dashboards.. but that makes sense since I probably would not want to see everybody else’s personal views anyway).

Dynamics Tip: Using business rules to sum up more than two fields

When defining a formula in the business rules editor, we can only use two entity fields:

image

So, what are we supposed to do when we have, for example, four fields to sum up (other than creating a calculated field or adding a javascript/workflow/plugin)?

image

Turns out, we can simply add multiple actions to the business rule so that every action will add one additional value to the sum field(and the first action will copy value from the first value field):

image

We also have to remember to add all those value fields to the condition just to make sure the business rule kicks in on all field changes:

image

And, once we have that, here is the end result:

image

It works.. Although, I guess it may still be easier to use javascript for thisSmile

Dynamics, Portals, and Adobe

We have a somewhat unique Dynamics environment here in Ottawa, so, sometimes, I am wondering if what’s happening here is a reflection of the overall trend or if it’s all about Microsoft trying to adapt to the specifics of the local market.

You see, most of the Dynamics implementations here are still on 2015 version of Dynamics, and they are still on-prem. This is a government city, so most of those implementations are for the government departments, and, for a number of reasons, they are not able to utilize Dynamics in the cloud yet.

What it means, for example, is that, right now, there is a clear upgrade path for Dynamics.. but there is, essentially, no upgrade path for the portals. Imagine a government department implementing an ADX 7 portal. A few years from now, they’ll go to Dynamics 2016/365/V9.. whatever the version is going to be. However, what are they going to use as a portal solution?

The interesting part is that there is, actually, a portal solution that’s being promoted by Microsoft locally. To me what’s being offered here looks like this:

image

ADX7 is not an option for new implementations – that’s why it’s pretty much greyed out.

One-Time source code release and community edition versions might be an option BUT they will have to be supported somehow.. and there is no support from Microsoft. Which will certainly make it an issue. So those two options are greyed out as well (may be a little less greyed out).

Then, there are customer portals online. Those are fully supported by Microsoft, but only for the online version of Dynamics. Technically, right now that’s, mostly, not an option because of what I wrote above. It may be an option in the future.

And, then, there is Adobe Experience Manager that’s offering integration with Dynamics (and other sources), and that’s likely a much more powerful product than ADX at this point. So, the relative scale on that image probably reflects the capabilities of those two solutions as well.

Actually, this is not a product of my imagination – this whole post is simply a reflection on the presentation Microsoft hosted earlier today for the government employees/consultants/partners where we saw what Adobe Experience Manager is capable of. I have to say it looked pretty good, though, as usual, the devil should be in the details we have not, really, seen.

Either way, keeping in mind the partnership between Adobe and Microsoft (have a look here, for example), and keeping in mind the announced depreciation of the Dynamics marketing service, I am wondering if we all should get to know Adobe Experience Manager better..

What do you think?

Dynamics 365 (Online): Deleting a user account – what NOT to do

Here is a scenario that may look rather innocent but that may cause a problem that will likely turn into a support call with Microsoft should it happen.

One day, you decide to delete a user account that used to be assigned a Dynamics license:

image

And, then, the time comes when you need to create a user with the same full name again. Maybe because there is a different user with exactly the same full name.. maybe it’s the original user who has come back..

So, you create another user and grant that user access to Dynamics:

image

Before long, you will realize that you created a bit of a havoc in Dynamics because, you see, now you have two users with the same name there:

image

Of course, one of those users is enabled, and another one is disabled. But we are talking about Dynamics 365 Online, so there is no way to update user names for the users directly in Dynamics. And, since one of those users does not even exist in Office 365 anymore, there is no way to update that user’s full name in Dynamics at all!

This does not seem to be such a big issue at the first glance, but think about the data import. Imagine that there is a user lookup field in the entity being imported:

image

If you try importing that kind of file, you will get an error message because.. there is a duplicate:

image

Import functionality in Dynamics does not care if those references are active or not, so it won’t be that easy to get rid of this error, especially keeping in mind that, again, you can’t even change user names for the users that have been deleted from Office 365.

That’s when you may need to contact Microsoft support.. Or, if you keep this issue in mind the next time you decide to delete a user from Office 365(admittedly, it might not be that easy to keep this in mind), you might simply rename that user first, ensure that user’s full name has been updated in Dynamics, and, then, delete that user account from Office 365 safely.

Happy 365-ing!

Dynamics 365 (V9): Progress Indicator API

It has only been a few weeks since I wrote a blog post about Alert.js, but, with the release of V9, we now have the same sort of functionality available out of the box:

showProgressIndicator

As described in the “What’s new for developers” article, there have been some client API enhancements in V9.  In particular, we’ve got two new functions in the Xrm.Utility namespace:

  • showProgressIndicator
  • closeProgressIndicator

 

You can see how the progress indicator looks like above, and here is the code I used to make it work:

function getPrimaryContactEmail()
{
    Xrm.Utility.showProgressIndicator("Loading contact email..");
    setTimeout(delayedLoadPrimaryContact, 3000);
}

function delayedLoadPrimaryContact()
{
    var contact = Xrm.Page.getAttribute("primarycontactid").getValue();
    if(contact == null){
       Xrm.Utility.closeProgressIndicator();
       return;
    }
    Xrm.WebApi.retrieveRecord("contact", contact[0].id, "$select=emailaddress1")
    .then(function(result) {
        var email = result["emailaddress1"];
        Xrm.Utility.closeProgressIndicator();
        alert("Here is the email: "+email);
    })
    .fail(function(error) {
        Xrm.Utility.closeProgressIndicator();
        var message = error.message;
        alert("Error: "+message);
    });
}

 

That’s a web resource I added to the account form, and, then, I added getPrimaryContactEmail as an onload event handler.

You may be wondering why there is setTimeout in this code.. it’s, really, just to make sure that progress indicator shows up for at least a few seconds. Retrieving contact email from CRM does not take long enough to notice the indicator otherwise.

That’s an oversimplified example, of course.. but, every now and then, we might need this ability to display a progress indicator to notify Dynamics users that something is happening behind the scene – it might be a ribbon button making a javascript call that is supposed to do some extensive server-side processing. Or it might be a javascript calling  a custom action. Or it might be any other javascript that’s taking at least a few seconds to complete.

Hope you are enjoying V9 so far!

PS. And, by the way, if you are wondering about that Xrm.WebApi.retrieveRecord call.. That’s another addition to the Xrm namespace, but you can read more about it here: Microsoft Dynamics 365 v9.0: Usage of new OOB WebApi functions – Part 1

Business rules and read-only forms

There is an interesting limitation of the business rules for which there seem to be no other workaround but to use javascript. Imagine the following situation:

  • There is a user who has read-only access to the account record through the security roles
  • There is a business rule that unlocks a field on the account form

In theory, since the user has read-only access, when such a user opens that record in Dynamics, all the controls on the form should be read-only no matter what.

That’s not the case in Dynamics 365 (V9), though, and, it seems, has not been the case in the earlier versions. You can see it on the screenshot below:

  • The form is readonly
  • But I can still select a value into the Parent Account field

And the only reason it’s happening is because I have the following business rule:

In other words, where we might think that security-based settings will have precedence over the business rules, it’s, actually, not the case.

But what happens if I select a value into that field? Well, not a lot  – yes, I can select a value. But no, I cannot save the record. There is no “save” button anywhere. However, if I try to navigate from that screen after that, I will get this warning message:

And, then, if I click “Cancel”, I’ll get “Access Denied”. Which is expected, of course, so, in terms of data consistency, there is nothing to worry about. It seems to be purely a user-interface issue.

As a workaround, we can always fall back to javascripts (where we can use getFormType to add required conditions), though that’s not, always, a good solution if you are trying to avoid code-based customizations.

Anyway, if this is something you’d want to see fixed/added to Dynamics, go ahead and upvote the idea:

https://ideas.dynamics.com/ideas/dynamics-crm/ID0002996

Happy 365-ing!

Data Migration – how do you usually do it?

In the last few years, I worked on a few Dynamics projects that involved data migration, and, somehow, most of the times I would settle on the approach to the data migration which I tried to illustrate on the diagram below:

image

The main reason I usually do it this way is that, when I have that database in the middle, I can do whatever I need using SQL queries and stored procedures, and, once I have transformed all the data, I can simply push it to Dynamics.

For example, here is a sample scenario:

  • I may have contacts in the DataWarehouse
  • I may have contacts in the portal database
  • I may have contacts in Dynamics

 

How would I create a “merged” version of those contacts in Dynamics?

One way to do it would be to use the integration tool to transform that data on the fly, to lookup destination records in Dynamics, to apply conditions and so on. Quite frankly, I think I don’t feel that comfortable with the integration tools to do all that within such tools. Besides, it’s almost like I’m loosing some level of control when doing it that way since I can’t really see a snapshot of the data that’s being sent to Dynamics before it’s sent to Dynamics.

Another way to do it would be to follow the process depicted above. In that case, I would, first, move all the data to the local database. It would not necessarily have to be a separate contact table per data source – it might be a single contact table with a bunch of extra columns. Or it might be a stored procedure that would do some kind of smart lookup. Or it might be just a SQL query that would do a relatively complicated update. In any case, the end result of that transformation process is a table that I can simply push to Dynamics. Instead of using text lookups, I can push actual guid-s. Instead of having to find option set values, I can simply push those values to Dynamics. In other words, that last step (from local DB to Dynamics) does not involve any data transformations (well, maybe it does involve some.. in the form of a SQL view or query).

One strange implication of this approach is that I don’t, really, need most of the advanced features which would be available in some Dynamics connectors and would not be available in others. Because, after all, all I really need is the ability to get data from Dynamics and to push it back, field-to-field. Granted, I need that “local” database somewhere, but, usually, that’s not so much of a problem.

This is why, for example, when I wrote the post below back in March, CozyRoc adapter for SSIS turned out to be almost my favorite when compared to Kingsway (if you don’t need those advanced features, the next thing you want to compare is pricing, and CozyRoc ends up being a winner):

http://www.itaintboring.com/dynamics-crm/dynamics-crm-data-migration-with-ssis-connectors/

However, since I was getting some questions about that comparison, I realized that I had to explain why it was done that way. There is no doubt it all depends on the specific approach to the data migration. Yes, I don’t use some of the advanced features of the KingswaySoft, but, to be fair, Kingsway does offer functionality which is not available from CozyRoc. For example:

  • Text Lookup
  • Local cache
  • Ability to run workflows

 

But, then, most of the times I would not be using it..

Having said that, I’m wondering what’s your experience with the data migration in general and with those Dynamics connectors in particular? How would you normally do it? Which connector would you prefer and why? Let me know.

Dynamics: using setDisabled/getDisabled may cause your javascript to fail

I ran into this myself not so long ago, and I just saw the same problem in the community forums, so this is probably something that’s worth being mentioned in a separate blog post.

Not every control can be disabled in Dynamics using setDisabled method

It might not be obvious from the description of setDisabled method in msdn:

https://msdn.microsoft.com/en-us/library/gg334266.aspx

However, it’s easy to prove.

If you add the following script to a web resource, and, then, add “testControls” as an onload event handler to a form, you’ll likely see an alert message once you open a record in Dynamics:

function testControls() {
var controls = Xrm.Page.ui.controls.get();
for (var i in controls) {
var control = controls[i];
if (typeof(control.setDisabled) == ‘undefined’) {
 alert(“There is no setDisabled method for ” + control.getName());
}
}
}

If, somehow, you don’t see an alert.. add a control that cannot be made read-only (add a subgrid, or add an iframe, or a web resource). Just don’t add a regular field for which you’d have this checkbox in the control properties:

 

Once there is that kind of control on the form, you should see an alert similar to the one I have on the screenshot below – that’s for an N:N subgrid:

 

This applies to both setDisabled and getDisabled methods – if there is no setDisabled, there is no getDisabled either.

Depending on the version of Dynamics, when you try using setDisabled with a control that does not have that method, the error you’ll see might be slightly different – it could be “there was an error with the field’s customized event onload”, or it could be “TypeError: control.setDisabled is not a function at”. However, no matter what the version is, unless you are going to use those methods with some specific controls(for which you know that you can use them), you can easily fix this problem by adding a condition like this:

if (typeof(control.setDisabled) != ‘undefined’) control.setDisabled(true);

 

Workflow or Plugin: which one will run first?

With all those customization options we have in Dynamics, we can do a lot, but, sometimes, it may get a little confusing. For example, we can use worklfows and plugins. Not only that, though.. Both workflows and plugins can be real-time/synchronous or background/asynchronous.

Earlier today I was observing a very interesting behavior. There was a synchronous plugin and there was a real-time workflow in my solution. Actually, I added them to the solution at different times. The plugin had been there long before that workflow was added, so, while adding the workflow, I just assumed that the plugin was working. And it was, but, as it turned out, when there were two of them, the workflow would run first. So, where I was expecting some data to be updated by the plugin before the workflow would start, it was not, actually, happening.

Which contradicts this article:

https://community.dynamics.com/crm/b/workandstudybook/archive/2014/10/14/real-time-workflow-and-plugin-which-one-is-executed-first

However, keep in mind that the article above may have been written for CRM 2013, and I was having this issue with CRM 2015.

So, I had to do some digging (and I did it with 365 online)..

As you probably know, we can define Sdk Message Processing Step execution step order when working with the plugin registration utility. Really what it does, it just sets the “rank” attribute of the SdkMessageProcessingStep record:

https://msdn.microsoft.com/en-ca/library/mt622430.aspx

Plugins should not be that different from workflows, so I figured there would be an sdkmessageprocessingstep record for each workflow as well. And, indeed, there is. Actually, if you use Advanced Find, you can see all Sdk Message Processing Steps, including those associated with the workflows.

Unfortunately, we can’t add “rank” attribute to the columns there, and that’s what I really wanted to see.

When it comes to 365, we can use this kind of link to display all those message processing steps:

https://<ORG_URL>/api/data/v8.0/sdkmessageprocessingsteps?$select=createdon,rank&$orderby=createdon%20desc

This will display createdon & rank attributes for the sdk message processing steps, and all those records will be ordered by createdon (the most recent record will show up on top of the list).

Here is what I got for a background workflow:

And here is what I got for a real-time workflow:

Those results were the same for create/update messages.

If you are wondering what’s that 2147483647 rank on the first screenshot, it’s, actually, the biggest integer (int32) number you may have. In other words, you can’t push it any farther in the execution order.

However, when the rank is 0, you can certainly use negative ranks, but, normally, you wouldn’t. So, normally, all those steps having rank 0 will run before anything else.

And, by default, plugin registration tool will set execution order to 1 when adding a new message processing step.

Therefore, to summarize all this, it seems that default workflow/plugin execution order is, actually, different in 2015+ versions:

  • Real-time workflows will, normally, run before synchronous plugins
  • Background workflows will, normally, run after asynchronous plugins