Thursday, January 27, 2011

CRM Web Service Toolkit Works for CRM 2011

This is a quick update with regard to CRM Web Service Toolkit. I had a chance to play around with the toolkit on CRM 2011 today, it turns out to be a surprise that the toolkit just works fine on CRM 2011 without requiring any modification. I tried to run all the unit tests that I developed in CrmServiceToolkitTest.aspx page, all tests have passed without any problems.

CRM Web Service Toolkit on CRM 2011

It's not me who has made this magic, but because CRM 2011 provided full backward compatibility with its web service interfaces. However, it's not my recommendation to use the CRM4 style web service interfaces, neither is this the best practice. But since CRM2011 SOAP Endpoint documentation is still under construction (shown below), I think it's not a terribly bad idea to keep using the CRM4 style web service interfaces for the time being, until the SOAP Endpoint details have been fully revealed.

CRM2011 SOAP EndPoint Doc 

Some may argue that we should all use CRM2011's REST endpoint instead since it's a new approach which may be more efficient, but be advised that the REST endpoint is not a full implementation of all CRM services. You are limited to only Create, Retrieve, Update, and Delete actions when you use REST endpoint.

I only tested on CRM2011 Beta, but I am relatively positive that the toolkit will work just fine for RC version, most likely the RTM version as well.

Thursday, December 30, 2010

MSCRM 4.0: LINQ to FetchXML Queries

When it comes to querying data from Microsoft Dynamics CRM server, I am a much big fan of FetchXML if compared to CRM Query Expression. There are a few reasons for that:

  1. FetchXML is more powerful, it can do something that Query Expression may not be able to do the same, such as aggregation, conditional criteria in linked entity, etc.
  2. FetchXML is more readable and more maintainable, it's much easier to add one or more extra attributes to be returned, or in a different scenario that you may want to add one or more new query criteria.
  3. FetchXML is more intuitive, and it could make your code refactoring effort a lot easier when you need to do so.

But FetchXML does come with a caveat, you need to deal with the XML string that MSCRM server responds back to you. There are a number of CRM SDK documents telling you how to perform a FetchXML query, but usually they all stopped at the point that you get the result XML back from CRM server. You don't actually have any clue about the next step, which is how you should process and manipulate the result in XML format in an efficient and elegant fashion.

In this blog post, I am going to show you a short snippet code that tells how you can properly do this, using the two XElement extension methods that I shared in my previous blog post.

Suppose that you have a requirement to get all CRM accounts in Washington state (WA), so you came up with the following FetchXML query:
<fetch mapping='logical' count='10'>
   <entity name='account'>
      <attribute name='name' />
      <attribute name='numberofemployees' />
      <attribute name='owninguser' />
      <attribute name='customertypecode' />
      <attribute name='donotemail' />
      <attribute name='createdon' />
      <filter>
         <condition attribute='address1_stateorprovince' operator='eq' value='WA' />
      </filter>
   </entity>
</fetch>

And CRM may return a result like the following one:
<resultset morerecords="0" paging-cookie="&lt;cookie page=&quot;1&quot;&gt;&lt;accountid last=&quot;{4BC7A5F8-AD02-DE11-83DE-0003FFE51F61}&quot; first=&quot;{25C7A5F8-AD02-DE11-83DE-0003FFE51F61}&quot; /&gt;&lt;/cookie&gt;">
   <result>
      <name>AB Company</name>
      <numberofemployees formattedvalue="95">95</numberofemployees>
      <customertypecode name="Customer" formattedvalue="3">3</customertypecode>
      <donotemail name="Allow">0</donotemail>
      <createdon date="2/22/2008" time="4:00 PM">2008-02-22T16:00:00-08:00</createdon>
      <accountid>{25C7A5F8-AD02-DE11-83DE-0003FFE51F61}</accountid>
   </result>
   <result>
      <name>Baldwin Museum of Science</name>
      <numberofemployees formattedvalue="250">250</numberofemployees>
      <customertypecode name="Customer" formattedvalue="3">3</customertypecode>
      <donotemail name="Allow">0</donotemail>
      <createdon date="2/22/2008" time="4:00 PM">2008-02-22T16:00:00-08:00</createdon>
      <accountid>{3AC7A5F8-AD02-DE11-83DE-0003FFE51F61}</accountid>
   </result>
   <result>
      <name>Blue Yonder Airlines</name>
      <numberofemployees formattedvalue="150">150</numberofemployees>
      <customertypecode name="Other" formattedvalue="12">12</customertypecode>
      <donotemail name="Allow">0</donotemail>
      <createdon date="2/22/2008" time="4:00 PM">2008-02-22T16:00:00-08:00</createdon>
      <accountid>{45C7A5F8-AD02-DE11-83DE-0003FFE51F61}</accountid>
   </result>
   <result>
      <name>Brown Company</name>
      <numberofemployees formattedvalue="39">39</numberofemployees>
      <customertypecode name="Prospect" formattedvalue="8">8</customertypecode>
      <donotemail name="Allow">0</donotemail>
      <createdon date="2/22/2008" time="4:00 PM">2008-02-22T16:00:00-08:00</createdon>
      <accountid>{4AC7A5F8-AD02-DE11-83DE-0003FFE51F61}</accountid>
   </result>
   <result>
      <name>Budget Company</name>
      <numberofemployees formattedvalue="32">32</numberofemployees>
      <customertypecode name="Reseller" formattedvalue="9">9</customertypecode>
      <donotemail name="Allow">0</donotemail>
      <createdon date="2/22/2008" time="4:00 PM">2008-02-22T16:00:00-08:00</createdon>
      <accountid>{4BC7A5F8-AD02-DE11-83DE-0003FFE51F61}</accountid>
   </result>
