I have found an old copy of the guide. You can download the guide from here.
Thanks.Saturday, August 9, 2014
Setup and Deployment guide for ‘Performance Toolkit’ for Dynamics CRM 2011
Friday, December 6, 2013
“Run Report” button on custom entities forms
There are 2 different ways to display the “Run Report” button on the custom entities.
By adding the "CommandDefinition” to the ribbon definition of the entity.
- Create a new solution in CRM, add contact entity to the solution and export the solution.
- Open the customization file from the exported solution and look for <RibbonDiffXML> . It will look like the following XML.
- Replace the highlighted line yellow with the following XML
- Save the file and overwrite the Customization file in your exported solution zip file with this file.
- Import the solution zip file and publish it. It’s done.
<RibbonDiffXml>
<CustomActions />
<Templates>
<RibbonTemplates Id="Mscrm.Templates"></RibbonTemplates>
</Templates>
<CommandDefinitions />
<RuleDefinitions>
<TabDisplayRules />
<DisplayRules />
<EnableRules />
</RuleDefinitions>
<LocLabels />
</RibbonDiffXml>
<CommandDefinition Id="Mscrm.ReportMenu.Form">
<EnableRules>
<EnableRule Id="Mscrm.FormStateNotNew" />
</EnableRules>
<DisplayRules>
<DisplayRule Id="Mscrm.ReadReport" />
</DisplayRules>
<Actions />
</CommandDefinition>
</CommandDefinitions>
By using Ribbon Work Bench 2013
Report button can be easily restored using “Ribbon Work Bench 2013”. Check http://community.dynamics.com/crm/b/develop1/archive/2013/09/06/how-to-restore-a-hidden-button-on-the-crm-2013-command-bar.aspx for the step by step instructions.
Note: Make sure in the step 4 of the instructions, “Form” is selected in the upper right corner as shown in the following screen shot.
Thursday, November 7, 2013
Behaviour of the “Add New” button on sub grids in CRM2013
CRM2013 displays the subgrids slightly differently than CRM2011. The “Add New” button on subgrids behaves in two different ways.
Scenario 1
The following screen shot displays the contact grid on the account form.
The “+” icon represents the “Add New Contact” button. When you click on the button, it pops up the search box as shown in the following screen shot.
On click of the button, the system displays the following pop up. You need to click on “+ New” button at the bottom right corner to open a new contact form.
Scenario 2
The following screen display the opportunities grid on the account entity.
On click of the “+” button. the system displays the new opportunity form.
Reason for the behaviour
The difference in the behaviour is because of “Field Requirement“ property of the lookup field.
In I:N relationship, if the “Field Requirement” property of the look field is “Business Required” then “Add New” button will display a new record form. The following screen shot displays “Field Requirement” of “Business Required” for the “Potential Customer” field in opportunity entity.
And if the “Field Requirement” property of the look field is not “Business Required” then “Add New” button will display search box as discussed in scenario 1. The following screen shot displays “Field Requirement” of “Optional” for the “Company Name” field in contact entity.
Thursday, October 24, 2013
addCustomFilter method for lookup control in CRM2013
In the new release, Dynamics team has introduce a new method addCustomFilter. It makes it very easy to apply filters to the lookup dialog. But there is one gotcha.This method can only be called from a “PreSearch” event handler of the lookup control. This event get triggered as the user is about to view results for the lookup.
We can add and remove the event handler to the PreSearch event using addPreSearch(handler) and removePreSearch(handler) methods.
In this blog, I am going to filter the parent customer lookup on the contact entity based on the city of the contact. Here is the code.
Code
function addEventHandler() {
// add the event handler for PreSearch Event
Xrm.Page.getControl("parentcustomerid").addPreSearch(addFilter);
}
function addFilter() {
//check if the city is not empty
if (Xrm.Page.getAttribute("address1_city").getValue() != null) {
var city = Xrm.Page.getAttribute("address1_city").getValue();
//create a filter xml
var filter ="<filter type='and'>" +
"<condition attribute='address1_city' operator='eq' value='" + city + "'/>" +
"</filter>";
//add filter
Xrm.Page.getControl("parentcustomerid").addCustomFilter(filter);
}
}
I am calling the addEventHandler function on the form load event.
The addEventHandler() function is used to attach the event handler to the PreSearch event of the “parentcustomerid” lookup of contact entity.
The addFilter() function will be called when the PreSearch event is triggered.
Screen Shot
In the screen shot above, the lookup is displaying accounts and contacts where city is equal to ‘Renton’
Things to remember
addCustomFilter method takes two parameters ‘filter’ and the ‘entityLogicalName’. The entityLogicalName is optional and if this parameter is provided, the filter will only apply to that entity type. Otherwise it will apply to all types of entities returned.For e.g. customer lookup control display account and contact records. If we don’t provide entityLogicalName parameter, the filter will apply to both account and contact records and if we provide “account” as a parameter then filter will only be applied to account records not to contact records.
Friday, October 18, 2013
Client side notifications in CRM2013- Part 2
Important points regarding form level notifications
- You can display multiple notifications on form.
- The height of the notification area is limited so If you have too many notification then user may have to scroll down to see the rest of notifications.
- The new notification is added at the top of notification area.
- setFormNotification - Xrm.Page.ui.setFormNotification(message, level, uniqueId);
- message- The text of the notification
- level- it decides the icon infront of the message. It can be an “ERROR” or a “WARNING” or a “INFO”
- unique- It can be any unique text string. it has to be unique as we use this uniqueId to clear the notification
- clearFormNotification - Xrm.Page.ui.clearFormNotification(uniqueId);
- uniqueId – it is same that is used to set the form notification
There are 3 parameters for this method
There is only one parameter for this method
For this blog I have created two functions.
- formNotification1 – This function displays an error notification if the value of “noofemplyees” attribute is less than 5.
- formNotification2– This function displays an warning notification if the value of “address1_postalcode” attribute is not 2150.
Code
function formNotification1()
{
//check if the value is greater than 5
if (Xrm.Page.getAttribute("numberofemployees").getValue() <= 5) {
//set the notification with an error icon
Xrm.Page.ui.setFormNotification("Employees number should be more than 5", "ERROR", "noofemployees");
}
else
{
//clear the notification
Xrm.Page.ui.clearFormNotification("noofemployees");
}
}
function formNotification2()
{
//check if the postal code is not 2150
if (Xrm.Page.getAttribute("address1_postalcode").getValue() != "2150") {
//set the notification with a warning icon
Xrm.Page.ui.setFormNotification("Account is not located in Parramatta", "WARNING", "postcode");
}
else
{
//clear the notification
Xrm.Page.ui.clearFormNotification("postcode");
}
}
Result
setNotication VS setFormNotification
| setNotification | setFormNotification |
| set notification on the control | set notification on the form |
| can create just one notification per control | can create multiple notification on the form |
| only supports error notifications | supports error, warning and info notifcations |
| can’t save the form without clearing the notification | can save the form with the notifications |
If you are interested in creating a similar functionality in CRM2011, check one of my old blog How to display a warning message on the CRM form. It looks like Microsoft has copied our idea.
Thursday, October 17, 2013
Client side notifications in CRM2013- Part 1
In CRM2013,notifications can be displayed on form level and/or on field level. This blog will explain How to use notification next to specific control on the entity form.
We can use the following 2 methods to display and clear the notification next to field/control on the form
- setNotification- Xrm.Page.getControl(controlname).setNotification(message) :
2. clearNotification- Xrm.Page.getControl(controlname).clearNotification() :
Remove a message already displayed for a control. We have to remove the notification to save the form.
Here is the JavaScript code I wrote to display the notification if the “No of Employees” entered on account form is less than 5.
function fieldNotification()
{
//get the control
cont = Xrm.Page.getControl("numberofemployees");
//check if the value is greater than 5
if (cont.getAttribute().getValue()<=5)
{
//set the notification
cont.setNotification("The number of employees should be more than 5");
}
else
{
//clear the notification
cont.clearNotification();
}
}
The above screen shot displays the notification next to “No of employees” control.
Note
This method is only available for updated entities. Please check the CRM SDK for the list of updated entities.Monday, July 15, 2013
Asynchronous Patterns in CRM2011- Part 1
I decided to write something about Async patterns and here we go. There are 3 types asynchronous programming patterns.
- APM – Asynchronous Programming model
It is also known as IAsyncResult pattern. It requires a begin and an end method. For example BeginExecute() and EndExecute() methods. We generally calls the end method in the callback method. You can find the examples of this pattern in the Silverlight samples of CRM 2011 SDK .
- EAP – Event based Asynchronous Pattern
The event based asynchronous pattern consist of function/s Async suffice (MethodNameAsync). These async function/s may have MethodNameCompleted event, which will be raised when the operation is completed. For more info please have a look at the http://msdn.microsoft.com/en-us/library/wewwczdw.aspx.
- TAP - Task based Asynchronous Pattern
Task based is introduced from .NET 4.0. The Task-based Asynchronous Pattern (TAP) is based on the Task and Task<TResult> types in the System.Threading.Tasks. The biggest difference in TAP, APM and EAP is the initiation and completion of the async operation in a same method.
TAP is the recommend pattern for future development. In this blog we will talk about using TAP for CRM2011 applications that need async calls for example Silverlight and windows store apps.
Why use TAP
As mentioned above in TAP section, the biggest problem the with APM and EAP patterns is initiation and completion of the operation in separate methods. This force us to put the program logic in different methods. It makes the code difficult to read.The good thing about TAP is that it is very easy to write a wrapper for APM and EAP and expose them as TAP implementations. This word document contains a lot of information about TAP.
Consuming the TAP pattern in VS2012
In .Net framework 4.5 TAP pattern can be consumed using a keyword “await”. An await expression must occur inside the body of an asynchronous method, with return type void, Task, or Task<TResult> for some TResult. The await keyword can also be used with .Net frame work 4.0 and Silverlight 5 by using Async Targeting Pack for Visual Studio 2012.There are also other ways to consume TAP pattern by using methods like “ContinueWith” and “ContinueWhenAll”. For sample code have a look at the Mike Snider’s blog.
Using TAP pattern in Silverlight 5 and CRM2011
In this blog we will talk about how to use TAP pattern with CRM2011 and Silverlight 5. I am going to use soapforsilverlight sample located at \sdk\samplecode\cs\silverlight\soapforsilverlight of CRM2011 SDK.If we look at the code we can see the sample is using the following 2 methods to retrieve and display the accounts names. These methods are defined in MainPage.cs file.
private void AccountList_Click(object sender, RoutedEventArgs e)
{
try
{
QueryExpression query = new QueryExpression()
{
EntityName = "account",
ColumnSet = new ColumnSet()
{
Columns = new System.Collections.ObjectModel.ObservableCollection<string>(new string[] { "name" })
},
Orders = new System.Collections.ObjectModel.ObservableCollection<OrderExpression>(new OrderExpression[]
{
new OrderExpression() { AttributeName = "name", OrderType = OrderType.Ascending }
})
};
query.PageInfo = new PagingInfo { Count = MaxRecordsToReturn, PageNumber = 1, PagingCookie = null };
OrganizationRequest request = new OrganizationRequest() { RequestName = "RetrieveMultiple" };
request["Query"] = query;
IOrganizationService service = SilverlightUtility.GetSoapService();
service.BeginExecute(request, new AsyncCallback(AccountList_ClickCallback), service);
}
catch (Exception ex)
{
this.ReportError(ex);
}
}
private void AccountList_ClickCallback(IAsyncResult result)
{
try
{
OrganizationResponse response = ((IOrganizationService)result.AsyncState).EndExecute(result);
EntityCollection results = (EntityCollection)response["EntityCollection"];
StringBuilder sb = new StringBuilder();
if (results.Entities.Count == 0)
{ sb.AppendLine("There are no Account records in the system."); }
foreach (Entity entity in results.Entities)
{
sb.AppendLine("Account Name = " + entity.GetAttributeValue<string>("name"));
}
if (results.MoreRecords)
{
sb.AppendLine("Only the first " + MaxRecordsToReturn + " records were returned.");
}
this.ReportMessage(sb.ToString());
}
catch (Exception ex)
{
this.ReportError(ex);
}
}
There are two methods “BeginExecute” and “EndExecute” which represent the initiation and the completion of the “Execute” operation. The “EndExecute” is called in the callback method.Now we are going to write a TAP wrapper for this code. The BeginExcecute method is taking 3 parameters request, callback method and IOrganizationService. We are going to do the same in our wrapper code.
public static Task<OrganizationResponse> Execute(OrganizationRequest request,IOrganizationService service)
{
var tcs = new TaskCompletionSource<OrganizationResponse>();
service.BeginExecute(request, (asyncResult) =>
{
try
{
tcs.SetResult(((IOrganizationService)asyncResult.AsyncState).EndExecute(asyncResult));
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}, service);
return tcs.Task;
}
}
TaskCompletionSource is required to get the completed async task. The completion can represents the successful completion of the call, any exceptions and cancellation of the process etc.TaskCompletionSource exposes 2 methods to set result. We are using tcs.SetResult. You can use TrySetResult. The same applies to set the exception for TaskCompletionSource.
Now we have a TAP wrapper. As I explained earlier, we would like to call this method using await keyword and to do that we need to create an asynchrous method. So here is my asynchronous method.
//async function
private async void getAccount()
{
try
{
QueryExpression query = new QueryExpression()
{
EntityName = "account",
ColumnSet = new ColumnSet()
{
Columns = new System.Collections.ObjectModel.ObservableCollection<string>(new string[] { "name" })
},
Orders = new System.Collections.ObjectModel.ObservableCollection<OrderExpression>(new OrderExpression[]
{
new OrderExpression() { AttributeName = "name", OrderType = OrderType.Ascending }
})
};
query.PageInfo = new PagingInfo { Count = MaxRecordsToReturn, PageNumber = 1, PagingCookie = null };
OrganizationRequest request = new OrganizationRequest() { RequestName = "RetrieveMultiple" };
request["Query"] = query;
IOrganizationService service = SilverlightUtility.GetSoapService();
//calling the TAP wrapper
var task = await Execute(service, request);
// Get the results from the task
var response = task.Results;
//Manipulating the result
EntityCollection results = (EntityCollection)task.Results[0].Value;
StringBuilder sb = new StringBuilder();
if (results.Entities.Count == 0)
{ sb.AppendLine("There are no Account records in the system."); }
foreach (Entity entity in results.Entities)
{
sb.AppendLine("Account Name = " + entity.GetAttributeValue<string>("name"));
}
if (results.MoreRecords)
{
sb.AppendLine("Only the first " + MaxRecordsToReturn + " records were returned.");
}
this.ReportMessage(sb.ToString());
}
catch (Exception ex)
{
this.ReportError(ex);
}
}
I have added the contents of AccountList_Click and AccountList_ClickCallback methods to create this async method. As we can see we can get the result of the call in the same method. Now I will call this method in AccountList_Click.
private void AccountList_Click(object sender, RoutedEventArgs e)
{
// calling the async method
getAccount();
}
You are good to go. Please leave some feedback. In next part we will try to create a TAP wrapper for EAP pattern.