Wednesday, October 30, 2013

Quick Views in CRM 2013

One of the simplest and most exciting features of CRM 2013 (Orion) is the ability to embed and display fields from the parent entity in the form a given record. This feature is not nearly as promoted as other features but I like it so much I will write about it.

Many times in the past I have struggled with the need to include fields from a related entity in the form of a given record. Typical scenario is that you would want to include the account number and the primary contact of the account in the form of a given case for which the customer is an account. Additionally, if the customer of the case is a contact, then I’d like to display in the case form the contact name, contact phone number and list of activities associated with the contact in the case form. While this was a nightmare to implement in previous version of CRM (require custom web resources that query and display data from related entities), all this is possible very easily out-of-the-box with MS CRM 2013 without having to write a line of code.

First, I will define the quick view forms for contact and account which I will later include in the case form:

image

image

image

 

Now that I have defined the quick view forms for both the accounts and contact, I can modify my contact form to include the related information form the account/contact. I have created a “Customer Details” section in the case form and will now insert the quick view forms I defined earlier:

image

 

Then I need to specify the quick view forms that I will use and for which lookup field it applies:

image

 

After I publish my case form, this is what it looks like if the contact of the case is an account:

image

 

If I change the customer field on the case, the form is updated dynamically and the “customer details” section is updated to display the contact quick view form I defined:

image

 

You can see that I can even insert sub-grids for records related directly to my lookup field (in this case activities related only to my customer contact). It is also  worth noting that fields from the quick view form are always read-only (e.g. From a case form, I cannot see the phone number of the contact associated, but I cannot edit it). If I need to edit fields from the related record I have to open the record and edit them in the regular form.

Tuesday, October 29, 2013

Filtering activities by type in CRM views

In some scenarios you might want to wish to filter your activity views by activity types. While it sounds very trivial it can be a bit more complex in the context of solutions because activity type is stored as objecttypecode (OTC) which is different in each environment for custom activities.

 

Scenario

I defined a custom activity called “Follow-up” and I would like a view/sub-grid in the account form which shows me all the related Follow-ups to the account (I don’t want to see any other activity there). I also don’t want to create an additional relationship between Account and Follow-up but rather use the generic “Regarding” lookup that is used by all custom activities.

 

Solution #1

I can simply define or edit an existing view and use the field “Activity Type” (activitytypecode) to filter and show only the activity type that I desire:

image

After I do this I can use my view in a sub-grid and voila, very simple, I now have a sub-grid in the form which displays related activities but only those of type “Task” and “Follow-up”:

image

 

The problem with solution #1

The problem now is that when I transport this view and form to QA/Prod or to another CRM organization, it might break. The reason is that the view uses the activitytypecode field to filter on activity type. This field references an objecttypecode (OTC) which is a unique number given to each entity. For system entities (task, accounts, etc) the OTC is the same in all environments. However, for custom entities, new OTCs are assigned incrementally so there is no guarantee that they are consistent across environments. In my dev environment, this is what my view definition looks like in the exported solution:image

While I can be sure that 4212 is always “task” in all environments, I cannot be sure that 10007 is my custom activity “Follow-up'” in all environments. In fact, an entity with OTC 10007 might not even exist in other environments, even if my custom “Follow-up” entity does exist (but with a different OTC).

 

Solution #2

If I would like to avoid my solution referencing a hard-coded OTC, I can use linked-entity in my view as a work-around. However, I cannot edit the views in the view designer of the application because it does not support joins. I would need to export my solution and edit the view XML in the solution file and then import it back. I will update the XML of the view I defined above in order to retrieve all tasks and follow-ups but without using the activitytypecode attribute:

image

Note that there is no reference to any objecttypecode in the view definition above, but it will automatically filter to show only activities of type new_followup because of the inner join. In order to update the view XML you will need to include the Activity entity to a solution, export the solution and then look for your view in the customizations.xml file and update the view definition fetchxml.

The problem with solution #2

Although solution #2 will work in all environments and will not break even if you transport the solution to another organization (as long as the new_followup entity exists), there are some disadvantages of this approach: First, the view filter criteria cannot be edited using the application view designer (so you will always need to update the XML if changes are required). Second, this only works if you want to filter to display a single activity type. However, if your requirement is to filter the activities to show 2 or more activity types (e.g. Follow-ups and tasks) then you will not be able to do this solution and only then I’d recommend solution #3.

 