</resultset>
Your job, as a CRM developer, is to process the result in an Object-Oriented fashion after you have got the result from CRM server. Suppose you are a fan of LINQ query as well, you may want to do it in an elegant way by utilizing the power of LINQ query.

To help you achieve this goal, you may include the two extension methods that I just mentioned in one of your static utility classes, and then start to write your FetchXML query code. The following is a short snippet code that could be used as your start point. You may be able to tell that what I am showing you here is a snippet code from an NUnit test.
string fetchXml = @"
<fetch mapping='logical' count='10'>
   <entity name='account'>
      <attribute name='name' />
      <attribute name='numberofemployees' />
      <attribute name='owninguser' />
      <attribute name='customertypecode' />
      <attribute name='donotemail' />
      <attribute name='createdon' />
      <filter>
         <condition attribute='address1_stateorprovince' operator='eq' value='WA' />
      </filter>
   </entity>
</fetch>
";

string fetchResult = crmService.Fetch(fetchXml);
XDocument xml = XDocument.Parse(fetchResult);

var accounts = from item in xml.Root.Elements()
               select new
               {
                   AccountId = item.ParseValueAs<Guid>("accountid"),
                   Name = item.ParseValueAs<string>("name"),
                   NumberOfEmployees = item.ParseValueAs<int?>("numberofemployees"),
                   DonotEmail = item.ParseValueAs<bool?>("donotemail"),
                   CustomerTypeCode = item.ParseValueAs<int?>("customertypecode"),
                   CustomerType = item.ParseValueAs<string>("customertypecode", "name"),
                   CreatedOn = item.ParseValueAs<DateTime?>("createdon"),
               };

var createdOn = new DateTime(2008, 2, 22, 16, 0, 0);

// Get the first account returned
var firstAccount = accounts.ElementAt(0);

// Assertions for the first account returned
Assert.AreEqual(new Guid("{25C7A5F8-AD02-DE11-83DE-0003FFE51F61}"), firstAccount.AccountId);
Assert.AreEqual("AB Company", firstAccount.Name);
Assert.AreEqual(95, firstAccount.NumberOfEmployees);
Assert.AreEqual(false, firstAccount.DonotEmail);
Assert.AreEqual(3, firstAccount.CustomerTypeCode);
Assert.AreEqual("Customer", firstAccount.CustomerType);
Assert.AreEqual(createdOn, firstAccount.CreatedOn);

As you may see, I have tried to parse customertypecode (a picklist field in account entity) in two different ways to serve different purpose. First I tried to get the integer value of the picklist field, then I tried to get the field's value attribute which is what the integer value represents for. The second value could be more meaningful to the end user of your application.

As I have mentioned in my previous blog post, you should use basic .NET CLR types as the target types when you try to parse FetchXML result.

All I have shown here is not actually something of rocket science, but hopefully it has given you enough idea how to properly parse a CRM FetchXml query result string in an easy way.

Cheers, and Happy New Year to everyone!

Sunday, December 26, 2010

From LINQ to XML to LINQ to Objects: Two Generic XElement Extension Methods

LINQ is one of the most amazing programming language innovations in the few recent years. Coming with .NET framework 3.5, there are a whole new stack of XML classes that help you manipulate XML document in your .NET program using LINQ approach.

In real-world programming practice, we often have the need to read from an XML file and convert to an enumerable list of strong-typed objects which you start to work with in your .NET application. But I have never come across a complete sample code that shows me how to do this properly in a simple way, so I came up with the following two extension methods that might help you if you need to do the same thing in your life.

