How to Expand the Email Description Field in Dynamics CRM

Have you ever gone into an email activity in Dynamics CRM and decided that you want to make the body of the email just a little bit bigger on the form? That should be no problem, right? Just customize the form, find the description field, and increase the number of rows.

So what happens if we try it? Let's find out.

  1. First, go to the form editor.
  2. Open the Description field.
  3. Under the Formatting tab, you may expect the number of rows to be displayed, as with any multi-line text field. Unfortunately, the description field is not a multi-line text field, and as a result, you cannot increase the number of rows.

You might be wondering, could this be a change in CRM 2013? The answer is no. For CRM 2011, as well as 4.0, the description field cannot be changed through the form editor.

Fortunately, there is still a method to modify the size of the description field, but it involves a little XML editing. It will involve creating a solution in CRM, adding the email entity, exporting the contents, editing the XML, and importing it back. Sounds scary? Not really! Just follow the steps outlined below.

1. Create a new solution in CRM by going to Settings > Solutions and clicking New.

2. For Display Name and Name, type "Email". For Publisher, click on the search box and select any that you see listed. Most likely it will contain the name of your CRM organization. For Version, type in a 1. Then click Save.

3. After saving it, go to Add Existing, and then Entity.

 

4. Find E-mail and select Ok.

5. If you see a message asking about "Missing Required Components" select No, and then click Ok.

6. Now the solution is ready. Click on Export Solution.

7. Press Next on all of the screens, and at the end click Export. After a few seconds, you will have the option to save the .zip file.

8. Once the file is saved, extract customizations.xml and open it with notepad or your favorite text editor.

9. This part may be a little bit tricky for those that are not familiar with XML. Do a search on this file for description="description"

10. If you have multiple email forms, you will see this listed more than once. Once you find it, just above the text you searched for, you will see "rowspan." The value indicated is how many rows the field will have. In the example below, the email description field is set to 12 rows.

If you want the email activities to have a body smaller or bigger, you can simply change this value. If you wanted to have a very small description field, you can change it to 4. For now, let's increase the size quite a bit and change that value to 20. So you should change this file so it will say rowspan="20"

11. You'll have to make one more modification, which is to add additional row columns for the amount that you increased. The reason for doing this that if you were to import this now, the row width could not be correct. So if the previous rowspan was 12, and you increased it to 20, you need to add 8 additonal <row></row> lines. So let's add those additional row columns. Highlighted in yellow is what you should add to this file.

12. Now save the customization.xml file, and copy it back to the zip file you just downloaded.

13. In CRM, back under Solutions, click Import.

14. Select the modified zip file, click Next and then Import. After a few seconds, it will complete. Then click Publish All Customizations.

15. Refresh your browser, and start a new email. It will now have a much larger body size.

There you go—in just a few simple steps, you now have a larger email description field in Dynamics CRM.

If this blog was useful to you, you might want to check out some of our other blogs on working with activities in Microsoft Dynamics CRM.

Happy CRM'ing!

 

Modifying Chart XML in CRM 2013 — The Basics

Microsoft Dynamics CRM 2013 comes with many charts out-of-box to help you visualize your data. Also, just as you can create custom system and personal views, it's also possible to create your own custom charts. You can take the visualization a step further by modifying chart XML in CRM 2013, resulting in seemingly endless possibilities.

Let's start with the basics. What can you modify in a chart?

Now we'll walk through some examples of working with a chart's XML. (The examples below will show the opportunity entity.)

How to Export a Chart's XML

  1. Navigate to Opportunities and expand the Charts pane on the right-hand side.
  2. Select the chart you want to modify and click the Command Bar dropdown.
  3. Click Export Chart. Note that this will be for modifying personal charts.

    Modifying Chart XML in CRM 2013

  4. Save the file.
  5. Open the file in a program to edit the XML. You can use Visual Studio, but you can also use Notepad. Do not open in Excel.

For System Charts

  1. Create a new solution with the entities and charts you want to modify.
  2. Export the solution.
  3. Open the customizations.xml file to access the chart XML.

