Registering custom client handlers for your business process flow stage handlers –Dynamics CRM

This post is in continuation to the my previous post – https://debajmecrm.com/2014/04/18/control-crm-2013-business-process-next-stage-and-previous-stage-flow-using-jscript/

In the above post I have showed how you can override the OOB next and the previous stage clicks and make your own functions to fire when the next or previous stage movements happen. Please note that whatever I have mentioned in the above post is totally unsupported customization and should not be done unless you do not have any other option to try to.

This comes in handy specially in case of Dynamics CRM 2013 where you do not have stage change event handlers on the client side and you have some complex business logic to validate if the stage movement is logical.

Also for CRM 2015, the addOnStageChange is great addition to the library. But these events fire after the stage has been changed. In case you want to fire something before the stage changes from the client side, you might need to use the trick mentioned in the above link.

However many of my blog readers have reported that the above code is not working for them. After my research I could find that to fetch the OOB event handlers for the next and the previous stage clicks, the above link uses the code below.

$originalNextStageHandler = $(“#stageAdvanceActionContainer”).data(“events”)[“click”][0].handler

However the data API of jQuery has been deprecated from jQuery 1.8 and above.

If you do not reference the jQuery, CRM by default uses the version 1.7.2 of jQuery. You can find the version of jQuery your page is using by opening developers tools of your browser and typing the below code in the console.

jQuery.fn.jquery

However many a times we refer the advanced versions of jquery in our forms and why not. In that case if your form is referencing jquery version 1.8 or later, then the above code would not work.

In that case you would require to change the code to fetch the event handler to the one below

$originalNextStageHandler = $._data($(“#stageAdvanceActionContainer”).get(0), “events”)[“click”][0].handler;

The above code makes use of the private data API in jQuery.

Again a word of caution – It’s an unsupported customization and should not be attempted unless you have no other option.

Hope this helps!

Advertisements

{Fix}–SSRS Reports in Dynamics CRM not running under executing user’s context

Wondering how is it possible. I myself was confused when the one of the developers in our project reported this. Surely I thought it is not possible. There is something the developer is confusing with.

So I checked the report and what I did is print the logged in userid in the report using the function dbo.fn_finduserguid(). And the developer was right, it was not fetching the executing user’s guid in the report.

Also in parallel to that, the reports were not running connecting to the the organization in which they were uploaded. They were running with the dataset specified in the BIDS while developing the report. So I  was pretty sure that it has to do something with the way the report got uploaded.

 

So I logged in the report sever and browsed to the report. There is a trick in the way you should browse the report so that you can troubleshoot it. One of our developers was using the url – /ReporServer">http://<servername>/ReporServer. And below is the screen you get once you browse the url. We have three organizations in our environment and for each of organizations, there exists a report folder in the environment which I have blurred here.

 

image

If you go inside any of these folders, you would find something like below. These are all the guids of the reports you have uploaded for your organization. Not much use isn’t it?

image

 

What you need to is go to URL – /Reports">http://<servername>/Reports. Then go inside you organization folder and click on the Detailed View. And then click on custom reports. Then you would find all the reports that you have uploaded for your organization. Please check for the screenshots below.

image

image

image

 

Now going back to the main topic, I select my report and from the report menu, click of manage and then click on datasources.

image

 

image

 

When you publish a report in Dynamics CRM, internally it configures the connection to use the shared data source for its organization and makes the option of Connect Using to – Credentials supplied by the user running the report.

However in this case, the option ‘Custom data source’ was selected with the connection string that was used to develop the report. I had to black it out due to security reasons.

So first of all I changed the data source to use the shared data source and enabled the option Credentials supplied by the user running the report. Then everything started working as expected.

image

 

So far so good. But why did the report upload like that. What about some other reports which got uploaded in the same way from CRM. Do I have to go and publish each report by changing the data source?

Publishing the reports again using the publishreports.exe utility in CRM.

Open a command window and navigate to C:\Program Files\Microsoft Dynamics CRM\Tools\   and run PublishReports.exe. It requires a parameter to specify your organization name. PublishReports.exe "<Organization_name>".

Hope this helps!

{Fix}–Report Parameter changes not taking affect when uploaded–SSRS Reports in Dynamics CRM

Every day brings a new surprise in the life on consultant. And today was also not an exception.

We had some SSRS reports for our client which required some changes in the default values of multiple parameters for each of the reports. So our SSRS report developer did all the changes which was pretty quick for him. He tested in BIDS and everything worked fine.

Then once I started uploading the reports and viewed each of them, I could see that the default values selection was empty. My initial thought was that there were some glitches from the report side (I should not have thought like that considering how good he is, but still you know humans Smile). I went up to his desk and he showed me how each report is working fine.

Then I realized that it had to do something to do with CRM. I searched some blogs and it suggested restarting Reporting services and all.

Finally we had no other option to delete and re-create the reports. After that everything started working fine.

Please note that before you delete a report, take a note of the all the sub-reports which were referencing it. Because once you re-create the report, you would need the sub-reports to point back to the parent report.

I am sure there must be some better way to get rid of this error. However we had a deadline to meet for our QA team and could not afford to do much R&D. So if you are facing the same issue, deleting and re-creating the report might do the trick for you.

 

Hope this helps!

{knowhow} Clone an entity record programmatically in Microsoft Dynamics CRM using Clone method

Recently in my project the customer came up with a requirement where they needed to clone a record programmatically. They wanted a common API which can be used to clone records of any entities.

Normally the requirement would be like there would be a button on the entity record form called ‘Copy Record’ or ‘Clone Record’ and then once you click that, a new form would open up with the data copied from the parent record. I have explained the same stuff in the blog post – https://debajmecrm.com/2015/01/27/how-to-using-xrm-utility-openentityform-to-clone-all-fields-of-one-record-to-another-in-dynamics-crm/.

However this time, the requirement was a bit different. This time the client needed an API which can clone a single entity or a collection of entities. The function would accept either an Entity as parameter or EntityCollection as parameter.

I was thinking if Dynamics CRM provides something like MemberwiseClone method of C#. Could not find initially anything like that initially and decided to write something of my own. But before that, I decided to go back to the CRM programmer’s bible – CRM SDK. And guess what, CRM indeed has a clone method which does exactly the same stuff I was looking.

Below is the screenshot of the method definition from the SDK.

image

As you can see, the method is present in the Microsoft.Xrm.Client.dll.

With the help of this, you could do something like the below to clone a record.

 

var customer = proxy.Retrieve("account", Guid.Parse("2767215B-C2D2-E111-B664-005056AB021D"), "Columns which you want to copy");
var newCustomer = EntityExtensions.Clone(customer, true); // You can also write customer.Clone(true);
newCustomer.Id = Guid.Empty;
newCustomer.Attributes.Remove("accountid");
proxy.Create(newCustomer);

A small note here. After you clone from the parent record and create a new customer, please remember to remove the primary key fields. Otherwise you would get an error like – Cannot insert duplicate key.

And voila! It worked.

A little bit of more searching and I came across this wonderful blog post. http://inogic.com/blog/2014/08/clone-records-in-dynamics-crm/. A greet post indeed like all other posts from Inogic. Wish I would have searched that before. Smile. It contains multiple ways to clone the record in Dynamics CRM.

 

P.S – The stuff I have mentioned here is only available in CRM on-premise. The Inogic blog gives you a very informative pointer to achieve this across all environments.

 

Hope this helps!

 

{Best Practices} Naming convention for you javascript webresources in Dynamics CRM

Let’s agree to this. In any complex CRM implementations you would end up with lot of client side coding. No matter how much hard you try, you simply cannot avoid them. And why not. With new additions in CRM 2015, the client API of Dynamics CRM is as powerful as it ever was.

However believe me, they can be a nightmare to maintain and debug and if not maintained properly. And here I was in the same situation doing code review for some client. They had huge bunch of custom entities and jscript webresources and they named their scripts like this-

like for account, they have a single file named  ‘account.js’. Similarly for opportunity – opportunity.js.

And all the code related to the that entity is stored in a single file be it the form events, custom ribbon button events, field events and what not. So whatever suggestions I provided, I thought of sharing with the community also since all this far my clients have been greatly benefitted by that approach and still I get a thank you note from them.

Well, then let’s start.

Suggestion 1

————————

Use namespaces in you jscript code like the way you use that in your Plugins and workflows. The biggest advantage of using namespaces is that even if you end up writing the same method in multiple jscript files and all those files are loaded by the browser at the same time, still they would be different since they would be qualified by their namespaces. So what is the convention?

So imagine you are doing some stuff for a company named ‘Constoso’. So the root namespace you can have as Contoso.

example:

if (typeof (Contoso) == "undefined") {
    Contoso= { __namespace: true };
}

Suggestion 2

—————————–

Keep a common helper file that can be used to write down all the utility functions that would be used across all entities and custom HTML webresources. I have seen that in projects with multiple developers working on the different modules, they tend to write up the same method as and when they require specific to the entity they are working. This results in loss of time and well as affects the re-usability and maintainability. A classic example would be something like – getUserRoles() and isUserInRole() methods. So instead of this you can do something like this.

  • Create a webresource named Contoso.Utilities.js
  • Then you can define the methods in the file like below.
  • if (typeof (Contoso) == "undefined") {
        Contoso= { __namespace: true };
    }

    Contoso.Utilities = {
        _getUserInfo: function(){},

       _isUserSysAdmin: function(){}

    }

 

  • You can then include the webresource wherever you need. To call the method of the file, you would need to use the fully qualified name

For e.g

var isAdmin = Contoso.Utilities._isUserSysAdmin();

  • You can then direct all your developers to write any utility function, if not already present, in this file and not specific files for entity javascripts.

 

Suggestion 3

————————————

Name the files as per their intended functionalities. So lets take opportunity entity for an example. For opportunity you can have something like.

  • Opportunity.FormEvents.js – This can be the place for all your form on-load and on-save events that you register for the form. So if there is any error you are getting during on save or on load of the form, you can be rest assured that the origin you can trace from this file.

 

  • Opportunity.FieldEvents.js – Any field on-change events, tab state change events etc, you can place in this field. The good thing is if there is any error during on-change event of some field, you know which file to look into. Also if you follow a specific naming convention for you onchange events like for the customerid field on the opportunity, if you name the event handler like function customer_changed, you do not need to open the customizations and check what is the function name and what file the function is in.

 

  • Opportunity.RibbonEvents.js – This can be very useful. If you place all the custom ribbon button event handler in this file, you no longed need to check the ribbon diff xml to find out which file the ribbon event handler is located in.

 

  • Opportunity.Constants.js – This can be place to store all your constants that you need for the processing. in Plugins and workflows you can use the C# enums instead of hardcoding the values. But in jscript, if you want the same effect, you can just place it in this file.

And off-course not to forget, just backup the code for these files in appropriate namespaces.

Say for opportunity.formevents.js

if (typeof (Contoso) == "undefined") {
    Contoso= { __namespace: true };
}

if (typeof (Contoso.Opportunity) == "undefined") {
    Contoso.Opportunity = { __namespace: true };
}

Contoso.Opportunity.ForEvents= {
    _formLoad: function(eContext){},

   _formSave: function(eContext){}

}

And believe me, if you maintain you stuff like this, you would find it much comfortable to maintain and use in the long run.

 

Hope this helps!

Typify your HTML webresources in Dynamics CRM using TypeScript

Does the word TypeScript sound familiar to you. Hear it buzzing around you and thinking as a dynamics consultant how and when can I use it, then this post for you.

People already expert in typescript, I would rather suggest stop immediately and close this post and move on to something else as this is going to be very basic stuff here and you may feel disasspointed. However I don’t mind if you read till the end. Smile

So let’s get to business. Let me be honest here. I am not a typescript expert. But I have been working my way through developing client side libraries for my client using typescript and gosh! I like it like anything. My intention is not to teach TypeScript here, but to introduce you the flavour of it. I am pretty sure once you finish this post, you will be itching to develop something in TypeScript the next time you get a chance to play with HTML webresource in your CRM implementation.

So what is TypeScript? From the definition in http://www.typescriptlang.org/

“TypeScript lets you write JavaScript the way you really want to.
TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
Any browser. Any host. Any OS. Open Source.”

Pretty explanative I think. So let’s just to a quick demo.

First of all you would need to create a typescript file. If you are using VS2012 or VS2013 version, just navigate to http://www.typescriptlang.org and go to the downloads section and download the installers for VS2012/ VS2013 depending on which version you are.

After you do that, when you open Visual Studio, go to File –> New File –> Scripts-> TypeScript File.

image

In the opened file, paste the following code.

class SecurityRole {
    Name: string;
    RoleId: string;
    BuId: string;

    constructor(id: string, name: string, bu: string) {
        this.Name = name;
        this.RoleId = id;
        this.BuId = bu;
    }   
}

enum UserType { InternalUser = 1, ExternalUser };

class User {
    FirstName: string;
    LastName: string;
    UserId: string;
    Roles: SecurityRole[];
    UserType: UserType;

    constructor(id:string, fName:string, lName:string, uType: UserType) {
        this.UserId = id;
        this.FirstName = fName;
        this.LastName = lName;
        this.Roles = [];
        this.UserType = uType;
    }

    getRoles(): SecurityRole[]{

        return this.Roles;
    }
}

var role1 = new SecurityRole("Role1", "<role guid>", "<bu Guid>");
var role2 = new SecurityRole("Role2", "<role guid>", "<bu Guid>");

var user = new User("<userid>", "Debajit", "Dutta", UserType.ExternalUser);
user.Roles.push(role1);
user.Roles.push(role2);

I have created two classes here – User and SecurityRole

Can you notice the difference here. Does not it look like coming straight out of C# somewhere. OK the variable declaration is bit awkward. But it’s very easy. For e.g – to declare a string in C# you would write something like this.

string firstName = “Debajit”;

In Typescript the variable type comes just after the variable name instead of before unlike C#

So in type script it would  var firstName: string = “Debajit”;

Don’t you agree it’s much more structured and typed. And also it is type safe. So when you compile this to a .js file, if you assign a number to the firstName variable which is of type string, it would throw an error. We would come to that in  a moment.

So you have the full power of constructors here to declare a new instance of the class. Similarly you have interfaces, inheritance, modularity, static variables, private modifiers and what not. Can you imagine all this in you javascript code in such structured manner?

Also did you notice the enum type and how I have used it.

enum UserType { InternalUser = 1, ExternalUser };

var user = new User("<userid>", "Debajit", "Dutta", UserType.ExternalUser);

Yes you have the Enums also here and to get the text of the enum you would just need something like this – UserType[1]. This would give you the text of the enum.

Liking it so far. Let’s see how you can transform this to .js file.

  • Open Visual Studio Command Prompt

image

  • Go to the Path where your TypeScript file is located. Mine is located @ C:\Debajit\Personal\My Projects\TypeScript.
  • Type tsc and then the name of the file. For e.g my filename is User.ts. To compile this to .js file I need to type tsc User.ts

image

  • If there is no error, the .js file with the same name would be generated.

The following is the code generated in javascript. I leave it to you to decide as a programmer which one you would use.

var SecurityRole = (function () {
    function SecurityRole(id, name, bu) {
        this.Name = name;
        this.RoleId = id;
        this.BuId = bu;
    }
    return SecurityRole;
})();

var UserType;
(function (UserType) {
    UserType[UserType["InternalUser"] = 1] = "InternalUser";
    UserType[UserType["ExternalUser"] = 2] = "ExternalUser";
})(UserType || (UserType = {}));
;

var User = (function () {
    function User(id, fName, lName, uType) {
        this.UserId = id;
        this.FirstName = fName;
        this.LastName = lName;
        this.Roles = [];
        this.UserType = uType;
    }
    User.prototype.getRoles = function () {
        return this.Roles;
    };
    return User;
})();

var role1 = new SecurityRole("Role1", "<role guid>", "<bu Guid>");
var role2 = new SecurityRole("Role2", "<role guid>", "<bu Guid>");

var user = new User("<userid>", "Debajit", "Dutta", 2 /* ExternalUser */);
user.Roles.push(role1);
user.Roles.push(role2);

Now let us assign a number to a string variable and then try to compile the same. Say For e.g  user.FirstName = 2;

image

How great isn’t it. C# like features in Javascript.

To learn more about it, read the full documentation about it from http://www.typescriptlang.org. I am still doing that Smile

And do send any more useful materials on this and anything. As much I love sharing knowledge, I like to learn more from others.

Hope this helps!