Dynamics Light Seeing the (Silver)Light effect in Dynamics CRM

14Dec/093

Pass Custom QueryString on CRM Form

You might encounter a scenario where you want to pass custom querystrings into your CRM form.
It sounds pretty straight forward until you encounter this error message

[InvalidOperationException: CRM Parameter Filter - Invalid parameter 'mycustomparam=mycustomvalue' in Request.QueryString on page /Contoso/activities/fax/edit.aspx
The raw request was 'GET /Contoso/activities/fax/edit.aspx?id=&mycustomparam=mycustomvalue' called from .]
at Microsoft.Crm.Application.ParameterFilter.ValidateParameter(Page page, ArrayList parameterCollection, String key, String value, String collectionName, EntityType pageEntityType)
at Microsoft.Crm.Application.ParameterFilter.ValidateParameters(Page page, EntityType pageEntityType, Boolean alwaysEnableParameterChecking)
at Microsoft.Crm.Application.ParameterFilter.ValidateParameters(Page page, EntityType pageEntityType)
at Microsoft.Crm.Application.Controls.AppPage.ValidatePageParameters()
at Microsoft.Crm.Application.Controls.AppPage.OnInit(EventArgs e)
at System.Web.UI.Control.InitRecursive(Control namingContainer)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

The issue here is, by default CRM does a filtering on the querystring passed to each form. And when it found an unknown querystring, it will throw this exception.
There is a workaround which involves modifying the registry. Ensure that you do a necessary backup before making these changes.

Open up regedit and browse to HKEY_Local_Machine\Software\Microsoft\MSCRM.
Add new DWORD called DisableParameterFilter with value 1.

Now, you can pass additional querystrings with no issue. :-)

2Dec/094

Elegant way to interact with CRM DynamicEntity

If you are using the CRM SDK assembly for your custom solutions, chances are you will be dealing with DynamicEntity. DynamicEntity is very useful when you interact with custom entity and custom attributes.

For example, to retrieve a custom attribute called “new_username” from Contact DynamicEntity, normally you will write something like this. Essentially, to get the base type value of a CRM Property, you will need to convert it to the right type (eg: StringProperty, etc) and call the Value property.

// Retrieve the contact.
DynamicEntity contact = ...;
 
// Ensure the new_username property exist before accessing it.
if (contact.Properties.Contains("new_username"))
{
   // Convert the Property into StringProperty so we can get the value.
   StringProperty usernameProp = (StringProperty) contact.Properties["new_username"];
 
   // Finally we get the value
   string usernameValue = usernameProp.Value;
}

I found it tedious and hard to read / maintain the code if we repeat the same code for, say 50+ attributes. What I really want is to be able to retrieve the base type value using a single line of code (and move this ‘tedious’ code behind the scene).

To do this, I make use of the Extension method feature from .NET 3.5. So now, you can do something like this

// Retrieve the contact.
DynamicEntity contact = ...;
 
// Retrieve the new_username value
string usernameValue = contact.GetPropertyValue<string>("new_username");
 
// Retrieve the name value of parentcustomerid
string parentCustName = contact.GetPropertyValue<string>("parentcustomerid");
 
// Retrieve the id value of parentcustomerid
Guid parentCustId = contact.GetPropertyValue<Guid>("parentcustomerid");

This way, you can retrieve the actual value with just ONE LINE of code. How good is that? :) Notice the call to GetPropertyValue method there? It’s actually the call to the extension method. Extension method lets you to ‘attach’ a behavior (method) to a class without having to inherit / subclass it. This comes in very handy for extending ‘sealed’ classes like String, etc.

To create your own extension methods, firstly you need to create a static class and define your extension methods as static. Then, the special part of the extension method is the first parameter of the method represents the Type that you want to hook in to. So this is the sample for the above GetPropertyValue extension method.