How to Import modified Chart XML

  1. Navigate to Opportunities and expand the Charts pane on the right-hand side.
  2. In the Command Bar dropdown, click Import Chart.
  3. Upload your saved .xml file. Note that this will create a new personal chart.

For System Charts

  1. Save the changes made in the customizations.xml file
  2. Import the solution with the modified xml file

Overview of the Main Parts of the XML

Between the <datadescription> and </datadescription> tags, the main elements are:

Also note that each attribute has an 'alias' that is referenced throughout the XML.

The next important part of the XML is between the <chart> and </chart> tags. The main elements are:

XML Modifications

Color

You can change colors for just about any line, label, or bar in a chart. Notice that the colors by default use numbers to define the color to use. Rather than using those numbers, it may be easier to use text. A library of all the possible colors can be found here.

For example, let's change the line color on the Actual Revenue by Month chart. I'll change the color of the <Series> to YellowGreen, as well as the y-axis title, and line color to Red (XML below).

Here is what it looks like once changes imported:

We also have separate blog on customizing colors in Dynamics CRM charts that you can reference.

Labels

Not only can we change the color for labels, we can change the font, size, and even hide a label. A library of title properties can be found here.

The format required for fonts is Font="font name, font size". In the example blow, I'll change the font for Y-Axis to TitleFont ="Tacoma, 35 px".

Here's what it looks like once the changes are imported:

Hiding Labels and Values

The IsValueShownAsLabel property displays or hides values on a chart. (True displays the values, False hides the values.) To hide labels on the axes, or anywhere else, use the Color property and set it to Transparent.

In this example, we will hide the values by using IsValueShownAsLabel="False". To hide the X and Y axis titles, use TitleForeColor="Transparent".

Once imported, it looks like this:

This covers many of the basics to personalize your charts in Dynamics CRM. If you are looking for more general information on charts, you can reference our CRM How-to Portal.

Happy CRM'ing!

Perform a Left Join Using FetchXML and Display Results in CRM 2013

As we've covered pretty extensively on the blog lately, Microsoft Dynamics CRM 2013 has a ton of new great features. One of the things we haven't covered yet is the new ability to perform left outer join queries using FetchXML. So let's dive in!

Below you'll see an account record that doesn't have any cases.

Left Join Using FetchXML

Account with no associated cases.

To query for accounts that don't have cases, you can use the following FetchXML query:

Left outer join query between accounts and cases (incident).

The two main pieces to specify are the link-type, which is part of the link-entity, and the operator of the condition of a filter. Set the link-type to outer and the operator to null.

Below is a screenshot of the results when the RetrieveMultiple request is executed.

Result from executing left join.

In order to use this left join inside CRM 2013, use the SavedQuery entity to create a view.

Use SavedQuery to create the view.

Once executed, you can now see this left join view.

View of accounts with no cases.

There you have it—that's how to perform a left join using FetchXML and display results in  Microsoft Dynamics CRM 2013!

Was this helpful? Keep checking back for more blogs covering Dynamics CRM 2013 features, and check out our events page for upcoming CRM 2013 educational webinars.

Happy CRM'ing!

Resetting the Dynamics CRM 2011 Ribbon

Today we're going to talk about how to go about resetting the CRM 2011 ribbon. (If this topic interests you, you might also want to visit the complete guide to CRM 2011 ribbon customization.)

If you recently upgraded from Dynamics CRM 4.0 to Dynamics CRM 2011, you may have noticed that all the entities that had customizations in the toolbar now have an extra tab on the form named ISV (e.g. ISV Account Form).

how to reset the CRM 2011 ribbon

Further investigation would reveal that there is a new web resource for each entity that had a customized toolbar. This new web resource will be a script file and the description will clearly tell you that it is regarding the entity’s ribbon.

In order to reset the ribbon for an entity (or multiple entities), add all the entities to a new solution (do not add required components – they are not needed). Include the item “Application Ribbon” in the solution.

Export the solution and save it.

