Monday, May 4, 2009

Freeze header and the first column of the GridView control

There have been often times when the customers (familiar with Excel Freeze Options) have asked for the same functionality on ASP .NET forms.

There is no direct property that would allow users to either fix the header or the column. The html concept of was hard to find with GridView control.

We found a solution that used stylesheet to freeze the header and the columns. This code really helped us achieve our goals.

Here it is...
Place your gridview under DIV. This div should contains style value as

style="height:500px; width:100%; overflow:auto;"

overflow:auto: to display the scroll bars when grid contents exceeds the grid height


Instead of hard coding div height if you need to apply the height as the page height you can refer to the following article, http://inogic.blogspot.com/2009/02/automatically-resize-iframe-to-adjust.html

In gridview header provide class name from stylesheet i.e. Freezing
< cssclass="FreezeHeader" id="”">
The above line will freeze the header row

To freeze the first column use below code for first column at run time
gvFix.HeaderRow.Cells[0].CssClass = "locked";

foreach (GridViewRow row in gvFix.Rows)
{ //stylesheet to firstcol
row.Cells[0].CssClass = "locked";
}
Here are the Stylesheet classes that are being referred above


/* Locks the left column */
td.locked, th.locked {
position:relative;
cursor: default;
left: expression(document.getElementById("div_gridholder").scrollLeft); /* div_gridholder : name of the div which holds gridview*/
}


/* Locks the header */
.FreezeHeader {
position:relative ;
top:expression(this.offsetParent.scrollTop - 2);
z-index: 20;
}


Hope this helps others give the option of Freezing rows and columns in grid controls.

Thursday, April 30, 2009

CS0433 Error in Dynamics CRM and its resolution

To incorporate a custom .NET application in Dynamics CRM, you are required to copy the custom forms to ISV folder and the compiled library to the bin folder. Sometimes it may so happen that after you have copied the dll to the bin folder and refresh CRM, it would just not load. One small custom application has brought down your CRM.

If you enable DevErrors in the web.config file, you would see a screen similar to this when you open CRM.



Cause: When developing the custom application, the project had a Global.asax added to it. When you compiled the project into a DLL the global.asax class was included in the compiled library. CRM 4.0 only requires a single Global.asax file and it has already included that in its own libraries.

Resolution: You need to remove the Global.asax from your project and compile it again. Put the revised dll in the bin folder and your CRM and the custom application is up and running.

Monday, April 27, 2009

Maps Integration for Dynamics CRM 4

There has often been a need especially when you have Sales rep requiring to visit the clients on-site to be able to get the directions to the customer location. Google Maps, Live Maps, Mappoint are some of the services that you can use to incorporate this feature in CRM. While Mappoint is a paid service, the other two are free services and can be used to plot the customer address on the map.

One of the important pre-requisites while plotting a customer address would be to geo-code (get the latitude and longitude) the addresses. It is using these geo-coding that the addresses are plotted on Map. Since a customer’s address would not change often, it is a good idea to write a workflow that will geo-code the customer addresses each time a new customer is created or its address updated.

The following webservice from Google can be used for geo-coding addresses.
http://maps.google.com/maps/geo?q=address&Key=abcd&output=xml&sensor=false

Once the addresses are geo-coded, we can add a tab on CRM account/contact form and display the customer address in a map. The map will place a pushpin at the customer location.

This can further be extended to get the Route and Directions to the customer location from a base location.

Using Live Maps it can be done using the following code

locations = new Array(‘addr1’,’addr2’);

//Make an object of RouteOptions
var options = new VERouteOptions;

// Draw the route
options.DrawRoute = true;

// So the map doesn't change:
options.SetBestMapView = true;

// Call this function when map route is determined:
//options.RouteCallback = ShowTurns;

// Show as miles
options.DistanceUnit = VERouteDistanceUnit.Mile;

// Show the disambiguation dialog
options.ShowDisambiguation = true;

//Show the directions on the map
map.GetDirections(locations, options);";

This will show a map with the route marked starting from the start point to the end location.





Another use of integrating maps would be to search of location within a given distance range. So you are visiting a customer in “Redmond” and would want to find out the other customers that are in and around this location so that you could schedule an appointment with them. Or it could be used for schedule service requests for a sales rep. If a salesrep was already scheduled for a call in Redmond area and there was another ticket raised for that area it could be handed to the same sales rep for servicing.

