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

24Feb/101

March Melbourne xRM User Group Meeting

For the next xRM User Group meeting, I will be presenting on a very interesting topic

“Investing your existing .NET skill in Microsoft Dynamics CRM”

Looking at the Australian market situation at the moment, the Dynamics CRM market has grown exponentially from last year alone. This is noted by a significant number of moves by the medium to large enterprises to Dynamics CRM. This spike, however, is followed by shortage of skill around Dynamics CRM product.

In this upcoming session, I will demonstrate on how you can leverage your existing .NET skill to build an awesome solution for Dynamics CRM. I will cover all the CRM Customization and Integration points such as Plugins, Workflows, Javascript, and Custom Pages. All written purely in .NET (C#).

Here is the details on the venue & RSVP link. Looking forward to see you all there.
If you have any issues finding the venue on the day, feel free to give me a call on 0403647619.

Venue: Microsoft Theatre – Level 5, 4 Freshwater Place, Southbank, VIC 3006
Date: 3 March 2010 (every first Wednesday of the month)
Starts 5.30pm for Pizza and Drinks before diving into the session
RSVP at http://www.eventbrite.com/event/580067999

Filed under: Microsoft CRM 1 Comment
20Jan/100

MSCRM Development Tips &Trick #1 – Minify your Javascript

I am starting a series of blog post about tips and tricks on developing solution using Microsoft CRM. The first tips I would like to share is about Javascript form customization.

In production environment, for the best result, ensure that you ‘minified’ your custom Javascript. It might not seem to have big impact on small set of Javascript, but as it grows over time, so does the benefit. So far, I found Google Closure compiler is the best one out there. You can specify different level of optimization starting from removing whitespace only, simple optimization which involves renaming methods and variables, to the ‘Advanced’ optimization which does the simple optimization plus pruning of unused methods. You might want to be extra careful when doing the ‘Advanced’ optimization, especially if you have dependencies with 3rd party JS libraries like JQuery as it doesn’t pick up external JS resources (yet). Most of the time, the Simple optimization will suffice.

As a comparison, I have a 100kb Javascript in my account form. After applying the ‘Simple’ optimization using Google Closure tools, now the size of my JS become 35kb. Around 60-70% improvement. Might not sound a lot, but it’s a great investment.

If you decided to go down this path, I highly suggest that you keep a backup of the original un-minified Javascript in your Source Control (eg: SVN, TFS, etc). Essentially, every time you decided to make changes to the form Javascript, you will need to copy the original un-minified JS to the CRM form, make the changes, save it back to the Source Control, and minify it. Alternatively, if you don’t want to keep the original JS in Source Control, you can use free JS formatter / beautifier (eg: http://jsbeautifier.org/) to format your JS nice and clean. The downside of this approach is you might not get all of the original variable / method names.

Filed under: Microsoft CRM No Comments
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. :-)

10Dec/090

MSCRM SocketException error on Bulk Data Import

I came across this error message when I did bulk data import either using the Microsoft CRM built-in one or through CRM Web Services.

System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted 10.10.5.45:8083
 
   at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.InternalConnect(EndPoint remoteEP)
   at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Int32 timeout, Exception& exception)
 
   --- End of inner exception stack trace ---
 
   at System.Web.Services.Protocols.WebClientProtocol.GetWebResponse(WebRequest request)
   at System.Web.Services.Protocols.HttpWebClientProtocol.GetWebResponse(WebRequest request)
   at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
   at Microsoft.Crm.SdkTypeProxy.CrmService.Execute(Request Request)

Apparently, when you are doing bulk import, behind the scene there are a lot socket being consumed. The problem is these sockets are not released until the timeout elapsed (the default is around 4 minutes). So, once all the sockets are used and none of them timed out, this exception is thrown.

There is a registry workaround for this issue which should be applied on the CRM Server.

NOTE: Ensure that you backup your registry prior to modifying it.

1. Open up regedit and browse to HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

2. Create or modify the DWORD Value called MaxUserPort and set the decimal value to 65534

3. Create or modify the DWORD Value called TcpTimedWaitDelay and set the decimal value to 48

4. Create or modify the DWORD Value called TcpWindowSize and set the decimal value to 64240

5. Restart the CRM Server

Once the server come back up, you will see there is no more SocketException error. And magically, it runs lots quicker too!

Filed under: Microsoft CRM No Comments
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);
    }
}
22Nov/091

Dynamics CRM 5 Sneak Peek

Microsoft PDC conference was held on 17 Nov – 19 Nov last week at Los Angeles. A bunch of new technology was announced such as Silverlight 4 Beta, Microsoft Live Pivot. On top of that, there are heaps of sessions around VS 2010 Beta 2, C# 4.0, SharePoint 2010, and the long awaiting CRM 5.

This blog post will summarize some of the new features from CRM 5 which I gathered from the PDC videos and a number of twitter feeds (ceibner, davidyack, crmlarry). CRM 5 itself is planned to be released on second half of 2010.

Note: the features listed here might change for the final release of CRM 5.