Uncompress the solution file and open “customizations.xml” with a text editor that can edit XML. Once open, do a search for “<RibbonDiffXML>”. This is where the customization of the ribbon for that entity (or application) begins. Select the entire <RibbonDiffXML> element until you get to the closing tag </RibbonDiffXML>. Replace the entire element with the default element which is:

[sourcecode language="xml"]
<RibbonDiffXml>
<CustomActions />
<Templates>
<RibbonTemplates Id="Mscrm.Templates"></RibbonTemplates>
</Templates>
<CommandDefinitions />
<RuleDefinitions>
<TabDisplayRules />
<DisplayRules />
<EnableRules />
</RuleDefinitions>
<LocLabels />
</RibbonDiffXml>

[/sourcecode]

Do this for each instance of <RibbonDifXml> in the file. Once done, save the file and compress customization.xml, solution.xml and [Content_types].xml into a compressed file. Import this file as a solution, publish and refresh the browser. You will now see that the tabs from those entities are gone! The web resources have no dependencies either anymore so they can be deleted too.

You may also be interested in:

Happy CRM'ing!

How to Resolve the Unique Column Names Error with the OrgDbOrgSettings Tool

In this post, we'll go a bit beyond basic CRM how-to's. We're going to cover a quick and painless resolution to the unique column names error on import of a managed solution into CRM 2011 using the OrgDbOrgSettings Tool.

Here is the error message from the Excel import log:

“Column names in each table must be unique. Column name ‘new_ordernumber' in table 'new_orderlistBase' is specified more than once.”

The cause of this issue is that the PhysicalName property for the field is not the same in the two managed solutions.  The field in question was likely removed from the form and recreated with the same name but not the same case.  This difference is enough to cause the import to fail.

Using the OrgDBOrgSettings tool for column names error

attribute PhysicalName="new_OrderNumber" - OrgDbOrgSettings tool

To resolve the issue, we can make use of Microsoft’s supported OrgDbOrgSettings Tool.

To use this tool you will need:

To use the tool:

1.    Download and install the OrgDbOrgSettings Tool.  I recommend not burying this in your C: drive because you will need to access it through command line in a few moments.

Documentation for Microsoft’s OrgDbOrgSettingsTool can be found here.

Download the OrgDbOrSettings Tool

2.    Modify the tool’s configuration file to target your CRM.

a. Open your CRM and navigate to Settings > Customizations > Developer Resources and take note of your discovery service url.  This value will need to match the tool’s configuration url.

Match the OrgDbOrgSettings Tool URL

b. Open the tool’s configuration file and modify the following urls to match your CRM settings

Modify the URLs in the OrgDbOrgSetting Tool's configuration file

c. Modify the user name to match the system administrator’s login.  You will need the password at runtime.

Modify user name to match system admin's

d. Modify the deployment type.  ‘Online’ works for online as well as hosted deployments.

Modify deployment type

e. Save and close the configuration file

3. Open the command console and navigate to the OrgDbOrgSettingsTool directory where you installed the tool.

4. Enter the following command.  Make sure the org name matches your CRM org name.

Microsoft.Crm.Se.OrgDbOrgSettingsTool.exe update <yourorghere> LookupNameMatchesDuringImport True

5. Press enter and enter the password for the user previously defined in the configuration.  Press enter again and wait.  After a few moments a message should appear and notify you of the result from the tool.  Here is a successful update of the CRM setting:

OrgDbOrgSettings tool update

After performing this update the managed solution was able to import without issue.  The Microsoft team has verified that his setting is safe to leave toggled, so unless your organization has reason to change it back you can move on.  Don’t forget to document this change in your change logs to avoid future headaches!

The OrgDbOrgSettingsTool can modify other settings as well.  Typing the following command will show a list of all settings available to the tool as well as their current values within the org:

Microsoft.Crm.Se.OrgDbOrgSettingsTool.exe Retrieve <yourorghere>

Dynamics CRM import errors like this one can be difficult to diagnose, but through careful utilization of supported tools you can resolve these issues quickly and painlessly.

Happy CRM'ing!

Microsoft Dynamics CRM Online – Currency Fields in FetchXML Reports