public static class Utils
{
    /// <summary>
    /// Gets the property value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="entity">The entity.</param>
    /// <param name="propertyName">Name of the property.</param>
    /// <returns></returns>
    public static T GetPropertyValue<T>(this DynamicEntity entity, string propertyName)
    {
        // Retrieve the matching property.
        object theProperty = entity.Properties.FirstOrDefault(i => i.Name.EqualsIgnoreCase(propertyName));
 
        // If property not found, return the default value.
        if (theProperty == null) return default(T);
 
        object value = null;
        string strPropertyType = theProperty.GetType().Name;
 
        switch (strPropertyType)
        {
            case "KeyProperty":
                value = ((KeyProperty)theProperty).Value.Value;
                break;
 
            case "StringProperty":
                value = ((StringProperty)theProperty).Value;
                break;
 
            case "PicklistProperty":
                if (typeof(T).Equals(typeof(string)))
                    value = ((PicklistProperty)theProperty).Value.name;
                else if (typeof(T).Equals(typeof(int)))
                    value = ((PicklistProperty)theProperty).Value.Value;
 
                break;
 
            case "CrmBooleanProperty":
                value = ((CrmBooleanProperty)theProperty).Value.Value;
                break;
 
            case "CrmDateTimeProperty":
                value = ((CrmDateTimeProperty)theProperty).Value.UserTime;
                break;
 
            case "CrmDecimalProperty":
                value = ((CrmDecimalProperty)theProperty).Value.Value;
                break;
 
            case "CrmFloatProperty":
                value = ((CrmFloatProperty)theProperty).Value.Value;
                break;
 
            case "CrmMoneyProperty":
                value = ((CrmMoneyProperty)theProperty).Value.Value;
                break;
 
            case "CrmNumberProperty":
                value = ((CrmNumberProperty)theProperty).Value.Value;
                break;
 
            case "LookupProperty":
                if (typeof(T).Equals(typeof(string)))
                    value = ((LookupProperty)theProperty).Value.name;
                else if (typeof(T).Equals(typeof(Guid)))
                    value = ((LookupProperty)theProperty).Value.Value;
 
                break;
 
            case "CustomerProperty":
                if (typeof(T).Equals(typeof(string)))
                    value = ((CustomerProperty)theProperty).Value.name;
                else if (typeof(T).Equals(typeof(Guid)))
                    value = ((CustomerProperty)theProperty).Value.Value;
 
                break;
 
            case "StatusProperty":
                if (typeof(T).Equals(typeof(string)))
                    value = ((StatusProperty)theProperty).Value.name;
                else if (typeof(T).Equals(typeof(Guid)))
                    value = ((StatusProperty)theProperty).Value.Value;
 
                break;
 
            case "StateProperty":
                value = ((StateProperty)theProperty).Value;
                break;
 
            case "EntityNameReferenceProperty":
                value = ((EntityNameReferenceProperty)theProperty).Value.Value;
                break;
        }
 
        try
        {
            if (value != null)
            {
                return (T)value;
            }
        }
        catch
        { }
 
        return default(T);
    }
 
    /// <summary>
    /// Equalses the ignore case.
    /// </summary>
    /// <param name="firstString">The first string.</param>
    /// <param name="secondString">The second string.</param>
    /// <returns></returns>
    public static bool EqualsIgnoreCase(this string firstString, string secondString)
    {
        if (string.IsNullOrEmpty(firstString) && string.IsNullOrEmpty(secondString)) return true;
        if (string.IsNullOrEmpty(firstString) || string.IsNullOrEmpty(secondString)) return false;
 
        return firstString.Equals(secondString, StringComparison.InvariantCultureIgnoreCase);
    }
}
29Oct/090

New xRM VPC released

Finally I've gotten around to do my first post for this blog. :)
The reason I setup this blog is to share my journey in Silverlight and Microsoft Dynamics CRM.

I am hoping to post new tips or tricks once a week or so.
So here is the first post. :)

Julie Yack posted about the new xRM VPC that was released few days ago...
What I found really cool from this XRM VPC is Visual Studio Team Suite SP1 and Silverlight 3 project is already pre-installed, unlike the April 2009 version.
That way, I don't have to waste hours of my time installing these stuff.

On top of that, apparently it starts up a little bit quicker than the April 2009 version, which is a BIG relief for me.
I think it also comes with few built-in accelerators as well. I haven't explored all of them yet, but there is an Asset Management, Event Management, etc.

Will post more details as soon as I get the chance to explore it.

In order for you to download this VPC, you will need access to the PartnerSource website. Normally you'll get this by default if you are a Dynamics Partner.

XRM VPC Part 01.exe
XRM VPC Part 02.rar
XRM VPC Part 03.rar
XRM VPC Part 04.rar
XRM VPC Part 05.rar

It also comes with the Demonstration Scripts which can be downloaded separately.
Employee Management Script
Facility Management Script
Vendor Management Script
xRM Scenario Flow Document

Happy downloading and GO xRM!

   
Get Adobe Flash playerPlugin by wpburn.com wordpress themes