Thursday, 25 January 2018

CRM 365 - Business Process Flow - Jump between stages

 The moment when something stops to work without any changes of any type. 

As it happened with me, i know it happened with many developers/customers more.

And as i got really annoyed more people got different feelings as well.

I will explain now what is the issue, in the opportunity entity it seemed the best for the client to use a Business Process Flow to help with a standard process, that is always a good idea, so that was developed against the Opportunity entity.

Everything was going great with the process, and then because of an exception we had to implement something that would allow to Jump from any stage to any stage, so, assuming the Business Process Flow had branches as well, thing could get more complicated. The solution was easy enough, implementing a "On Demand Process" that would change the Stage Id to the one necessary. Until that moment, everything was working with no issues.

However, at some stage, Microsoft just decided that the way the Business Process Flow was implemented was not the best/great, whatever....

What happened, or at least i understood from phone calls with Microsoft was, new tables were created for the purpose and a field "traversedpath" was about to become the Star of that.

Now let me explain what is the traversedpath. Traversedpath is a string field that contains all the guids of every stage until from the first until the current appended with the ',' comma. Trying to be on the brilliant minds that came to that for me it makes sense, so, what's the problem in here? Basically, opportunities created before the Update 9.0 (if i'm not mistaken). 

Everything seemed to work apparently at the beginning, people creating new Opportunity records, and playing around the stages, and jumping sometimes from the first stage to the last one, everything seemed to work more or less.