There is a recent issue we ran into while dealing with currency fields in reports with FetchXML queries. The issue is that when a money field is added to a report with FetchXML query, excel formulas does not seem to be working properly on these fields with a currency symbol attached to them. Whenever a currency field is listed in a FetchXML query, it pulls back 2 columns. One with a currency symbol attached to it in the data with the original column name and the other with just the decimal value of the currency field with a “Value” postfix attached to the column name as shown in the screenshot below:

Currency Fields in FetchXML Reports

As you can see, there are 2 columns returned from the query with one money field being it – “estimatedvalue” is the original column name used and that is the column returning the value with the currency symbol in it and the other “estimatedvalueValue” without the currency symbol and a ‘Value’ postfix in the column name. When using this information in the report if you use the field with the currency symbol in it (or the field without the “Value” postfix in the column name) and export the report into excel – there are issues with using formulas for calculations against this column.

Currency Fields in FetchXML Reports

Excel does not recognize this column as a numeric field and no matter how it is formatted. It can be seen in the screenshot below from the exported report after applying some calculation formulas.

Currency Fields in FetchXML Reports

 

 

 

 

 

 

 

You should be using the second field without the currency ($) fields (the one with the “Value” prefix in it). This is the field with just the decimal value of the money field from database.

Currency Fields in FetchXML Reports

The reason that the column with the currency symbol is not working is probably because it has the currency localization info attached to it making it a special column making the formulas and calculations void on these types of columns. So, this is important to note to show the correct field in the report as some of our clients use a lot calculations after exporting the data from a report into excel.  Hope this helps someone out there and saves some time in debugging this issue.

If you are still having questions please reach out and talk to one of the Microsoft Dynamics CRM Experts at PowerObjects – your #1 Microsoft Dynamics CRM partner in the world.

Happy CRM'ing!

Adding PowerGlobalSearch to a Different Area in CRM 2011

PowerGlobalSearch adds value for each and every user of CRM 2011 by providing the ability to earch any entity and any field from one window.  By default, PowerGlobalSearch is added under the Workplace Module in the 'My Work' section.

adding search enhancement to Dynamics CRM 2011

This is great for the user that spends their time in the My Work section of the Workplace but let's not forget about our Sales/Marketing/Service users that like to spend their time outside of the Workplace Module. Follow the steps below to move or duplicate PowerGlobalSearch to any of the modules in CRM.

1. Create/Save a solution with only the Site Map included.

a. Go to Settings > Solutions and click New.

search enhancement to Dynamics CRM 2011 add-on

b. Give your new solution a Display Name, Publisher, Version and Name. After filling in the required fields, click Save.

global search for crm

c. After the solution finishes saving, click Add Existing and choose Site Map from the list.

d. Save the solution and then click .

e. A wizard will appear. Click  twice and then click .

f. Save the file to the desktop or another easy to retrieve location.

2. Make a copy and edit the XML

a. Make a copy of the file by right clicking and selecting copy. Right click again and select paste at a different location. This will give us a backup in the case that we delete a part of the Site Map that we didn't intend to or are unhappy with where we added PowerGlobalSearch.

b. Double click the original file to open it.

c. Right click the Customization XML file and select Copy.

d. Paste the Customization XML file outside of the .zip file.

e. Open the Customization XML file in your favorite editor.

f. Locate the SubArea for PowerGlobalSearch. As you recall from the beginning, this is within the My Work section of the Workplace module. Workplace is the first Area you will see in the XML and generally My Work is the first Group. Using the find tool of your editor and searching for "PowerGlobalSearch" is an easy way to find the SubArea.

g. Copy the entire SubArea for PowerGlobalSearch.

h. Find the Area and Group you would like to add PowerGlobalSearch to and paste in the SubArea. Below we have added PowerGlobalSearch to the Sales module. Deleting the SubArea in My Work will remove PowerGlobalSearch from that area.

i. Save the file and add it back to the .zip file that we pulled it out of originally. Ensure you still have your original Site Map copy that is unchanged.

3. Add the Site Map back to CRM.

a. Go to Settings > Solutions and click Import.