This could be done by finding the distance between the base location and other customer addresses and plotting the customers that fall within the requested distance on the map. One pushpin will be placed on the map for each customer address that is being shown in the map.



There is so much you can do with Maps :) And it is pretty easy to as its shown above and requires a bit SDK skills and programming knowledge. The web is full of details as to how to use various maps functionality to achieve the same. We at Inogic were debating whether to come up with an add-on for Live Maps integration at all or just leave it for you people to figure out on your after giving you the above methodology.

Friday, April 24, 2009

Use of Shared Variables in Plugins

Apart from the various improvisations of Plugin over Callouts, is the ability to share data between events of an entity. This option was not available when working with Callouts in CRM 3.0. The workaround we used then was to create an attribute and store the information in an attribute in the Pre Create event. In the Post Create use the value of the attribute.

Plugins in CRM 4.0 have introduced the concept of Shared Variables. So now instead of storing the values in a custom attribute you can store the value in a context variable. This is then available in the Post event for use. It is possible to read/write data into SharedVariables of context.

The following code example shows how to use SharedVariables to pass data from a pre-event registered plug-in to a post-event registered plug-in.

Example:
public class PreTest : IPlugin
{
public void Execute(IPluginExecutionContext context)
{
// Create or retrieve some data that will be needed by the post event handler. You could run a query, create an entity, or perform a calculation.
//In this sample, the data to be passed to the post plug-in is represented by a GUID.
Guid contact = new Guid("{74882D5C-381A-4863-A5B9-B8604615C2D0}");
// Pass the data to the post event handler in an execution context shared variable named PrimaryContact.
context.SharedVariables["PrimaryContact"] = contact.ToString();
}
}

public class PostTest : IPlugin
{
public void Execute(IPluginExecutionContext context)
{
// Obtain the contact from the execution context shared variables.
if (context.SharedVariables.Contains("PrimaryContact"))
{
Guid contact = new Guid((string)context.SharedVariables["PrimaryContact"]);
// perform action on contact.
}
}
}

Thursday, April 16, 2009

Intuit QuickBooks integration link with Dynamics CRM 4.0 released

QuickBooks is one of the most popular accounting packages for the SME segment. There has always been a need to integrate CRM with accounting system to avoid duplicity as well as to improve productivity and efficiency by providing the sales people using CRM a view of the financial details of the customer so as to enable them to handle the sales/marketing process better.

To satisfy these needs, Inogic lab have come up with a link which has been deployed at a number of customer sites and we have now packaged it and would like to announce the release of version 3.0 of the integration having the following features:

Customer Synchronization: Accounts of Dynamics CRM and Customers of QuickBooks are completely synchronized. You can save an Account in Dynamics CRM and promote it to QuickBooks. Vice versa, you can synchronize customers from QuickBooks applications to view and edit it in Dynamics CRM. Any edit and update on the Dynamics CRM side reflects in QuickBooks in the real time.

Invoices and Orders Viewing in Dynamics CRM: Complete view of a particular customers Invoice and Orders history from QuickBooks in Dynamics CRM within the Account form.

Promote Orders from Dynamics CRM: This feature is extremely useful for Sales people to make Orders against opportunities in CRM and then promote it to Quick Books for further processing.

Quick Customer Account Information: Various financial important data like Credit Limit, Aging, and Terms etc from the Quick Books is available against the Dynamics CRM customer for viewing by Sales People.

Versions supported:
QuickBooks:
Enterprise 8.0 US/UK Edition

Microsoft Dynamics CRM: 4.0 On-premise (IFD not supported), Partner Hosted and CRM Live.

The challenge for integration between QB and Dynamics was the inherent difference in the SDK and databases and having a detailed knowledge of the accounting system as well as CRM system. It is not easy to code and develop an integration which takes care of deduplication, checks out the security rights and also takes into account that accounting compliance are maintained. You also need to have a knowledge of QB SDK as well as be confident about the financial aspects of the system as Order Entry process needs to be duplicated in the integration. If you require more information with regards to QB and would like to pick our brains in terms of integration with any other accounting package which you are attempting, please be free to email us and we will be more than willing to discuss our experience with the same.