Friday, November 30, 2012

Error on load of queue form in CRM 2011

I was setting up a new dev environment. It was working perfectly and suddenly, I can’t create a new queue or modify the existing queues.
I was getting the following error message.
image
I had a look in the event viewer. It was showing a warning message as shown in the screen shot.
image
I could not figure out the problem. I tried to repair the CRM. This happened after I setup the email router.
So start looking what I did. I found out that I was using “User Specified” access credential for incoming profile. By default, it is not allowed if you are not using SSL (HTTPS). But there is workaround as explained on TECHNET. The article mentioned that I have to manually add registry key DisableSecureDecryptionKey with value 1.  That’s what I did and that was a problem. I created a key instead of creating a DWORD value. To make this work, it should be a “DWORD” not a “Key”.
image
The DisableSecureDecryptionKey entry should look like following screen.
image
I made the change and it worked like a charm….

Thursday, November 22, 2012

My experience with Microsoft Dynamics CRM 2011 Custom Code Validation Tool

 

Microsoft released the “Microsoft Dynamics CRM 2011 Custom Code Validation Tool”  in May 2012. The purpose of this tool is to detect the potentials issues in  HTML and JavaScript web resources when  CRM2011 starts supporting multiple browsers. 

The cross browser functionality was supposed to be released in Q2 2012 but, that did not happen. The next release of CRM2011 code name Polaris is coming out in December 2012. One of the many features included in Polaris is cross browser compatibility. This blog lists  “What’s included in Polaris?”.

After reading about Polaris, I decided to try “CRM 2011 Custom Code Validation Tool”. Here is the link to download the tool. Here are my findings. The results are mixed but you can make up your own mind.

The following screen shot displays the results from the tool. To check the results, the user has to scroll down the list of web resources one by one.

image

Issues found by the tool

I included some old and unsupported code in the libraries to test the tool. Here are some of the screen shots of potential issues found by the tool.

image

image

So far so good. Here is the screen shot of the JavaScript webresource with most issues.

image

The thing that shocked me the most is that this code is straight from the CRM SDK sample provided by Microsoft.

Issues ignored by the tool

I intentionally added some unsupported code to the JavaScript web resource. But the tool did not identify this code as potential issue.

Here is the screen shot of one such unsupported code. I am using code to attach the custom CSS on form onload.

image

Conclusion

This is very good to identify the potential issue. But I can’t say how reliable it is.

Anyway  don’t use any unsupported code intentionally.

Monday, November 5, 2012

List of Currencies in CRM2011

To create a new currency in CRM, we have an option to select currency type of “System” or “Custom” as shown in the screen shot.

image

If we choose “system” for currency type which is the default selection, we can select  currency code from a look up view as shown in the following screen shot.

image

The selection from the lookup will fill all the required fields (“currency name”, “currency precision”, “currency symbol”) for the currency. We have to manually provide the value for the “exchange rate” field.

Now if you want all the currencies in your system then you have to repeat this process hundred plus times.

I had a look around to find a list of currencies to import into the system instead of creating these record one by one.There is a URL in  currency lookup view with the view id. Here is the URL from my environment.

http://servername/orgname/_controls/lookup/lookupinfo.aspx?AllowFilterOff=1&DefaultType=9105&DefaultViewId=%7b1A364391-BF41-407B-B91F-5C326BAF0A3B%7d&DisableContextMenu=1&DisableQuickFind=0&DisableViewPicker=1&LookupStyle=single&ShowNewButton=1&ShowPropButton=1&browse=1&objecttypes=9105

I looked into the database and found a saved query record with a name  “Currency List” with the viewid shown in the above URL. But the “Query API” field value of the record was showing “TransactionCurrency.RetrieveDotNetCurrencies”. It suggested me that this currency list is not stored in the database table. It may be residing in the database but I did not find it.

I used “Fiddler” and  internet “Developer tools”  and compile the list of currencies in the lookup view. The list is XML spread sheet 2003 format.  Here is the link to download the file. This file can be imported into the system using data import tool. Here is screen shot of some sample data from the file.

image