NEW FEATURES: USER INTERFACE

- New Ribbon UI

This will replace the existing CRM Toolbar at the top of each page. I started to like this new Ribbon UI. It really provides a visible quick-way to perform an action.

CRM5_RibbonUI

- Single Page Forms

The forms in CRM 4 uses tabs to divide information in a form into multiple views. In CRM 5, all the tabs are displayed along the left hand side as a section.

As you can see in the screenshot below, the tabs in Account form are displayed under the Information link.

CRM5_SinglePageForm

- Data Filtering

In CRM 5, the end user can navigate to the "DataView" and perform their own filter criteria directly.

CRM5_DataFiltering

- Inline Visualization

CRM 5 supports simple numeric data visualization using in-line charts out of the box, without having to use SQL Reporting Services or third party charting solutions.

CRM5_InlineVisualization

- New Ownership Type

Team Owned entities are supported in CRM 5 and fully integrated into the Role-Based security model.

- Native SharePoint Integration

Integration with WSS (Windows SharePoint Services) for document management, including site and document library provisioning, document metadata, item security, and check-in / check-out capabilities.

- Unstructured Relationships

The next generation of "Set Regarding" and "Relationship Roles" functionality, allowing you to define ad-hoc relationships between two entities.

- Option Sets (Global Picklists)

This functionality allows the end user to define a number of picklists (enumeration) and be able to reuse it across multiple entities. One of the great example of this is the country list which you might use across Account, Contact, etc.

- Flexible Form Layout

In CRM 5, you can position sections side by side, as well as customize the labels position (top, left, or right of each field). On top of that, you can create "In-Line Sub-Grids" easily without having to use IFrame and JavaScript. Just in case you are wondering, yes the form editor in CRM 5 will support drag-and-drop fields.

CRM5_FlexibleForm

- Filtered Lookups

You can choose a pre-defined views or filter by related record on the same form.

CRM5_FilteredLookup

- Built-In Audit Capability

NEW FEATURES: Development

- Uses .NET 4.0 as the base framework

- Flexible Web Services

Supports WCF, REST, and AJAX Web Services.

The new WCF Web Service also provides a significant performance improvement over the classic ASMX Web Service.

By exposing these new interfaces, it lends itself to easier interoperability with other non .NET technologies such as PHP, Ruby, etc.

- Enhanced Query Support

LINQ will be the first class citizen in CRM 5. If you are developing a xRM solution in Silverlight, you could also use .NET Ria Services to interact with CRM 5.

- Custom Code Sandbox

There is a new server role for running custom plugin and workflow activities without requiring full trust. This allows ISVs to run custom code on CRM Online environment and achieve true parity between On-Premise, Partner-Hosted, and Microsoft-Hosted deployments.

- Plugin Transaction Support

Previously in CRM 4, you can only register plugin to run before or after the event takes place, which is troublesome when it comes to rolling back changes when failures occurs. Luckily, CRM 5 allows you to register your plugin as a part of the same transaction as the platform event.

- Automatic Plugin Profiling

CRM 5 tracks how a plugin executes, how much resources it consumes. If a particular plugin fails a number of times, it will automatically disable it to maintain system integrity.

- Better support for ALM (Application Lifecycle Management)

Andrew Bybee had a full session on this which you can download here. As ISVs, how many times we build xRM solutions which consist of multiple components with complex dependencies, and every clients want to get only parts of the solution or slightly different component to what we have out-of the box. This causes a lot of pain in CRM 4. The great thing is, Microsoft introduced a concept of Solution in CRM 5. This allows multiple ISVs to deploy their own solutions and customize the prefix to avoid namespace collision.

CRM5_ALM

Filed under: Microsoft CRM 5 1 Comment
12Nov/096

Building xRM Dashboard Part 1

I am doing a screencast on building a very cool xRM Dashboard using Silverlight 3 technology. This was the demo that I did on the last Melbourne xRM User Group meeting.
The first screencast is just about the demo of the Dashboard. There will be more screencasts covering the implementation part of it.

For those of you who missed the last meeting, the slides and the sample code can be downloaded here and here.

Hope you enjoy it. Feedback or comments are welcome. :)

29Oct/090

Melbourne xRM User Group Kick-off Meeting

After a month of planning (and lots of hard work too!), we finally managed to have the very first meeting for Melbourne xRM User Group on Wed, 4 November 2009.

The meetings will be held every first Wednesday of the month, starts at 5.30pm for FREE pizza and drinks.
Microsoft has been very generous in letting us to use their venue at Freshwater Place, Southbank.
Thank you to JayThom as well who is sponsoring this User Group.

For the first meeting, I will be presenting on "See the Light in xRM", which sort of aligns with the purpose of this blog.
The presentation will go through the cool stuff in Silverlight 3 and how use Silverlight to build you xRM solutions.
This session will be a mixed of demo and coding. :)

To help us estimating the pizzas, please RSVP at http://xrmug.eventbrite.com/
Thank you and looking forward seeing you there. :)

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