But, when people started to play around old opportunities, things started to become a nightmare, and now, believe in me, when you have a CRM implementation with many opened opportunities and everybody started to complain about that, then you starting to fill mad(here i don't want to put the name of my actual feeling, could be to strong).

What you do next, with no clue at all, you start to try things, to google and when you find that you not alone, you think, at least i'm not the only one, however, not me, i just thought, not again....

So Microsoft was called for that, and after few hours, something was becoming more clear, but even the code provided was not working 100% for the purpose, then i just tried few more things and i saw some improvements in the tests from the Test team and as well from the Client, scenarios were put on the table and tested in the Sandbox environment.

You can guess what happened, finally production environment was upgraded and then, with a full team of users using the system, more scenarios came into and more problems......

At that moment, and because is a Show Stopper, Microsoft was called again and few more experiences were tried, but at the end nothing conclusive, again i tried few more things and at the moment i believe that i'm really close to the end of the problems, but not 100% sure.

In the Custom Workflow Activity developed first thing done is getting the full path (all stages from the 1st until the current one) and update the opportunity before doing the actual jump of the stage. Below some code that can be seen as example:

Opportunity _opportunityToUpdate = new Opportunity();
_opportunityToUpdate.Id = opportunityId;

//all the guids should be appended in here from the 1st until the current stage
_opportunityToUpdate.TraversedPath = traversedPath;
_opportunityToUpdate.StageId = currentStageId;
_opportunityToUpdate.ProcessId = process.WorkflowId;
service.Update(_opportunityToUpdate);

I have tried to update the opportunity with the newStageId and the traversedpath to the new stage with no luck.

And then my solution, probably not the prettiest one, but it works: 

Going one by one from the current until the one we need.

foreach (Guid stageId in stagesToUpdate)
{
Opportunity opportunityToUpdate = new Opportunity();
opportunityToUpdate.Id = op.Id;
opportunityToUpdate.StageId = stageId;
opportunityToUpdate.ProcessId = process.WorkflowId;


service.Update(opportunityToUpdate);
}

Hope it helps.

Thursday, 14 September 2017

CRM 2016 - Migrating Data Performance Issues (Important to read)

 I'm the kind o person that really likes to do Migration and Integration tasks into and from CRM.

Last time this happened to me i forgot to mention in here, and probably most of you already know, if no, just spend few minutes reading this.

I was importing some data into CRM 2016, the same applies to CRM 2015 and only for creating the Account entity records (few data fields filled) it was giving an average of 1.5 sec for each one. That's really an issue when you need to import thousands or millions of records, if you migrate or integrate only few hundred, you wouldn't loose time trying to understand why.

However, i'm really stubborn, so i had to figure out why.

What would you do at first? First you would question yourself, do i have any PrePlugin or Post-Plugin that would affect the performance? If yes, let's try to deactivate those steps and check if the performance is better.

I have to tell that i didn't have any plugin either Pre or Post Sync that would affect the performance, but then i remembered that CRM 2015 and CRM 2016 usually comes with the Activity Feeds Plugins activated. And that was the real problem, after deactivating them, instead of 1.5 sec in average it gave 80 ms (milliseconds).

My question is why Microsoft ??!!?!??!!? Leave those deactivated and let the partners or developers ask to the customer if they really need that active. 

I wouldn't mind at all to leave active if it wouldn't give any kind of performance problems, but it is not the case, it really gives.


Hope it helps

Friday, 4 August 2017

Dynamics 365 - Business Process Flow

This is a nice to have to guide users in terms of filling information based on stages, for instance:

The information needed to a contact to be a prospect, probably we only need First Name, Last Name and mobile phone. On the other hand, to become an opportunity, we will need some more details.

In this situation i would use this kind of approach, Business Process, because it will be really easy to see by opening the record in which phase of the process the contact is only by looking to the process bar. 

However, using this feature of CRM can be sometimes a little bit disappointing because customizing what the fields do (hiding based on rules, setting required based on others is not possible), i mean, configuring only with the CRM default functionality is not possible.

My personal opinion and because i've been working with CRM on my last 13 years already, using Javascript for this purposes it can be a nightmare in terms of Upgrades of the product.

But, because sometimes you get to a point where a system is already implemented and you don't have the time to redesign the feature, one thing i have to say, just customize with an approach of having some constants with the name of the field, and not use hard-coded all-around.

With this, if the DOM changes, you will need to change the new name only in one place, instead of in all the places you have been using this.

For this example i will give few lines of Javascript that can be used to Hide the next stage button on the Process flow, set the required level of a field and set the field readonly.

var probabilityHeaderFieldName = "header_process_new_probability_1";

//to set required

Xrm.Page.getControl(probabilityHeaderFieldName ).getAttribute().setRequiredLevel("required");

//to set readonly

Xrm.Page.getControl(probabilityHeaderFieldName ).setDisabled(true);

//to hide the next stage button

var nextStageButtonName = "stageAdvanceActionContainer";

document.getElementById(nextStageButtonName ).style.visibility = 'hidden';

Microsoft URL for the Business Process Flow, click here.

Hope it helps.

Tuesday, 3 January 2017

Note Attachment Download giving the message: "Invalid Action" - CRM 2015

 A user was trying to download a note attachment when the message "Invalid Action" just appeared in the browser.


The first thing i did was using my old friend Diag Tool where i saw the exception "The key specified to compute a hash value is expired, only active keys are valid.", i have found as well that in the Event Viewer.


Doing some research i saw that restarting the MS CRM Asynchronous Processing Service or running the executable from the Tools folder inside CRM folder Microsoft.Crm.Tools.WRPCKeyRenewal.exe /R, i could solve the problem.


I did that, i restarted the server and in the end, the same problem. What do you do in this situations, just google it a little bit more, so, after 5 minutes someone had the same issue, and that one more step neededto be done, Clear the Browser Data on the client side was the solution.


Hope it helps.

Thursday, 18 August 2016

Upgrade from CRM 2015 to CRM 2016

 Upgrade from CRM 2015 to CRM 2016 On premise

Yesterday was one of those days that i really like to have, i know, sometimes can be really frustrating because of some problems you have to go trough when performing an upgrade.

I have performed many upgrades since CRM v1.2 and it is always a challenge, for more tests in other environments, when it is to Production, something new will happen, yesterday was not exception.

In a virtual machine just performed the Upgrade, it was really quick and no trouble.

As planned, after hours we just performed the Upgrade in Production with all the scenarios covered in our checklist, almost in the end of the Upgrade, it was on the same step for almost 1 hour (Enabling Read Committed Snapshot Isolation for organization).

After some investigation about what could be the cause of that, my colleague just killed the process in the SQL Server. Than it appeared on the CRM Setup screen a message that was more clear to us, "The operation cannot be performed on database "XPTO_MSCRM" because it is involved in a database mirroring session or an availability group. Some operations are not allowed on a database that is participating in a database mirroring session or in an availability group.". 

At that moment, we understood why the setup didn't go from the same step for that long, my question in here is: Why the setup didn't throw an exception before? It was necessary kill the process that was performing that action in the SQL Server.

So, we just removed the database mirroring, and the setup finished successfully. 

Hope it helps.

Tuesday, 26 April 2016

CRM 2015 oData Vs CRM 2016 Web API – Part 3 – oData Metadata

When another version of CRM gets out, we all have to learn from 0 few things, and regardless the experience we all have, nobody can deny that sometimes it is frustrating when we experience an error/exception for the first time and more time we spend understanding the "why?" without finding the solution more we feel worst.

What i have found on the very start of the painful task of changing the Javascript code to meet the Web API requirements was that the way i was doing few things related to fields and entities just changed, as an example, the lookup field i wrote on my previous post.

To help me on that tedious task of updating or creating records trough the Web API i found my new best friend regarding that matter, the oData Metadata Service.

For who knows CRM, just go to the Settings - Customizations -  Developer Resources - Click to download the oData Metadata, i can tell you that will make your life just much easier when dealing with lookups now in CRM when using them in a custom web resource. In there, you will find the object model used by the Web API.

I have found how i could set a value on a lookup field from that file, the lookups are now the navigation properties, and because of that, sometimes, the Navigation Property name for that specific field is just different from what you used before, and in there you will be able to see what is the name you need to use.

Hope it helps.

Monday, 25 April 2016

CRM 2015 oData Vs CRM 2016 Web API - Part 2 - Setting a Lookup Field with NULL

 On the subject of CRM 2015 oData Vs CRM 2016 i will be posting the main differences that i have found when upgrading my client code to CRM 2016 Web API.

I could start with the methods (Create, Update, Retrieve,....), however, those things are easier to find in the SDK than this specific one.

Previously you could already use a method called Disassociate to set a lookup field to null, but that involves an additional call for each one of the fields to update. So, i can imagine that you would be doing something similar to:

var account = {};

account.primarycontactid = null;

XRM.Rest.Update(account, "accountSet", ...,...,...);

Don't mind with the (...) on the method call, in my case i have a generic class to expose the Odata Organization Functionalities, the point in here is how easy was to set the field to null.

Now with CRM 2016, because we have those lookups as Navigation Properties (please, see my previous post about Navigation Properties on CRM 2016 Web API), to be able to perform the same operation, we need to call the Disassociate method, in my case:

 Xrm.WebAPI.Disassociate(accountid, "accounts", "", "primarycontactid",
                        SuccessCallBack,
                        ErrorHandler, false);

Where the first parameter is the id of the account, the second is the type "accounts" and the forth one is the field to set up as null (remove the relation between those two entities.)

Hope it helps

Tuesday, 19 April 2016

CRM 2015 oData Vs CRM 2016 Web API - Part 1 - Entities Properties

 This is my first post on the subject CRM 2015 oData Vs CRM 2016 Web API.

I will start with for me something that took me some time to understand and use properly when upgrading from CRM 2015 to CRM 2016 on the client side

With the Web API, now we have two different types of fields (properties), the primitive properties and the lookup properties (navigation properties).

Primitive types

OData supports a wide range of data types but Microsoft Dynamics CRM doesn’t use all of them. The following table describes how CRM Organization service types are mapped to OData primitive types.

Navigation properties

In OData, navigation properties allow you to access data related to the current entity. When you retrieve an entity you can choose to expand navigation properties to include the related data. There are two types of navigation properties: single-valued and collection-valued.

The lookup properties as the name says, it represents a lookup (lookup, owner, partylist) in one entity to another, whereas primitive properties are the others (money, string, decimal, integer,status,...)

After a retrieve of an entity data, primitive properties can be used like (account.name), on the other hand, the navigation properties have to be used like 

 account["primarycontactid@odata.bind"] = "/contacts(" + primaricontactGuid + ")";

For more information please follow the MSDN link: 

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

Hope it helps.


Monday, 14 March 2016

CRM 2015 - Developer extensions for Microsoft Dynamics CRM

 Developer Extensions is a set of tools provided in the SDk that intendes to simplify and accelerate development. Usually to be used in Client apps, something like Portals.

 It provide the following capabilities:



Don't forget:

Developer Extensions for Microsoft Dynamics CRM supports deployment for CRM on-premises and CRM Online. However, plug-ins that run in the sandbox on CRM Online shouldn’t make use of any classes or methods in Microsoft.Xrm.Client because certain functionality in that assembly isn’t supported in the sandbox.

Friday, 11 March 2016

CRM 2016 - SDK - New Messages

 New messages available in CRM 2016 below:

Request class

Web API action

Description

More information

CloneAsPatchRequest

CloneAsPatch Action

Creates a solution patch from a managed or unmanaged solution.

Create patches to simplify solution updates

CloneAsSolutionRequest

CloneAsSolution Action

Creates a new copy of an unmanaged solution that contains the original solution plus all of its patches.

Create patches to simplify solution updates

CreateKnowledgeArticleTranslationRequest

CreateKnowledgeArticleTranslation Action

Creates a translation of a knowledge article record.

Create a knowledge article translation

CreateKnowledgeArticleVersionRequest

CreateKnowledgeArticleVersion Action

Creates a major or minor version of a knowledge article record.

Create major and minor versions of a knowledge article

DeleteAndPromoteRequest

DeleteAndPromote Action

Replaces a managed solution plus all of its patches.

Create patches to simplify solution updates

FullTextSearchKnowledgeArticleRequest

N/A

Performs a full-text search on knowledge articles in CRM using the specified search text.

Search knowledge articles using full-text search

IncrementKnowledgeArticleViewCountRequest

N/A

Increments the per day view count of a knowledge article record.

Increment knowledge article view count

SetProcessRequest

SetProcess Action

Sets the process that associates with a given target entity.

UpdateSolutionComponentRequest

UpdateSolutionComponent Action

Updates a component in an unmanaged solution.

Package and distribute extensions using solutions

SRC URL:

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


Hope it helps.

Wednesday, 9 March 2016

CRM 2015 - How to change max number of records per collection

Not the best thing to do in terms of performance probably, but if you need to increase the max number of records per collection, i.e: Rest call to get records and render as a table in a custom page, by default it will bring 50, to increase run the next sql statement in the MSCRM_CONFIG database:

update ServerSettingsProperties
set IntColumn = 250 
where ServerSettingsProperties.ColumnName = 'MaxResultsPerCollection'

Hope it helps.

CRM 365 Cloud - Disassociate 2 records using typescript

In case you need to Disassociate 2 records, please find below the code that allows you to do that.      export async function DissociateE...