b. Browse for the .zip file with the changes made above and click 

c. Read the warning about unmanaged solutions and if you are still comfortable with your changes, click . You should be comfortable if you copied the .zip from the steps above.

d. Click 

After publishing the customizations, close CRM and restart it. This should refresh CRM and let you see your handiwork! All that is left to do now is to sit and wait for the sales, marketing and service users to send you "Thank You" emails.

        

And that's it. We hope this helps enhance your PowerGlobalSearch experience. Questions? Feel free to reach out to our PowerPack Pro.

Happy CRM'ing!

Microsoft Dynamics CRM SOAP Logger – A tool that can greatly simplify writing HTTP Requests

JoeCRM says, "Microsoft Dynamics CRM SOAP Logger makes me happy!"

Writing a fetch can be time consuming and aggravating, even if you know what you’re doing.  The common niceties that developers have come to enjoy, like IntelliSense for instance, don’t exist.  Writing queries becomes trial and error and can greatly increase the time it takes to finish your project.

Fortunately, the CRM 2011 SDK comes with an application that allows you to write your queries in Visual Studio and capture the format of the fetch.  This application, SOAP Logger, lives in a less than obvious location:

crm2011sdkrootsamplecodecsclientsoaplogger

Note that there are three regions in the code:

Microsoft Dynamics CRM SOAP logger

(If you don’t see this view, you can use Ctrl+M Ctrl+O to contract your code)

The only area we’ll need to modify is the region CodeToCapture.  Here you’ll be able to write a query expression and the application will log the request.  For now, let’s focus on the query and we’ll come back to what is captured later.

Inside the CodeToCapture region, let’s do a simple query to retrieve all Contacts whose last name is “Smith”.  In order to do this, we’d write a query like the following:

[sourcecode language="js"]var query = new QueryExpression("contact");
query.Criteria.AddCondition("lastname", ConditionOperator.Equal, "Smith");
[/sourcecode]

For context, this is where the query is placed in the method:

[sourcecode language="js"]
/// <summary>
/// This method connects to the Organization service.
/// </summary>
/// <param name="serverConfig">Contains server connection information.</param>
//<snippetSOAPLogger1>
public void Run(ServerConnection.Configuration serverConfig)
{
try
{

// Connect to the Organization service.
// The using statement assures that the service proxy will be properly disposed.
using (_serviceProxy = ServerConnection.GetOrganizationProxy(serverConfig))
{
// This statement is required to enable early-bound type support.
_serviceProxy.EnableProxyTypes();

IOrganizationService service = (IOrganizationService)_serviceProxy;

using (StreamWriter output = new StreamWriter("output.txt"))
{

SoapLoggerOrganizationService slos = new SoapLoggerOrganizationService(serverConfig.OrganizationUri, service, output);

//Add the code you want to test here:
// You must use the SoapLoggerOrganizationService 'slos' proxy rather than the IOrganizationService proxy you would normally use.
var query = new QueryExpression("contact");
query.Criteria.AddCondition("lastname", ConditionOperator.Equal, "Smith");
slos.RetrieveMultiple(query);

}

}

}

// Catch any service fault exceptions that Microsoft Dynamics CRM throws.
catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>)
{
// You can handle an exception here or pass it back to the calling method.
throw;
}
}
//</snippetSOAPLogger1>

[/sourcecode]

Now, we just run the application from Visual Studio.  A large amount of data has been redacted here, but the values you provide should be somewhat obvious for you.

SOAPLogger

After choosing your organization, the program will end and you can press the Enter key to exit.

SOAPLogger

Navigate to the folder

crm2011sdkrootsamplecodecsclientsoaploggersoaploggerbinDebug

You should see a file called output.txt, the content of which should include the HTTP Request and Response.  The request for our query looks like the following:

[sourcecode language="plain"]
HTTP REQUEST
--------------------------------------------------
<s:Envelope >reach out to us...we can help. PowerObjects provides Microsoft Dynamics CRM Service, Support, Education, and Add-Ons.

Happy CRM’ing!