Solution #3

Thanks Jukka for suggesting this. Every activity has at least on activity party (at least the owner). Therefore, we can leverage the activity party relationship to display “all activities which have an activity party which has a parent activity of type X”. This is what the query would look like if I only want to display Follow-up activities for example:

image

The problem with solution #3

The only problem with this solution is that it only works if you want to display a single activity type. If for example you have multiple custom activities and you want a view to display only follow-up and task activities then this will not be possible. Note however that if you want to display only custom activities you can easily filter out the out-of-the-box activities using solution #1 with a filter of “Does Not Equal (task,appointment, etc).” and that will be fine to transport across organizations because OTC for out-of-the-box activities are always constant.

 

Solution #4

You might be disappointed but if you need to filter to display more than 1 activity type but not all activity types, and you are using custom activities in your filter, then the only other solution would be to stick to solution #1 (see above) and then create a tool that automatically remaps the objecttypecode in the views xml to replace it with the appropriate objecttypecode in the target environment. You could do so as a stand-alone tool or you can have a post-solution action which does this for you (using the solution configuration page web resource).

Sunday, October 27, 2013

Join the CRM 2013 experts round table in Spanish

On October 31st the most distinguished CRM experts in the Hispanic community are getting together to discuss in a virtual round table the new features of Microsoft Dynamics CRM 2013 (“Orion”) and the challenges for migrating.

The following attendees are invited:

  • Gus Gonzalez (MVP, Zero2Ten, moderador de la sesión)
  • Damián Sinay (MVP, Remoting Coders)
  • Ramón Tebar (MVP, MetroBank)
  • Demian Raschkovan (MVP, Infoaván)
  • Gonzalo Ruiz (MVP, Avanade)
  • Pablo Peralta  (MVP, CRMGamified)
  • Jimmy Larrauri (Microsoft)

 

Additionally, you can ask your own questions in advance! Please leave your questions here and let the experts do the best to answer* during the session.

* We will try our best to respond all questions during the discussion and the timeframe we have. Given the time limitations we cannot commit to answer all questions although we will try our best.

Don’t miss out this opportunity, even if is just to practice your Spanish (even my Spanish is a bit rusty)! Thanks to Gus and Pablo for being the champions organizing this event!

Register for the event here.

Monday, April 29, 2013

Availability of “Add New” and “Add Existing” buttons in sub-grids

When you have a subgrid in CRM, you will notice there is an “Add New” and an “Add Existing” button. But the question is: Why sometimes only one of the two buttons is visible while some others both are visible?

image

The answer is actually not very straight forward and it depends on multiple factors:

1. Is it a 1:N or N:N relationship?

This determines the display rules of the given buttons.

 

2. On which entity?

Some out of the box entities have different display rules than others.

 

3. Is it the sub-grid of a custom entity?

Custom entities should all have the same display rules.

 

4. Is the parent lookup a required field in the child records?

This affects the visibility of these buttons. For example, if you have an 1:N relationship between Airports and Terminals then the visibility of the “Add Existing” button for the Terminals sub-grid on the Airport form depends on whether “Airport” is a required field for the Terminal or not.

 

This table summarizes the availability of the “Add New” and “Add Existing” buttons:

 

Relationship Type Is the parent required on the child (lookup field is marked as required) “Add New” button visible? “Add Existing” button visible?
1:N Yes Yes Yes*
1:N No Yes No
N:N N/A No Yes
 
* Not available on some Out-of-the-box entities
 
 
You can always modify the default behaviour by editing the ribbon and updating the display rules on the sub-grid buttons of the entity you would like to change. Before you do that, here is some useful information you might need:

When you look at the sub-grid ribbon you might find that there are two “Add Existing” buttons defined (this is true for most system entities and all custom entities): “Add Existing Standard” and “Add Existing Associated”:

image

