Showing posts with label Microsoft Dynamics. Show all posts
Showing posts with label Microsoft Dynamics. Show all posts

Tuesday, October 14, 2014

How to debug a sandbox plugin in CRM 2013 online

How to debug a sandbox plugin in CRM 2013 online

Preface

Debugging a sandboxed plugin in CRM 2013 online may sound a little obscure at first but don't you deny that it would be really life saver. Maybe you've given up the idea and instead decided to do something that I call poor man's debugging - throwing InvalidPluginExecutionExceptions everywhere and hoping to find a solution? I admit, I used to do that a lot too but this is just wrong. Throwing exceptions is not a solution for debugging, it is solution for handling exceptions and should stay that way.

In this blog post I'm teaching you, step by step, how you can debug a plugin in CRM and save a huge amount of time and effort in the future.

First we go through what you'll need. You probably own all necessary components already since you are a CRM programmer.

Then I explain an example scenario that I'm using while going through this debuggin process.

You may now close all other tabs in your browser. This blog post contains all you need in order to debug a plugin in CRM Online.

What you need

  1. Plugin to debug
  2. CRM 2013 online (although this might work for on-premises as well)
  3. CRM 2013 SDK
  4. Visual Studio (I'm using Visual Studio 2012)

Scenario

Let's pretend we are developing a plugin that has to generate an email address for a contact. Email address is generated by using contact's full name and by adding a fixed "@exampledomain.com" to the end. 

We've created a plugin that'll be fired always when a contact is created or updated (running a plugin on every update is not preferred in this case but just play along). 

Both steps are registered on pre-operation stage of execution.

Below is my plugin code. Note that I've divided some of the common plugin logic to its own class (Plugin.cs) which we are inheriting in our actual plugin. 


So what happens there is we take target entity's full name property and add "@exampledomain.com" to it. Then we assign that new email string to entity's emailaddress1 property. Since this is a pre-operation plugin we don't have to call update.

This plugin works well on create because full name is business required field. But for some reason on update this is not working... Well we all know the reason already, but let's pretend we don't.

It's debugging time!

Debug a plugin

Step 1
Open your plugin registration tool. It is located in SDK\Tools\PluginRegistration folder.


Step 2
While plugin registration opened you want to install something called a profiler. All you need to do is to press "Install Profiler" and wait for a moment. 



When the profiler is installed (when you see "Profiler Installed Succesfully") press Ok. 

Note: This (profiler) creates a new managed solution to CRM. As I was writing this tutorial something weird happened (CRM happened) and my plugin registration tool lost a connection to CRM. I wasn't able to connect CRM for a little moment so I went and deleted that managed solution from CRM manually. I don't know if it was only coincidence or if it actually helped but everything worked normally after that. So that's something to keep in mind for sure!

Step 3
Choose a plugin and a plugin step you want to debug.

As described in the scenario our plugin is crashing on update event. So we want to debug our plugin on update step / event. 

Highlight a correct step and press "Start Profiling"



Step 4
Set up profiler settings. You may want to leave them as they are. Press OK when ready.



Step 5
Once you've started the profiler you have to raise an event that will fire the plugin. In our case that means we have to update an existing contact.

I'm updating Fernando Alonso's job title to 1st driver which will raise an update event but will also crash our plugin (well, you know why don't you). When that happens a profiler gives us a log file that we have to download and store locally for further use.

Download the log file and then close business process error popup by pressing ok.



Step 6
Go back to your plugin registration tool and press debug.



Step 7
Replay Plug-in Execution popup opens on the screen. There are three fields that has to be filled.

1. To "Profile" field search the log file you just downloaded in step 5.
2. Assembly Location: To this field you need to search for your plugin's DLL file. When you are building your projects in Visual Studio it creates a debug folder under a bin directory. Use the DLL file from the debug folder.
3. Select the right plugin

Do not press Start Execution yet



Step 8
Open Visual Studio and your plugin solution / project if not already opened.

Add break points to your code. 

So from now on it works as normal debugging. I add one break point to beginning of the plugin.



Step 9
Attach Visual Studio to PluginRegistration process.

When Visual Studio and your plugin solution / project is opened go to Debug -> Attach to process.



Step 10
Select PlugingRegistration.exe from the list. If you have more than one opened at the same time make sure to select a right one. Then press attach. Your Visual Studio will go to a debug mode.

Step 11
This is the moment we've been waiting for. Go back to plugin registration tool and press "Start Execution".



Step 12
Now you can actually debug your code, step by step!



Step 13
Enjoy! When you're done stop profiling and remove profiler. I'm sure you'll find out how, just do the steps in reverse order :)

Final step
Find the problem and fix it.

For those who wonder the problem was that target entity didn't carry full name property because it was not changed and thus not passed for the execution context. That's why we got "The given key was not present in the dictionary"


Final words

Thank you for reading. Hopefully I was able to clear things out. This may seem little overkill but trust me on this, it'll save you a lot of time on a long run.

Please do not pay too much attention to code in this post. I wanted to keep it simple as possible. Don't do what I do, do what I say :)

Monday, August 18, 2014

How to edit Microsoft Dynamics CRM 2013 command bar / ribbon by using Visual Studio 2012 and schemas

How to edit Microsoft Dynamics CRM 2013 command bar / ribbon by using Visual Studio 2012 and schemas

NOTE: Applies also to Microsoft Dynamics CRM 2011 and probably to other versions of Visual Studio as well

NOTE: In CRM 2011 what used to be called Ribbon is now basically called Command Bar in CRM 2013 even though it's not basically the same thing. Ribbons are available in CRM 2013 as well (Outlook client for example).

Preface

Usually I would recommend editing MS CRM 2013 / 2011 ribbon / command bar by using 3rd party tools such as Visual Ribbon Editor or Ribbon Workbench.

Sometimes though, it is desired, that editing is made by hand. You'll face these situations more likely when you don't have an access to install 3rd party softwares or you just wanna be hardcore... or any other reason.

I would divide editing (manual editing) process into five steps
  1. Create a solution that contains concerned entity and then export the solution.
  2. Unzip solution
  3. Edit customizations.xml
  4. Zip files back to one package
  5. Import .zip file back to CRM
While steps 1, 2, 4 and 5 are pretty simple and self explatonary step 3 can be done many different ways.

You could just open Notepad++ and start editing and hope that everything is in place when you import your solution back. Or you could open Visual Studio, attach schemas from the SDK and make your life much easier.

You will need

Step 1. Create a solution and export it

The first step is to create a solution that contains entity / entities whose ribbon(s) you want to edit. You could just export the default solution but for the sake of the peace of mind I recommend you to create a new solution that contains only entities you really want to edit. Otherwise your customization.xml will be really big and hard to read (even with modern editors such as Visual Studio). In this example I'm editing account's command bar.



Step 2. Unzip solution

Unzip the solution to any folder you wish. You'll end up with at least these three files



Step 3. Edit customizations.xml

Now this is the part actual work happens. First I want you to open customizations.xml with your Visual Studio.

Then you should open File Properties window. You can open it from View -> Properties Window or by pressing F4.

After that open Schemas window by pressing the button with three dots in it (see picture below).



Now select the following schema files (.xsd files) from the CRM 2013 SDK (SDKFolder\Schemas) by pressing Add... button



Then click OK. Now you may wonder how this will help you. When you attach these schema files to your xml file it tells to Visual Studio automatically check your xml file against schema files. So it's real time validation.

But even better advantage (imo) is that you'll get Intellisense. So no longer you need to constantly go and see what properties are available and for what node. Visual Studio will tell you.

Take this as an example. I want to add new button to account's form. I know that I need to add custom action node under custom actions but I'm not quite sure how to continue from there. I could go to MSDN and find out, or I could save time and let Visual Studio tell me.




So as you can see I wrote only "<" and Visual Studio told me that under CustomerAction node there should be CommandUIDefinition. If I just add CommandUIDefinition and leave it like that Visual Studio can tell me that it is incomplete and that I still need to add something before it matches the schemas.



So it goes without saying that this is really neat feature and it can save you alot of time. The good rule of thumb is that when your xml passes validation it should be okey for importing. But do not take that for granted either.

Step 4. Zip files back to one package.

Again, this should be piece of cake. Just make sure that your folder structure is same than when you unzipped exported solution. Some packaging softwares tend to add one extra root folder if you're not carefull.

Step 5. Import solution (.zip file) back to CRM

Import your solution back to CRM and enjoy your customizations.

More reading

For more reading this is good place to start http://msdn.microsoft.com/en-us/library/gg309639.aspx

Saturday, October 12, 2013

Edit command bar / ribbon in Microsoft Dynamics CRM 2013

As Microsoft Dynamics CRM 2013 came out the ribbon was excluded with couple exceptions. Instead of ribbon we now have something that's called "command bar", well, because it is a command bar. However, you could think it as a "ribbon in disguise" because all modifications are still to be done through RibbonDiffXml. You can modify your RibbonDiffXml by hand or you can make your life much easier and use Ribbon Workbench software / solution. It will allow you to modify both your command bar and the ribbon. Some few entities / forms in Crm 2013 still use ribbons. Outlook client use ribbons in a certain depth as well so it's definitely something to keep in mind. I also recommend to take a look at the CRM 2013 SDK as it can help you to understand this whole concept.

Example

In this example I'm adding a simple button to my custom entity's command bar

RibbonDiffXml:


And here is what it looks like. Notice my custom webresource icon. You can find tons of icons in CRM SDK.




And this is how Ribbon Workbench looks like. I definitely recommend using it but of course it's always good to know what happens under the hood!



Resources:

Thursday, October 10, 2013

Business rules in Microsoft Dynamics CRM 2013

Business rules in Microsoft Dynamics CRM 2013


Microsoft Dynamics CRM 2013 has been released a little time ago with a lot of new features and changes.

Business rules are one of the new features in CRM 2013. Business rules are relatively easy, well, business rules, that you can create through the user interface. Let's say you want to show or hide a certain field depending on another field's value. That would have take some javascript coding with CRM 2011 but with CRM 2013 you can actually achieve this by using only UI. So no programming needed, which is of course always welcome - especially for programmers.

So what can you do with business rules? Below lies a short list of different possibilities

  • Show error message
  • Set field value
  • Set business required
  • Set visibility
  • Lock or unlock field
So very basic but indeed very helpful stuff. Let's take a look at how to actually implement a business rule.

Show or hide a field using business rules

Example:

I have created an xRM system which I use to keep track of my sport activities. I have created a custom entity type named "Sport activity". In the sport activity form I have a drop down list of different sport activity types (including running, cycling, badminton, football). I also have a "Distance" field in the form (hidden by default) and I want to show it only when I've selected a certain sport activity type (such as running or cycling).

So what I need to do is to create a new business rule that'll set distance field visible when the sport activity type equals running or cycling. I can start this by opening a form designer and double clicking the sport activity type -field. There I see Business Rules tab with the "New" button. Refer the picture below.


Click "New" and fill the form. My business rule looks like this



Notice the Scope option on a top right hand side corner. It means that this business rule applies for Information form by default. You can change the value to be "All forms" for example or if you've created a custom form you can set it as a scope.

When you're ready simply Activate your business rule and you're on the go.

Note that you have to create another business rule to hide the distance field in relevant cases. Otherwise it would never go away after the first time it is set visible.


Tuesday, February 12, 2013

Import data from Excel to MS Dynamics CRM

Hello, let's take a quick look at how to import data from excel spreadsheet into the Microsoft Dynamics CRM. There are two things you have to do (apart from collecting all data you want to import of course).

1. Download a template

First, you need to download the excel template from Microsoft Dynamics CRM. By doing this you ensure that after you have populated it with your data you are still able to import it back without any problems. Go to the entity's page you want to import (leads, opportunities, accounts, etc.). Then click "Import Data" from the data tab inside the top ribbon and select "Download Template for Import". Please refer the picture below.

Save the template in any place you find suitable. Note that the template is actually XML file, so you don't necessarily need Microsoft Excel in order to populate it.

2. Import the populated template

Now once you have filled all data you are ready to import your file back. To do this go back to the entity's page you want to import and at this time select "Import data" from the same button as earlier. The rest should be self explanatory. Just follow the import wizard.

Monday, July 30, 2012

How to get an entity by its id using javascript

How to get an entity by its id using javascript

Short answer

Click here for a short answer.

Long answer

Step 1

The first step is to get an id of an entity whose information you'd like to return. In most of a cases you have a lookup field where you have some entity selected and you most likely want to return information from that particular entity. Notice that you can't really use only Xrm.Page.getAttribute('lookupfield').getValue() for the lookup field because instead of returning the entity it returns a lookup item which is only a link to the actual entity. However we are using it for getting the id. Why we can use it is because the lookup field's value contains actual entity's name, logical name and more importantly the id. The id in turn can be used on a step 2 when reaching out the entity itself and rest of its data.

To get entity's id from a lookup field use

Xrm.Page.getAttribute('lookupfield').getValue()[0].id;

It returns the id in a following form {FD140AAF-4DF4-11DD-BD17-0019B9312238}. We have to get rid of the braces though in order to use it in a further stage. You can use for example javascript function replace() and replace any braces with nothing. See JavaScript replace Method.

Xrm.Page.getAttribute('lookupfield').getValue()[0].id.replace('{','').replace('}','');

Depending on your needs you can save the id straight into a variable or make a function that returns the id when called. I use the function

function getId(){
return Xrm.Page.getAttribute('lookupfield').getValue()[0].id.replace('{','').replace('}','');
}

Step 2

Now when you know how to get the id from the lookup field let's get the fun started. The key element of the whole process is the XMLHttpRequest object. If you don't know what that is or how to use it please refer The XMLHttpRequest Object. Let's start building our function. Give it a meaningfull name.

function getData(){}

Now we have it. At the end of this tutorial that function will have an access to the entity's data we are looking for. First we have to create a new XMLHttpRequest object.

var request = new XMLHttpRequest();

Next we have to use XMLHttpRequest.open() method to assign some information for a pending request. It takes three different parameters.
  1. Method to use to open the connection
  2. Url to the data source
  3. Whether the request is asynchronous or synchronous.
Before we can use the open() we have to define the url to the data source. Below I briefly show you how to construct the url. For more information about URI Conventions I recommend to check out the OData Protocol URI Conventions. Anyway, the url consists of three parts.
  1. Root URI
  2. Resource path
  3. Query
Root URI is constructed in a same manner in all CRM 2011 systems.

var rootURI = Xrm.Page.context.getServerUrl() + '/xrmservices/2011/organizationdata.svc';

Resource path in turn depends on what type of an entity we are looking for. The name is always in a format like <EntityType>Set. For example in case of an incident it looks like


var resourcePath = '/IncidentSet';

Then comes the query which greatly varies depending on your search conditions. In this tutorial we are searching entities by them ids and thus the query is relatively easy. How to construct more complex queries see the OData Protocol URI Conventions once more. The query in this example looks like following

var query = '(guid\'' + getId() + '\')';

What happens here is we are putting the id that our function returns between (guid' and '). Notice that \' stands for an apostrophe that is counted as a string. You could do this apostrophe adding during the step 1 when we were using replace() functions. I personally prefer the current way though because I might need the id somewhere else in a different format for example.

We are now ready to use XMLHttpRequest.open() method since we have all three parameters available. Our getData() function should look like this.

function getData(){
var request = new XMLHttpRequest();
var rootURI = Xrm.Page.context.getServerUrl() + '/xrmservices/2011/organizationdata.svc';
var resourcePath = '/IncidentSet';
var query = '(guid\'' + getPalvelupyyntoId() + '\')';
request.open('GET', rootURI + resourcePath + query, true);
}

Let's finish the XMLHttpRequest by adding two custom HTTP headers, telling what to do when the request is sent and finally sending it. Add these two custom headers that indicates the content type.

request.setRequestHeader('Accept', 'application/json');
request.setRequestHeader('Content-Type', 'application/json; charset=utf-8');

Yes we are using JSON (JavaScript Object Notation) for returning the data and for that you will need the JSON in JavaScript library. I also recommend to visit JSON website which nicely introduce you to JSON in a case you don't know what it is.

Now let's tell our request object how to act when it is sent. In other words when ever the ready state is changed. For that of course we will use good old onreadystatechange event. You can do this many ways but in this case I prefer using so called anonymous function which has no identifier. I leave the function body empty now for the sake of simplicity. We add the body later on.

request.onreadystatechange = function(){};

Then the final step is to send the request by using send() method.

request.send();

Our getData() function should look like this right now.

function getData(){
var request = new XMLHttpRequest();
var rootURI = Xrm.Page.context.getServerUrl() + '/xrmservices/2011/organizationdata.svc';
var resourcePath = '/IncidentSet';
var query = '(guid\'' + getId() + '\')';
request.open('GET', rootURI + resourcePath + query, true); 
request.setRequestHeader('Accept', 'application/json');
request.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
request.onreadystatechange = function(){};
request.send();
}

Basically if you would run the code above it would send the request and even run the anonymous function we attached to the event, but of course nothing significant wouldn't happen because the function body is empty. For that we as a final step we are going to add the function body in which you have the access to entity data.

Remember that the function is called every time when the ready state is changed. For that reason we have to make an if statement to check out what is the current state. We don't want to perform any functionalities if any data is not available. See readyState property documentation for more information.

if(this.readyState == 4){}

When all the data has been received (or when the ready state equals four) we have to check the status as well. See status property documentation for more information.

if(this.readyState == 4){
if(this.status == 200){
}
}

Now finally inside the second if statement you can start write your code you want to perform. In example below I'm demonstrating how to parse the data into a variable and then referring an individual datum. 


if(this.readyState == 4){
if(this.status == 200){
var result = JSON.parse(request.responseText).d;
console.log(result.CustomerId.Name); // Printing a value to console 
}


Now when you put all together it should look like this.

Final result

function getId(){
return Xrm.Page.getAttribute('lookupfield').getValue()[0].id.replace('{','').replace('}','');
}

function getData(){
var request = new XMLHttpRequest();
var rootURI = Xrm.Page.context.getServerUrl() + '/xrmservices/2011/organizationdata.svc';
var resourcePath = '/IncidentSet';
var query = '(guid\'' + getId() + '\')';
request.open('GET', rootURI + resourcePath + query, true); 
request.setRequestHeader('Accept', 'application/json');
request.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
request.onreadystatechange = function(){
if(this.readyState == 4){
if(this.status == 200){
var result = JSON.parse(request.responseText).d;
console.log(result.CustomerId.Name); // Printing a value to console 
}
} 
};
request.send(); 
}

You can do very powerfull functionalities when chaining requests together. It's extremely handy approach for example when creating auto fills for forms. Don't forget to include JSON though. When you parse the result you can use for each loop to loop through all properties of it.

If you have any questions or so leave a comment below. Thank you.

Wednesday, July 25, 2012

How to hide a tab section in Microsoft CRM 2011 using javascript

How to hide a tab section in Microsoft CRM 2011 using javascript

Short answer

Xrm.Page.ui.tabs.get('tab_name').sections.get('section_name').setVisible(false);

Long answer

Sooner or later you end up in a situation where you have to hide or show certain tab sections based on certain conditions. While I was searching a solution I noticed many people use tab and section sequence numbers when referring a certain section. It works as well but may cause problems when someone modifies the form itself. Hence I prefer using tab and section names instead.

As you already may know Xrm.Page object offers a strong way to interact with forms. For more information check out the Xrm.Page Reference. We are interested in Xrm.Page.ui, more specifically Xrm.Page.ui.tabs and Xrm.Page.ui.tabs section Methods and controls.

The first step is to select a tab in which you want to hide or show a section. You can select the tab by using get() method from Xrm.Page.ui.tabs. As you can see you can refer the tab with the name or number. I find myself using the name more ofter since I think it's more secure.

Xrm.Page.ui.tabs.get('tab_name');

After you have selected the tab you have to select the section. Sections collection has same methods than the tabs collection. Refer Xrm.Page.ui.tabs.sections Collection. By using get() again you can select a section you'd like. Once again you can either use the name or number when selecting a section.

Xrm.Page.ui.tabs.get('tab_name').sections.get('section_name');

Notice that you can also use get() method without any parameter. Method will then return an array including all sections inside the tab. You can then refer a section using normal array element numbering. For example the code below would return the first section inside the tab.

Xrm.Page.ui.tabs.get('tab_name').sections.get()[0];

This is extremely handy when you have to loop through all the sections for some reason.

After you have the section selected you have an access to section methods and controls. We are using setVisible() method to change the visibility of the section. Give a boolean value as a parameter.

Xrm.Page.ui.tabs.get('tab_name').sections.get('section_name').setVisible(false);

That's it. If you are running into any trouble please leave a comment below.

Thank you!