Error Customizing CRM 2011 Entity Form

While working on a Microsoft Dynamics CRM 4.0 to CRM 2011 upgrade we encountered this error while trying to customize the CRM 2011 entity form:

Error: Exception of type 'System.Web.HttpUnhandledException' was thrown.

Error Message: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Error Details: Exception of type 'System.Web.HttpUnhandledException' was thrown.

Source File: Not available

Line Number: Not available

Request URL: http://servername/orgname/tools/formEditor/formeditor.aspx?action= &formtype=main&objectTypeCode=3&pagemode=iframe&sitemappath=Workplace%7cMyWork%7cnav_dashboards

Stack Trace Info: [NullReferenceException: Object reference not set to an instance of an object.]

at Microsoft.Crm.Application.Controls.FormEditorBase.AddPlaceHoldersInSection(XmlNode& secNode)

at Microsoft.Crm.Application.Controls.FormEditorBase.AddSpacerCellsInSectionIfRequired(XmlNode& secNode)

at Microsoft.Crm.Application.Controls.FormEditorBase.AddColumnsAttribute(XmlNodeList& nodeList)

at Microsoft.Crm.Application.Controls.FormEditorBase.ValidateFormXml()

at Microsoft.Crm.Web.Tools.Views.FormEditorPage.ValidateFormXml()

at Microsoft.Crm.Web.Tools.Views.FormEditorPage.GetFormXml(String formXmlString)

at Microsoft.Crm.Web.Tools.Views.FormEditorPage.ConfigurePage()

at Microsoft.Crm.Application.Controls.PageManager.OnPreRender(EventArgs e)

at System.Web.UI.Control.PreRenderRecursiveInternal()

at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

Fortunately, Microsoft seems to have already encountered this issue, we found this post on the MSDN blogs:

In this post we will expand on Microsoft's post to make it easier for the CRM community to understand.

Disclaimer: This article describes manually editing the configuration file for CRM. Making mistakes here can have devastating effects on your CRM system and is considered advanced work. Be sure to save a copy of your original export file in a safe place before making any changes to the XML. If this kind of work makes you feel queasy, ask for help from someone who is more technical.

The problem is a discrepancy between the rowspan attribute on the cell tag and corresponding row tags in customizations.xml.

Let's look at the XML for the Description field on our Opportunity Form

CRM 2011 Error Customizing Entity Form

Notice how the value of rowspan (5) matches the number of row tags in the XML? This is good XML.

Now since I like you all so much, I am going to break my XML to show what happens. Let's take one of those <row></row> tags out, save the file, compress it, import it into our CRM system and Publish.

When I try to customize the main Opportunity form here's what I get:

If you don't have development errors enabled, you'll just see this, but I would get the error above if I were tracing this error.

To fix this problem we need to get the customizations.xml for the entity that is giving you trouble. Go to Settings, Customizations, Solutions. Create a new, unmanaged solution and add the entity that is producing the error. You will not need to include required components; in fact, you'll be glad that you didn't. Export the solution, extract the files and open customizations.xml with a XML text editor.

Now for the tedious part: Perform a search for rowspan= and find the section or sections that contain a rowspan count attribute that is greater than the number of <row> tags for the section. Here's where not including required components is going to save you time. When you find the section that has fewer row tags than rowspan specifies, just go ahead and add another set of <row></row> tags before the last one. Complete your search for additional rowspan attribute to row tag discrepancies and then reimport the solution to your CRM system. This will fix the error above.

We hope you found our explanation helpful. If you're encountering this error and would prefer the help of a CRM professional to resolve it, give your CRM super heroes a call!

Happy CRM'ing!

CRM custom reports - Issues with pre-filtering and non-searchable primary key for an entity.

We're gonna get a bit technical today.

In Microsoft Dynamics CRM, one of the reasons for turning on pre-filtering for custom reporting is to associate the report with the open form (record) so that it picks up the unique identifier of the opened record and passes it to the report. So, when the report is run, it filters records and only displays information about the opened record.

The following is the FetchXML report definition code snippet for turning on pre-filtering (for entity Cases- a.k.a. incident):

