How to set EntityCollection property of service response for unit testing purposes [CRM]

When unit testing CRM C# codes, you may find that you need to mock the response of calls to CRM’s Organisation service. A number of response classes in the SDK contain an EntityCollection property. This property however is null and is read-only, which means you cannot populate it with mock entries – or at least it seems that way.

This will not work:

var mockResponse = new InstantiateTemplateRequest();

//This won't compile as EntityCollection property does not have a setter
mockResponse.EntityCollection = new EntityCollection();

Neither will this:

var mockResponse = new InstantiateTemplateRequest();

//This will give you a run-time exception as EntityCollection property is null.
mockResponse.EntityCollection.Add(new Entity());   

Behind the scene, the EntityCollection property is actually a facade for reading a key from the Results property. The Results property is defined on the base class of all response classes.

You therefore can set and populate the EntityCollection property as follow:

//The mock response
var response = new InstantiateTemplateResponse();
response.Results["EntityCollection"] = new EntityCollection(new List<Entity> { new Entity() });

//response.EntityCollection will now contain one mock entity that we have just configured above.
Advertisements
Posted in CRM, Unit Test | Leave a comment

Getting entity type name, entity code, and entity display name in JavaScript [CRM]

This is a rehash of Michaël Hompus’ post https://blog.hompus.nl/2015/05/28/entity-type-code-using-javascript-only/ to help me remember this very useful trick.

Note that the scripts described in this post are unsupported.

In JavaScript, use Mscrm.EntityPropUtil.EntityTypeName2CodeMap to retrieve the entity type code for a given entity type name, e.g.:

Mscrm.EntityPropUtil.EntityTypeName2CodeMap.new_application   //returns 10008

Use Mscrm.EntityPropUtil.EntityLogicalNameToLocalizedNameMap to retrieve the entity display name for a given entity type name, e.g.:

Mscrm.EntityPropUtil.EntityLogicalNameToLocalizedNameMap.new_application   //returns Credit Application

Depending on how your script was loaded, Mscrm may be null, in which case try looking for it under the parent object instead, i.e. parent.Mscrm.EntityPropUtil…

Posted in CRM | 2 Comments

Mixing early-binding and late-binding with nameof operator in C# [CRM]

There are many benefits of using early-binding when coding against CRM. There are times however when you need to fall back to late-binding, for example when you need to query relationships, or when you need to call Retrieve to optimise performance (as this service call allows you to load only selected fields of a record).

Rather than using literal string, you can use the nameof operator in C# 6 to get the attributes and relationship names. This works because the properties of the early-binding classes are generated based on the attributes and relationship names in CRM.

For example, to get the AccountNumber field of an Account record:

var client = new CrmServiceClient(ConfigurationManager.ConnectionStrings["CRM"].ConnectionString);

//Remember to convert to lowercase.
var accountNumberAttributeName = nameof(Account.AccountNumber).ToLower();

var entity = client.Retrieve(Account.EntityLogicalName, Guid.NewGuid(), new ColumnSet(accountNumberAttributeName));
var accountNumber = entity.ToEntity<Account>().AccountNumber;

And there you have it: late-binding with all the early-binding zen!

Posted in CRM | 2 Comments

Apply filtering to subgrid’s inline lookup in CRM

A common requirement is to apply filtering to a subgrid’s inline lookup on CRM form. For example, you might want to allow users to add only contacts of a particular account (selected in another field) to a contact subgrid on the form.

Just to be clear, the highlighted lookup below is what we want to filter (and what this post is about). There are several posts on the web that talk about filtering the subgrid; but they are about filtering the records that appear on a subgrid, and not the records that appear in the inline lookup that is use to add a record to the subgrid.

1-lookup

Note: The method described in this post is unsupported.

The inline lookup of a subgrid is actually a normal lookup control (more or less), and therefore has the same methods as a normal lookup control. We therefore can apply filtering to this control using the standard addPreSearch and addCustomFilter methods of the control.

It is however difficult to gain access to this control (for a subgrid) as it is not exposed in any of the API. We therefore will need to use unsupported methods to access it.

The subgrid’s lookup control is actually given a control name by CRM, and this name is based on the name of the subgrid. For example, if the subgrid is named grdContacts in the form, the name of the subgrid’s lookup control would be lookup_grdContacts. We can use this name to retrieve the lookup control – but wait..

While you can use Xrm.Page.getControl(“lookup_grdContacts”) to retrieve the subgrid’s lookup, you can only do so after the user has clicked the + icon on the subgrid to bring up the lookup control. Therefore, our code to retrieve the lookup control and call the addPreSearch and addCustomFilter methods on it would need to happen within (or triggered by) the click event of the + icon.

The HTML ID of the + icon has the format [gridName]_addImageButton, e.g. grdContacts_addImageButton. Using this ID we can retrieve the + icon from the DOM and attach code to the click event to retrieve the lookup control and apply our filter.

Below is the code. Please review the in-code comments.