/// <summary>
/// Convert the value of an XElement's child element to the specified generic type.
/// </summary>
/// <typeparam name="T">The target type to be used to convert the XML element value</typeparam>
/// <param name="xe">The XML element that contains child elements</param>
/// <param name="childNode">The child element that you want to parse its element value</param>
/// <returns>Converted value of type T</returns>
public static T ParseValueAs<T>(this XElement xe, XName childNode)
{
    return ParseValueAs<T>(xe, childNode, null);
}

/// <summary>
/// Convert the value of an XElement's child element (or one of its attributes) to the specified generic type.
/// </summary>
/// <typeparam name="T">The target type to be used to convert the XML element or attribute value</typeparam>
/// <param name="xe">The XML element that contains child elements</param>
/// <param name="childNode">The child element that you want to parse its element or attribute value</param>
/// <param name="attribute">If provided, the attribute value will be parsed. Otherwise, the element value will be parsed</param>
/// <returns>Converted value of type T</returns>
public static T ParseValueAs<T>(this XElement xe, XName childNode, XName attribute)
{
    if (xe == null)
        return default(T);

    XElement childElement = xe.Element(childNode);
    if (childElement == null)
        return default(T);

    bool valueIsEmpty = attribute == null
                            ? string.IsNullOrEmpty(childElement.Value)
                            : childElement.Attribute(attribute) == null || string.IsNullOrEmpty(childElement.Attribute(attribute).Value);

    if (valueIsEmpty)
        return default(T);

    string value = (attribute == null) ? childElement.Value : childElement.Attribute(attribute).Value;

    Type type = typeof(T);

    if (type == typeof(bool) || type == typeof(bool?))
    {
        switch (value.ToLower())
        {
            // You may tweak the following options a bit based on your needs
            case "1":
            case "true":
            case "yes":
                value = "true";
                break;

            case "0":
            case "false":
            case "no":
                value = "false";
                break;

            default:
                return default(T);
        };
    }

    TypeConverter converter = TypeDescriptor.GetConverter(type);
    return (T)converter.ConvertFromString(value);
}
Given that you have an XML file, suppose it's called contacts.xml, like this:
<Contacts>
  <Contact>
    <Name>Patrick Hines</Name>
    <Phone>408-555-1234</Phone>
    <BirthDate>1990-01-01</BirthDate>
    <Address>123 Main St, San Jose, CA, 94500</Address>
  </Contact>
  <Contact>
    <Name>Patrick Hines</Name>
    <Phone>510-444-0123</Phone>
    <Address>345 Center Ave, Milpitas, CA, 94439</Address>
  </Contact>
</Contacts>
You can use the following C# snippet to convert the XML to your LINQ objects.
XDocument xml = XDocument.Load("contacts.xml");

var contacts = from item in xml.Root.Elements()
               select new
               {
                   Name = item.ParseValueAs<string>("Name"),
                   Phone = item.ParseValueAs<string>("Phone"),
                   BirthDate = item.ParseValueAs<DateTime?>("BirthDate"),
                   Address = item.ParseValueAs<string>("Address"),
               };
I used an anonymous type for simplicity, but you can always use any defined class that you may already have in your application, so you are working with the objects that you are familiar with.

As usual, here are a few notes before we conclude this blog post:
  • You should always try to use the basic CLR types as your target type, such as int, bool, string, DateTime, etc.
  • As I have mentioned, I have offered a pair of overloaded methods, they are serving for different purpose. One of them is parsing the XML element's value, another one is parsing an XML element's attribute value. With the overloaded signatures, you have the flexibility to either read the XML element or an XML element's attribute.
  • You may want to tweak a little bit about how you want to parse into boolean value depending on your XML data and business requirement.
  • I didn't include any exception handling in the code, which you may want to add, if your XML data is unpredictable.
  • It's advisable to return nullable type, so when the XML element or attribute doesn't exist, it return null as the value, which makes more sense in most cases.

[Update - Jan 6, 2010] I updated the code so that the extension methods now support XML namespace.

If you are coming Microsoft Dynamics CRM world, I will show you in my next blog post about how to use the above extension methods to properly parse your FetchXML query result. Stay tuned.

Hope this helps, cheers!

Friday, November 26, 2010

SharpSSH: A Recompiled Version Compatible with Latest 64-bit Windows Server System

One of my recent project works is to integrate our CRM solution with a few data sources from different vendors, which requires me to develop an ETL component to download incremental update files from SFTP sites before processing them in our CRM application.

Since there is no support of SFTP in .NET framework itself, I have to look for alternative solution, so I ended up with the open source library called SharpSSH, which is pretty promising.