So what’s the difference? It is misleading to believe that “Standard” is the button shown when there is an actual sub-grid inserted in the main form and “Associated” is the one visible in the associated view when using the form navigation (associated view) instead of a sub-grid. In fact, that’s not it at all. The actual difference is that “Standard” is the button that applies to 1:N relationships and “Associated” is the button that applies to N:N relationships. Therefore, depending on the type of relationship for your entity you will need to modify one button or the other. Note that some entities (e.g. contact) do not have an “Add Existing Standard” button so by default the “Add Existing” button is only available to N:N relationships.

To make your life simpler, I suggest using the visual ribbon editor which will show you all the buttons available in all entities as well as the display rules that apply.

Monday, April 15, 2013

Enterprise Data Integration Strategies with CRM 2011

In case you missed the excellent presentation by Daniel Cai in XrmVirtual about the different data integration strategies for CRM, you can view the recording here.

Data integration is a very common scenario in enterprise CRM implementations. Therefore it is important to understand what the options are and what the advantages and disadvantages are. Here is a small extract from Daniel’s presentation about 4 different data integration options:

 

1. CRM 2011 Import Data Wizard

What’s it?

  • Free utilities offered by the platform

Pros

  • Works for simple and small data import scenarios
  • Works within application, available for CRM users for self-served data
  • imports
  • Undoable
        works well for new insert, but not update though
  • Free

Cons

  • No delete
         don’t confuse with the above undo capability
  • No transformation
  • No scheduling, no automation
  • Difficult to manage incremental changes
  • Maximum number of records is constrained by file size
  • Limited capability of handling relationship
  • Exceptions to be expected when used for some special entities, fields

 

2. Custom Integration Development

How does it work?

  • Write custom code against CRM web service interfaces using SDK or service references