<entity name="incident" enableprefiltering="true" prefilterparametername="FilteredIncident">

CRM Team

When running a custom report, if you are getting following message that prevents the report being rendered- follow the instructions below.

It can take you some time to figure out the issue like this.

As per the message above, the pre-filtering tried to use the primary key field of the entity to pull the record. But the field – in this case incidentid was not found because it was not searchable. Pre-filtering uses the advice find to look for the record. In this case, the incidentid was not searchable and pre-filtering did not find that field and hence the error.

Solution:

Make the field searchable by going to Settings->Customizations->Customize the system->Cases (primary entity the report is for) and open the field and make it searchable and publish customizations.

Everything should work as expected!

Hope this will save some time if you are experiencing the above issue. If you have any custom reporting needs or issues please reach out to our CRM team at PowerObjects.

Happy CRMing!

Microsoft Dynamics CRM and Dynamic Option Sets

If you were to imagine a custom form in Microsoft Dynamics CRM where you could select any entity and any field on that entity you would realize a few things about option sets.

  1. To enter and support every entity and field would be a daunting and impossible task.
  2. Even if you were to spend the time tackling the previous hurdle, any customizations you made to those entities would have to be tracked and re-applied in the option sets, thereby duplicating your workload.
  3. Option sets do not inherently support dynamic lists.

But wait, you might say, there's an example of how to dynamically modify the option set with JavaScript that ships with the SDK. This example still relies on the idea that you will have pre-filled the option set with all the possible options and then will remove the ones you no longer want. This really wasn't a viable solution for what we were trying to do either.

The solution we came up with was to utilize single line of text fields hidden on the form to store the values for our option sets. We'll demonstrate this with one mapping field. So let's start by setting up our form.

We create a new entity with the following fields:

We'll add the fields to our form and leave the "Selected" fields visible for now:

dynamic option sets: mapping field

Now we can dive into the JavaScript for populating our Mapping Entity field. It should be noted that the code has been written for readability. If you do plan on implementing this there are places where refactoring should be performed and efficiency improved.

function getAttributes(entityName) {

    var lookupFields = Xrm.Page.ui.controls.get("po_mappingfield");

    try {
        var xml = "" +
        "<!--?xml version="1.0" encoding="utf-8"?-->" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "EntityFilters" +
        "Attributes" +
        "" +
        "" +
        "MetadataId" +
        "00000000-0000-0000-0000-000000000000" +
        "" +
        "" +
        "RetrieveAsIfPublished" +
        "true" +
        "" +
        "" +
        "LogicalName" +
        "" + entityName + "" +
        "" +
        "" +
        "" +
        "RetrieveEntity" +
        "" +
        "" +
        "" +
        "" + "";

        var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");

        xmlHttpRequest.Open("POST", "/XRMServices/2011/Organization.svc/web", false);
        xmlHttpRequest.setRequestHeader("Accept", "application/xml, text/xml, */*");
        xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        xmlHttpRequest.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
        xmlHttpRequest.send(xml);

        var doc = xmlHttpRequest.responseXML;
        var nodeList = doc.selectNodes("//c:AttributeMetadata");
        for (i = 0; i < nodeList.length; i++) {
            xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
            xmlDoc.loadXML(nodeList[i].xml);
            if (xmlDoc.selectSingleNode("//c:DisplayName/a:UserLocalizedLabel/a:Label") != null) {
                var display = xmlDoc.selectSingleNode("//c:DisplayName/a:UserLocalizedLabel/a:Label").text;
                var value = xmlDoc.selectSingleNode("//c:LogicalName").text;
                var option = document.createElement("OPTION");
                option.value = option.innerText = value;
                option.text = option.innerText = display;
                lookupFields.addOption(option);

            }
        }
    }
    catch (err) {
        alert("Script encountered error: " + err.name + "nMessage: " + err.message);
    }
}

The XML request in this function retrieves all available attributes of the entity that is passed into the function. After we've received the XML response back from the request, we loop through each attribute node in the document and use XPath statements to grab both the display and schema name.