I was very happy that it worked with my first try on my local development VPC image which is on Windows Server 2003, 32-bit edition. But as soon as I promoted my ETL component to our UAT environment which is on Windows Server 2008 R2 (of course, 64-bit system), I ran into a "Bad Data" error when my component was trying to make connection to the SFTP site.

I did a little Google search, and found the solution here. I followed snowcoder's instructions, made a bunch of changes, and recompiled the library. Then everything worked for me on the 64-bit system.

Here are the download links, I hope that they could save you some time if you ever need this component (There were some errors in snowcode's original code he pasted there probably due to HTML formatting issue):

SharpSSH-1.1.1.13 Library (DLLs only)

SharpSSH-1.1.1.13 Source Code

[DISCLAIMER] I am by no means an expert on hardcore networking or cryptology programming (I have no intention to become one either at this moment), I am posting the recompiled library just for your convenience. All credit goes to Tamir Gal, snowcoder, and Mono Project. The license should stay as whatever it is originally.

[Further Note - Updated December 2011] There is another open source library in the community called SSH.NET, which you might want to check out. The library has got support for .NET 3.5, .NET 4.0, Windows Phone, Silverlight respectively. It looks very promising, and it has been actively maintained by the author.

Hope this helps!

Thursday, November 25, 2010

Non-sense CRM4 Customization Import Error

Here is another CRM4 customization import error that I recently ran into, but it's a non-sense and probably a nasty one.

What the problem is, I have been trying to update my development VPC image from rollup 9 to a more recent one. As soon as my VPC image is updated to any rollup after 10, I start to receive an error message when I try to import CRM customizations. The weird thing is, this error even happens in the same environment. By the same environment, I mean that it happens even I was exporting the CRM customizations and then re-importing the same customization file on the same server box.

Here is what the error message looks like:
Failure: incident_activity_parties: Cascade link type 'NoCascade' is invalid for Delete.
Nonsense Customization Import Error
Since I had a little bit cycle today and I was aware that Microsoft has just released Rollup 14 last week, I thought it would be a good chance to give it another try. I usually had pretty good confidence at Microsoft team's fast turnaround in terms of bug fixing. Unfortunately it's not the case this time, the same error persisted after I updated to Rollup 14.

I was naive enough, I thought that I could become a hero if I could find a solution for this issue. So I turned on CRM server trace log, and re-ran the import process. After about two tries (first try failed for a different reason), I got 115 log files in my CRM trace folder (they consumed 1.1GB hard drive space on my poor VPC image). However those log files didn't give me much helpful information, except another error message that was thrown before the previously mentioned message, which stated that "Failed to import entity relationship incident_activity_parties", which I don't have any clue why it has happened either.

After about 30 minutes of experimenting and Google search, I gave up on this. A few folks in the community have been suggesting to muck around the customization xml file, which I am not so encouraged to go this path, as I believe that could possibly cause more problems in the long run that it actually solves.

[Update - Feb 28, 2011] I finally figured out what the problem is, I had Data Migration Manager installed on my server. As soon as I uninstalled DMM and the problem went away. Still a mystery for me, but I can now finally go with more recent rollups.

Wednesday, November 24, 2010

JavaScript Snippet: Test Whether a JavaScript Variable is Regular Expression

Here is a short snippet if you ever need to check whether a JavaScript variable is regular expression.

function isRegExp(obj) {
   return Object.prototype.toString.call(obj) === '[object RegExp]';
};

You might be wondering why on the earth you ever need this function. It could be when you want to develop a validation framework that takes a variable for validation purpose, and you want to make the validation framework flexible as flexible as possible, so that the variable could be a function, string or even a regular expression. Your validation framework would do different thing based on the type of the validation variable that is passed to the framework. Hope this makes sense to you now, maybe you have a totally different reason for using it, which is absolutely up to you... :-)

[UPDATE - Dec 10, 2010]: A couple of hours after I published the original blog post, I figured that I should be able to use JavaScript instanceof operator to achieve the same purpose, which could be an easier solution. But further reading indicated that will not work correctly if you are evaluating a cross-frame RegExp object. If you are interested, you may continue reading a very detailed explanation with regard to a similar testing of JavaScript Array object. I have also updated my code a little bit so it looks pretty much the same as kangax's isArray function now, shamelessly. ^_^

A lesson learned from this is, you should only trust JavaScript instanceof operator if your code never has the need to go cross frames. If you want a robust solution to evaluate the type of a JavaScript object, you better take the similar approach as I have just illustrated you.

You can always expect some surprise from JavaScript. Stay tuned until next time.