The “regionname” does not get stored in the currency record. You need to provide the exchange rate for the currencies against your base currency.

When you import this file into CRM map the fields of this file to the currency entity of the system. The mapping screen will look like this.

image

Import process will import 102 records and 62 records will fail. The reason for the failed records is duplicate currency code.

If you look into the currency list, there are a lot of duplicate currency codes. For example “CAD” currency code is repeated 4 times.

image

INR, EUR and some other currencies are repeated multiple time too.

Make the changes to the file as required and import it into CRM using built-in import tool.

I hope this helps. 

Tuesday, October 30, 2012

Workflow assembly to cancel waiting workflows - Part 2

In my last blog, I posted a code for a custom workflow assembly that updates the status of waiting workflow to “Cancelled” when a new instance of the workflow is created.
I did not like the fact that I need to pass the name of workflow as a parameter to the assembly. Then this thought across my mind that I may be able to use this workflow for some other scenarios. For e.g What will happen if I deactivate an account which have one or more workflows in a waiting status?
Personally, I would like to cancel all waiting workflows if I deactivate the account. So I change the code.
Now this workflow assembly can be used in 2 different scenarios.
  1. If I pass the name of the workflow to the assembly. It will update the status of waiting instance of the workflow to “Cancelled” .
  2. If I pass nothing, then it will update the status of all the waiting workflows to “Cancelled” for an entity regardless, of the name of the workflow. In the following screen shot, I am leaving the work flow name empty.
image_thumb[10]
Click here to download the workflow.zip. I have uploaded the whole solution.

Workflow assembly to cancel waiting workflows - Part 1

Sometimes we need recursive workflows with waiting condition in the system. For example a workflow that fires on creation and on change of follow up date of the task. This workflow may wait for few days after “follow up” date and create a new task or send an email. If the follow up date is updated, the system will start a new instance of the workflow. It results  in multiple waiting workflows in the system. It will effect the performance of the system.

The ideal situation will be a workflow that can cancel any waiting workflows on start of a new  instance of the workflow.  The original idea is from Ayaz Ahmed’s blog. I took that idea and came up with this  CRM 2011 workflow assembly. It checks for any waiting instances of the workflow and update their status to “Cancelled”. Here is the code.

using System;
using System.Activities;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Workflow;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Client;

namespace Workflow
{
    public class KillWaitingWorkflows: CodeActivity
    {
        protected override void Execute(CodeActivityContext executionContext)
        {

            //Get the tracing service
            //ITracingService tracingService = executionContext.GetExtension<ITracingService>();

            //Get the context
            IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
            IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
            IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

            //get workflow name from the input property
            string sWorkflow = workflowName.Get<string>(executionContext);

            //Get a service context to use linq queries and 
            var ServiceContext = new OrganizationServiceContext(service);

            try
            {
                QueryExpression query = new QueryExpression("asyncoperation");

                //get columns
                ColumnSet cols = new ColumnSet(new string[] { "asyncoperationid", "statecode" });

                //create conditions
                ConditionExpression c1 =
                    new ConditionExpression("name", ConditionOperator.Equal, sWorkflow); // name of the workflow -input property
                ConditionExpression c2 =
                     new ConditionExpression("regardingobjectid", ConditionOperator.Equal, context.PrimaryEntityId);// entity id
                ConditionExpression c3 = 
                     new ConditionExpression("statecode", ConditionOperator.Equal, 1);//statecode of waiting

                //create the filter
                FilterExpression filter = new FilterExpression();
                filter.FilterOperator = LogicalOperator.And;
                filter.AddCondition(c1);
                filter.AddCondition(c2);
                filter.AddCondition(c3);

                query.ColumnSet = cols;
                query.Criteria.AddFilter(filter);

                //get the collection of results
                EntityCollection colResults = service.RetrieveMultiple(query);

                foreach (Entity async in colResults.Entities)
                {
                    Entity e = async;

                    //change the status of the system job
                    e["statecode"] = new OptionSetValue(3); //cancelled

                    //update the object             
                    service.Update(e);
                }
 
            }//end try
            // Catch any service fault exceptions that Microsoft Dynamics CRM throws.
            catch (Exception ex)
            {
                // You can handle an exception here or pass it back to the calling method.
                throw;
            }
            }
        