Finally, we create option elements, fill out their value and text attributes and add it to our option set.

Now that we have a helper method, which will populate our control, we need to call it from an event and pass it a value. For this example, we'll utilize the onLoad functionality of our form and hardcode the value lead to be passed to our helper method.

 function OnLoadGetAttributes()
{
    getAttributes("lead");

    $("#po_mappingfield").html($("option", "#po_mappingfield").sort(function (a, b) {
        return a.text == b.text ? 0 : a.text < b.text ? -1 : 1
    }));

    $("#po_mappingfield option:eq(0)").attr("selected", "selected");

}

In addition to calling our helper method, we utilize jQuery to sort our returned results for us. Then we ensure the dropdown field is set to the default blank option.

Now we'll add our JavaScript and the jQuery library to our solution as a web resource, add the libraries to our source and bind our form onLoad event to the OnLoadGetAttributes method.

Once published, you should be able to create a new mapping entity from CRM with a dropdown that is populated with all available attribute or field names:

Now that we've got the values in a dropdown, we need a way to store them. Since CRM does not have an option set tied to the back of this, in order for those values to persist, we'll need to affix another method to the onChange event of the po_mappingfield dropdown:

function onLookupFieldChange() {
    var fieldLookup = document.getElementById("po_mappingfield");
    var field = fieldLookup.options[fieldLookup.selectedIndex].value;

    var selectedMappingField = Xrm.Page.data.entity.attributes.get("po_selectedmappingfield");
    selectedMappingField.setValue(field);
}

You might notice here that we're utilizing generic JavaScript to access the Mapping Field dropdown rather than the CRM provided getValue function. Since this isn't a real option set as far as CRM is concerned, it won't pass back any value.

After adding our new function to our JavaScript web resource, we'll make sure to call the function on the onChange event of the Mapping Field.

If you create a new Mapping Entity and select an option from the dropdown, you should now see the Selected Mapping Entity field populated with the schema name of the attribute:

This new value will persist when saving the entity. We can now hide this field if we wished too. It is now just a friendly storage site on your form.

There's one piece of the puzzle left and that's how to handle when the page loads. If we were to load the page as it exists, our hidden field would contain the schema name of our attribute, but the dropdown would only have the default value selected.

On our current onLoad function, we can add a check to determine if a Selected Mapping Field exists:

function OnLoadGetAttributes()
{
    getAttributes("lead");

    $("#po_mappingfield").html($("option", "#po_mappingfield").sort(function (a, b) {
        return a.text == b.text ? 0 : a.text < b.text ? -1 : 1
    }));

    var selectedMapping = Xrm.Page.data.entity.attributes.get("po_selectedlookupfield");

    if (selectedMapping.getValue() != null) {
        $('#po_mappingfield option[value="' + selectedMapping.getValue() + '"]').prop('selected', true);
    }
    else {
        $("#po_mappingfield option:eq(0)").attr("selected", "selected");
    }
}

Now when our page loads, not only will the dropdown be populated, but it will have selected the proper attribute if we have one stored in our Selected Mapping Field.

Bam!!! There you have it. Hope this helps you as it has the CRM Experts at PowerObjects.

Happy CRM'ing!

How to properly connect to CRM

For Microsoft Dynamics CRM, there are various ways to connect to CRM's web services. In many applications, such as a web portal, a long lived and cached connection is desired. A common rookie mistake is to open a connection and assume it is open and alive for ever. If the security token does expire or become invalid, and a check is not done properly, an error such as this will be encountered:

"The HTTP request to 'https://org.crm.domain.net//XRMServices/2011/Organization.svc' was aborted. This may be due to the local channel being closed while the request was still in progress. If this is not desired, then update your code so that it does not close the channel while request operations are still in progress."

The reason for this message is the connection to CRM has terminated such as due to an expired security token or an iisreset and the code assumed the connection was still open.

The issue can be resolved by following the below steps:

This solution may seem simple, but it takes care of caching the security token and will re-connect if it expires. This can then reduce or eliminates http request aborted errors.

Happy CRM'ing!