function setSubgridLookupFiltering() {
	var subgridAddButtonId = "grdContacts_addImageButton";

	//Try to get the element from both the current and the parent document.
	var subgridAddButton = document.getElementById(subgridAddButtonId) || window.parent.document.getElementById(subgridAddButtonId);

	//This script may run before the subgrid has been fully loaded on the form. If this is the case,
	//delay and retry until the subgrid has been loaded.
	if (subgridAddButton == null) {
		setTimeout(setSubgridLookupFiltering, 2000);
		return;
	}

	//Local function to retrieve the lookup control and apply the filter. We will queue this function in the click event handler of the
	//Add button's click event.
	var getSubgridLookupAndAddFilter = function() {
		var subgridLookup = Xrm.Page.getControl("lookup_grdContacts");

		//Delay and retry until we can locate the lookup.
		if (subgridLookup == null) {
			setTimeout(getSubgridLookupAndAddFilter, 200);
			return;
		}

		//This is a custom property we are tagging on to the lookup control to ensure that we will
		//apply the custom filter only once when the Add button is first clicked.
		if (subgridLookup.customFilterAdded) {
			return;
		}

		subgridLookup.addPreSearch(function() {
			//Standard logic to build up the filter query string
			var filterQuery = "";

			//filterQuery = "<filter type='and'.....></filter>";
			//..
			//..

			//Standard call to add filter to the lookup control
			subgridLookup.addCustomFilter(filterQuery, "contact");
		});

		//Mark the fact that we have already added the filter so that we won't do it again the next time the user clicks the Add button.
		subgridLookup.customFilterAdded = true;
	};

	//Attach the function to retrieve the lookup and apply the filter to the Add button's click event. Remember that we
	//can only get the lookup after the user has clicked the Add button.
	subgridAddButton.addEventListener("click", function() {
		setTimeout(getSubgridLookupAndAddFilter, 200);
	});
}

Here is another post that uses a similar approach: http://www.bobylog.com/microsoft-dynamics-crm-2015-subgrid-lookup-filter/. This however retrieves the lookup control using a magic sequence of object properties, which differ between versions of CRM, and in my opinion is more prone to breaking in future versions.

Posted in CRM | 1 Comment

Non-admin users cannot see updated group names in form navigation [CRM]

Recently we renamed the group names in an entity’s form navigation. These are the headings that group navigation links to related entities on an entity’s form.

group-name

After deploying the solution we found that only users with System Administrator role can see the updated names. Non-admin users still see the old names, even after F5 and Ctrl + F5 to refresh the browser.

I found the answer on this post http://www.magnetismsolutions.com/blog/11-12-09/Changing_Form_Navigation_Group_Names_Dynamics_CRM_2011.aspx. It turns out that a particular privilege is required to see the updated names, and this is the ISV Extensions privilege. You can find this privilege under the Customization tab of the security role editor.

Posted in CRM | Leave a comment

Solving IIS SMTP mails stuck in Queue folder when using Gmail

It is actually quite easy to setup a local SMTP and routing through Gmail to test sending emails from your application. There are a few good posts on this that you can follow:

I however had an issue where the mails would get stuck in the Queue folder (e.g. C:\inetpub\mailroot\Queue).

I tried turning off Windows Firewall and enabling POP in Gmail but it did not help.

In the end it was because 2-factor authentication was enabled on my Gmail account. Disabling this fixed the issue for me. Here is a help document for disabling 2-factor authentication, just in case you need it: https://support.google.com/accounts/answer/1064203?hl=en.

Posted in CRM, SharePoint | Leave a comment

SPClientSideDeployment now supports deploying assemblies to GAC (On-Prem only)

While these days server-side solution looks as if it’s going out of fashion, the fact is quite a number of people are still dependent on them for various reasons. Back in the days when server-side solution was the only (practical) option, CKSDev was one of my must-have dev tools for its ability to quickly deploy assemblies to GAC and files to the Layouts folder.

CKSDev however does not work with Visual Studio 2015, and it appears the original author is no longer working on it. While there are a few posts on the web with hacks for installing it on VS 2015, some of the commands that I regularly use resulted in exceptions and did not work correctly.

Deploy assemblies to GAC with SPClientSideDeployment

The ability to quickly deploy assemblies to GAC has now been added to SPClientSideDeployment 3.2 (supported for On-Prem only). I know this is not really “client-side deployment”, and it pains me a bit, but at the end of the day what’s important is the productivity gain for developers.

What does it do?

In short, it builds the project(s), GACs the relevant output assemblies and recycle the IIS app pool of the target project.

Which assemblies will be GACed?

This command is enabled on both SharePoint and non-SharePoint projects, and the assemblies that are GACed depends on the type of the target project.

If the target is a SharePoint project, the following assemblies will be GACed:

  • The main output assembly of the target project
  • Other assemblies that are included in the SharePoint Package.package file with the Deployment Target set to Global Assembly Cache

With the Package definition below for example, the Model, ServiceLibrary and SharePointSolution1 (target project) assemblies would be GACed.

1 Package

If the target project is a non-SharePoint project, only its main output assembly would be GACed.

Which IIS app pool is recycled?

Again this depends on the type of the target project. For SharePoint projects, the command uses the OOTB Site URL project property to locate the app pool that should be recycled.

For non-SharePoint projects, the command uses the SharePoint URL project property that is added by this extension.

OK.. so how do I trigger the command?

You can trigger the command in the following ways:

  • Right-click on the code editor of a C# or VB code file and choose Deploy to GAC (SharePoint). The keyboard shortcut key for this is Alt + Q, W. This will execute the command against the active code file’s project.2 Code Editor
     
  • Right-click on a project and choose Deploy Assemblies to GAC (under the SharePoint group).3 Project 
  • From the Tools menu, choose SharePoint Deployment, then Deploy Assemblies to GAC. This executes the command against the solution’s start-up project. The keyboard shortcut key for this is Alt + Q, E.4 Tool Menu

Download it now!

You can download the latest version of SPClientSideDeployment from the Visual Studio Gallery.

What’s next on the roadmap?

Next on my to-do list is to add other productivity features that were found in CKSDev, including:

  • Deploy files to Layouts folder
  • Attach to IIS

I hope you find this new addition useful, and as always, I’d love to hear from you with feedback and suggestion.

 

Posted in SharePoint, SharePoint 2013, SPClientSideDeployment | Leave a comment