    [Input("Work Flow Name")]
    [Default("workflow name")]
    public InArgument<string> workflowName { get; set; }
               
    }
}
  
  • Compile the workflow assembly and register it using plugin registration tool.
  • If everything goes smoothly, you can see this workflow assembly available in workflow. It will look like the following screens.
image

  • I am calling the assembly before the waiting condition. Click on the “View properties” link next to assembly name highlighted in yellow to specify the name of the workflow.
image

  • Activate the workflow and test it.
The problem with this code is that we have to pass “workflow name” as input parameter to the assembly. Then an ideas came to me to use this for my advantage. Wait of my next blog “Workflow assembly to cancel waiting workflows Part 2”.

Sunday, September 30, 2012

Outer Joins in Fetch XML queries in CRM2011

This blog will walk you through on how and when to use “Outer” joins in CRM2011 fetch queries. Outer joins can be very important for  fetch xml based SSRS reports.
Here are some of the examples.

Example 1

Creating a query to retrieve  opportunities with fields from related account entity. Here is the query.
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
  <entity name="opportunity">
    <attribute name="name" />
    <attribute name="customerid" />
     <attribute name="estimatedvalue_base" />
     <order attribute="name" descending="false" />
    <link-entity name="account" from="accountid" to="customerid" visible="false" link-type="outer" alias="accountid">
      <attribute name="telephone1" />
    </link-entity>
</entity>
</fetch>

This query will return name(Topic), customerid(Potential Customer), estimatedvalue_base(Estmated Revenue), telephone1(Main Phone from account entity).
This query will return the above columns for all the opportunities. What will happen if the potential customer on opportunity is a contact instead of an account? The answer is it will still return all the opportunities as there is an outer join between the two entities. It will return the empty telephone 1 column. If we remove the link-type="outer" then the query won’t return any opportunities that have contacts as potential customers.
This query is also possible using advance find.

Example 2

What if we want to return all the opportunities and also any phone call activities related to these opportunities. This is also achievable using outer joins. There is 1:N relationship between opportunity and activitypointer entity. Therefore the query will return multiple records for the same opportunity if there are more than one phone call recorded against an opportunity. Here is fetch xml for the query
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
  <entity name="opportunity">
    <attribute name="name" />
    <attribute name="customerid" />
    <attribute name="estimatedvalue_base" />
     <order attribute="name" descending="false" />
    <link-entity name="account" from="accountid" to="customerid" visible="false" link-type="outer" alias="accountid">
      <attribute name="telephone1" />
    </link-entity>
<link-entity name="activitypointer" from="regardingobjectid" to="opportunityid" visible="false" link-type="outer" alias="phonecall">
      <attribute name="subject" />
 <attribute name="description" />
 <attribute name="createdon" />
<filter type="and">
      <condition attribute="activitytypecode" operator="eq" value="4210" />
</filter>
    </link-entity>
  </entity>
</fetch>

The above fetch xml will retrieve the subject, description, createdon  columns for related phone call activities as well as the columns mentioned in example one.
I have created a sample SSRS report using the above fetch xml query. Here is result. You can change the display name for the columns in the data set as required.

image

Saturday, September 22, 2012

Single Sign On for CRM 2011 Online

In July 2012 CRM online has been moved to “Online Commerce Platform”. It is same platform used by Office 365. One of the benefits of this change is that the customers can access various office 365 services using same username and password. But the thing that excites me the most is the ability to configure Active Directory Federation Services (ADFS) to work with Office 365. This makes single sign on a reality for CRM Online users. The users can use their AD credentials to login to CRM Online, Office 365 services and other on premise applications.
I did some research and found these 2 blogs on how to setup ADFS for CRM Online/ Office 365.
http://blogs.msdn.com/b/girishr/archive/2012/09/05/dynamics-crm-identity-federation-demo-setup.aspx
http://www.messageops.com/documentation/office-365-documentation/ad-fs-with-office-365-step-by-step-guide
Go Dynamics CRM….