Pros

  • Leverage your .NET programming (C# or VB.NET) skills
  • More granular control
  • Flexible integration points
        Plugins
        Workflows
        Standalone applications (Console, Windows Form, and probably third-party apps)

Cons

  • Could be an exhaustive effort, particularly when infrastructure coding is involved
        Scheduling
        Threading
        Intricacies of working with CRM web service interfaces
  • Most likely much higher maintenance cost down the road
  • Often the case, the implementation ends up with a tightly-coupled architecture style, which leads to poor maintainability

3. ETL Tools

What’s ETL

  • Extract, Transform, Load

Pros

  • Development Productivity
  • Visual development environment for data flows and control flow tasks
  • Scheduling engine
  • Performance
  • Scalability
  • Extensibility
  • Can be part of your overall BI and data warehousing strategies

Cons

  • Learning curve of the ETL tool
  • Extra license cost of the ETL tool and/or the adapters
  • Probably not ideal solution for real-time requirements

Options

  • SSIS (SQL Server Integration Services)
  • Informatica
  • Scribe
  • Connectors for Microsoft Dynamics

 

4. Service Bus / BizTalk

What’s service bus?

  • A software architecture model used for designing and implementing the interaction and communication between mutually interacting software applications in service-oriented architecture (SOA)

Pros

  • Messaging based approach
         Optimized to move single transactions between different systems or processes in near real time or real time
  • Decoupled integration architectural model
         Best suited for decoupled heterogeneous systems by using a middleware

Cons

  • Probably not best fit with large volume data load
  • Performance overhead due to serialization and deserialization

 

Thanks to Daniel for sharing. I have also provided a Spanish translation of this post here.

Saturday, March 16, 2013

Setting a Blank Default URL for an IFrame in CRM 2011

It is common that we want an IFrame in an entity form and we need the URL of the IFrame to be set dynamically when the form loads using the setSrc() method in a script. But how can we set a blank default URL?

When you insert an IFrame in a form, the form designer forces you to enter a blank URL. Before Polaris (UR12) we could enter “about:blank” and we’re all set! However, you are now forced to enter a URL with a valid prefix (http, https, ftp, fttps):

image

If your IFrame will embed external web pages (such as www.bing.com ) then it is not a problem to enter the default URL and have the script modify the URL if required at run time. However, if your IFrame is used to display HTML pages that you have defined as CRM Web Resources then you will not want to enter the full URL (e.g. http://mydevcrmserver.com/myorg/WebResources/test.html ) because the URL would contain a link to your DEV organization and that means that every time you promote to test/prod or install the solution on a different server, you’d have to go and modify the URL manually. So what can you do?

One option is to set the defaul URL to some hard-coded external website (e.g. http://www.bing.com) and have your script update the URL at runtime so the IFrame loads your HTML web resource. Ugly!

The best option would probably be that Microsoft allows as to enter “about:blank” but it seems this is no longer allowed after UR12 (hopefully they will allow it in the future). But you don’t want to rely on that.

The second best option that should work for you is to define your own “blank” web resource (Thanks to Alex Ries for the suggestion):
  1. Create a new HTML web resource, which is blank (<HTML/>)
  2. In your form, instead of inserting an IFrame, insert a web resource and use your blank web resource you just created.
  3. At run time, your script should still be able to modify the URL of your web resource to point to another web resource. The setSrc() method is supported on IFrame as well as web resource controls!


With this solution, you are no longer using an IFrame so you are not forced to set a default URL! Hope this helps you!

Sunday, March 3, 2013

CRM 2011 Workflow Utilities released for CRM Online

You might know the CRM 2011 Workflow Utilities Codeplex project. The most popular request is now available: CRM Online support.

Today I have created a new release (v2.0.2.0) which now supports installing the solution in a CRM Online organization. Workflow utilities is a CRM solution that allows you to extend the CRM workflow design experience by providing the following custom workflow steps available directly from the CRM process designer.:

  • Delete record
  • Share or “unshare” a record
  • Insert hyperlink to a CRM record
  • Qualify lead (convert to account/contact/opportunity)
  • Bulk activate / deactivate records (no record count limit)

For more details on how to install and use the solution please visit the Codeplex site. Thanks for all the feedback received, enjoy!

Wednesday, February 13, 2013

JavaScript, XML processing, DOM and CRM 2011 UR12

If you have scripts in CRM which somehow retrieve or process XML, chances are you will need to do some re-write or validations when applying Update Rollup 12 (UR12). This post explains how to fix you JavaScripts when you make use of the DOM parser for processing XML.

One of the highest-risk customizations to break with UR12 are JavaScripts and these are the 2 most common reasons why:

1. It is common for developers to perform unsupported operations with the page DOM instead of using the supported xRM APIs. Since UR12 introduces cross-browser support, accessing the DOM by unsupported methods such as ‘getElementById’ on CRM forms will no longer work because it has changed. Therefore, customizations like this one will break.

2. Because CRM has historically only been supported in IE, developers might have written JavaScripts that depend on IE extensions specific to Microsoft, these will also stop working because the assumption is no longer true (will be broken even in IE!). Even though you are not doing anything unsupported in your scripts, they can break and might need to be fixed.

There are plenty of tools and blog posts that talk about how to tackle #1, so in this article I will focus on problem #2 above and I will pick the specific example of processing XML.

Assume you are parsing and processing an XmlDocument in your JavaScript, perhaps you retrieved the xDoc from and XML HTTP request, using AJAX or even if you are simply parsing text into an XmlDocument object. In my case, I was retrieving an XML web resource using the following code:

  1. function ShowHelpText() {
  2.     var tooltipsTextFile = "ava_TooltipsText.xml";
  3.  
  4.     // Use AJAX to retrieve the tooltips texts
  5.     $.ajax({
  6.         type: "GET",
  7.         async: true,
  8.         url: tooltipsTextFile,
  9.         dataType: "xml",
  10.         success: parseTooltipsXml,
  11.         error: function (xhr, textStatus, errorThrown) {
  12.             alert("Error retrieving tooltips: " + xhr.message);
  13.         }
  14.     }); //end ajax
  15. }

Before UR12, this code used to return a documentElement of type IXMLDOMElement which is a Microsoft extension to the W3C DOM. Therefore, I was happily calling methods such as selectNode and selectSingleNode. The problem is, after UR12, the same code will return a standard Document object which does not support selectSingleNode so I get the error “Object doesn’t support property or method ‘selectSingleNode’”:

image

 

In part, this is great news, because now your JavaScript will work in any browser (mostly), but you still need to do some clean-up to remove any dependencies on IE DOM extensions. In my case, I had to update my script to make use of getElementsByTagName and verify that I only use methods and properties that are W3C standard as documented here and process my XML according to that documentation (which works slightly different than if you have IE-specific JS).

Although my example is specific to parsing XML, the same can apply to any other scripts that rely on IE extensions not available in other browsers or not standard. I hope this post helps others be more aware and proactive before applying UR12 and in understanding how your scripts can break even if you are not using any unsupported customizations!

Saturday, January 26, 2013

Problems with leading and trailing blank spaces in CRM data

I recently ran into a number of problems that ended all up being due to blankspaces in some CRM data. I thought of sharing where these problems come from, how blank spaces can affect CRM functionality and how you can resolve them.

You might wonder: how can you end up with leading or trailing blank spaces in text fields in CRM? While it is true that CRM forms are smart enough to remove these blank spaces upon form save, it might not be the case when the data comes in from data import or during integrations with external systems. It sounds like a small problem, but if you are not careful, blank spaces can become a data integrity nightmare for the following reasons:

1. You might end up with duplicate data that is hard to resolve later on. For example you might have account “123” and account “ 123 “ which reference to your same customer. Now all your activities, invoices and all related records are potentially spread across 2 different records. Fortunately, duplicate detection ignores leading/trailing blank spaces so these 2 records would be considered duplicate if you have a published rule on account number field. However, if these accounts are created from the SDK (or through an integration layer), chances are that the duplicate detection is not enforced because when making web service calls duplicate detection is off by default unless specified in the create/update message. Fixing duplicate parent records can be a really long and boring task.

2. Assume you have multiple contacts related to account “123” that you want to import using the data import wizard. However, your account appears in CRM as “ 123 “ (with blank spaces). It will be impossible for import wizard to match the contact’s parent account and import will fail because the parent account was not found. You might say: I can just change my import spreadsheet to reference account “ 123 “ instead of “123”. The answer is: it does not matter if in your import XML file you enter “123” or “ 123 “ as the parent account, CRM will not be able to resolve the parent account!! In short: You cannot use the out-of-the-box data import feature to import related records to that account until you fix the blank spaces, argh.

3. Once you fix all your integration points to trim all text fields before committing a create / update to CRM, how do you clean the thousands of records that already exist? My first guess was: Export to Excel for re-import, use some Excel functions to remove blank spaces and import back to CRM. Again to my surprise, removing leading/trailing blankspaces in text fields is not considered a change for CRM so during import, the records were not even processed! When you export records for re-import, CRM is smart enough to know that if you did not update a row, it will not re-import that row. However, it is not smart enough to figure out that you removed blank spaces so it also ignores your update.

4. Sometimes the CRM forms trim blank spaces for text fields. This can become a problem because if your data has trailing blank spaces, the CRM form will remove then on load, and automatically the form is marked as dirty! Therefore, just by opening the record your form is dirty and you get a warning about pending changes when you close the form even if you did not update the record. It also prevents some functionality since some of our ribbon buttons require the form to not be dirty. It is also not evident what was happening and took us a while to figure out why some forms where always getting marked as dirty.

 

We let our production CRM get really messy because we did not notice this problem until too late (we never noticed the external systems were sending data padded with blank spaces) so cleansing the data became quite challenging since it was spread to multiple fields in multiple entities, many duplicate parent and child records. As I mentioned earlier, fortunately duplicate detection does consider these 2 cases as duplicates (“123” and “ 123 “) so you can execute multiple duplicate detection jobs to find and resolve duplicates. However, it can be a really long task to do. In our case, because of the magnitude of the data cleanse that was required we had to invest in a data cleansing tool that would iterate through multiple records resolving the blank spaces and the duplicates which reduced considerably the amount of manual work required to solve the problem. The “tool” in a nutshell consisted simply in a custom workflow activity that takes as input a CRM query (Rollup Query) and then retrieves and cleans all the records specified as input. Then we can use on-demand workflows and provide different queries to resolve duplicates in multiple entities. In any case our conclusion is that we should have thought about this from the beginning and I hope this post helps other avoid the same problem before it is too late.

Sunday, January 13, 2013

Script# (ScriptSharp) and CRM: The good and the bad

If you are familiar with Script# you probably understand how it can accelerate JavaScript development and completely eliminate annoyances such as accidental JavaScript syntax errors. However, does it work well for Dynamics CRM for scripts and web resources?

If you are not familiar with Script#, here is a very simple definition: Write your code in C# and you can then compile it into a JavaScript (instead of programming in JS directly). I have been using Script# for many years now (and love it), but I recently took the challenge for the first time to use it for designing and deploying all script customizations for an enterprise CRM project and quickly realized that there are a few issues about Script# and CRM that will make me think twice next time. Let’s start with the “good”:



1. Forget about JS syntax. Honestly, I hate JavaScript and client programming. One of the reasons is because I find it too error prone, I don’t know how many times I have run into issues with my JavaScript and often turns out to be something like forgetting a curly braket “}” somewhere in the syntax or accidentally typing a capital letter when it shouldn’t be. I am devoted to C# and that’s why I’m so motivated with Script#; isn’t it just awesome that I can write all my JavaScripts in C#, a language that I know inside out, gives me compile-time errors and intelli-sense? I’m sold already! Also because you write your form scripts in C#, you could even share some code between plugins (server) and web resources (client-side JS)!



2. Excellent Script# Xrm.Page Library. You can download for free this library that Gayan Perera has shared with the community. It is as simple as adding a reference assembly to your Script# project and now you have access to the entire Xrm.Page object model from Script# including intellisense for different APIs and enumerations available in the CRM SDK. This is an amazing productivity gainer.



3. Access to mscorlib from your JavaScripts. JavaScripts can get ugly with complex operations. Having a subset of mscorlib available from Script# makes things much simpler. You can have access to useful classes like String, Dictionary, Queue, List<T>, CultureInfo, XmlDocument, XmlHttpRequest , Math and many more, and all this with the intelli-sense we love. Some of these functions would be painful and/or ugly to implement in JavaScript alone. You can also use OOP/C# concepts such as inheritance, static classes and members, Properties, Events and Delegates. This way you can program your JavaScripts in C#and you can use API’s and syntax you are familiar with from .Net. Although it would be possible to do al this in JavaScript, for a C# developer, the usability and efficiency to write Script# does not compare with that of writing JavaScript.



On the other hand, I ran into the following “issues”:

1. Library size. When you make use of any API from a referenced assembly (except Xrm.Page) then you need to include the JavaScript version of that referenced assembly (e.g. mscorlib.js) to be loaded with the CRM form. These libraries can be big and typically, you only need a small subset of the library. It could slow down loading the forms, however, you will have the same problem even without Script# when for example you want to use the JQuery library.

2. You cannot reference any JavaScript code from Script#. If you want to re-use a JavaScript library from a previous project or a library you found online, you cannot reference any JS function from a Script# project. You would have to write “empty wrappers” in C# for each JavaScript function you plan to use, then compile it as a Script# library and then add the reference assembly to your code. It is not too complicated but it adds some pain.

3. AJAX incompatibility. I noticed that my dates in the form were not getting formatted as per the CRM user settings and some other fields and controls had strange issues (e.g. missing the month from the calendar control). After some investigation the culprit ended up being Script#. The reason: mscorlib.js defines classes and functions such as Date.prototype.format and Date.prototype.localeFormat. These functions are also defined in the AJAX framework that the CRM application uses in global.ashx and guess what: They are not implemented the same way. Because the CRM application relies on the MicrosoftAjax.js implementation it will be buggy if it uses the mscorlib.js implementation. Unfortunately, as soon as you add mscorlib.js library to your form, it will overwrite the functions from global.ashx and there is no way to “force” the CRM application to use the functions defined in global.ashx instead. I had to implement an emergency workaround to fix this problem which consisted in adding another JS library to the form, which would define the functions back with the AJAX implementation (something like overwriting the overwrite). Ugly, but it fixed the problem.



In summary, I had a good experience using Script# for CRM, but the issue with AJAX framework became a deal-breaker for me. Other things that I will explore in the future are TypeScript and the new Xrm.Page script template available with the CRM SDK 5.0.13+ which gives you intellisense for your CRM JavaScripts. TypeScript sounds promising since it is simply a superset of JavaScript which allows you to reference other JavaScript libraries; however, it is not C#-based and the syntax is not the same, so it would be yet another language to learn.