There are a few blog posts out there that cover this topic, but the ones I’ve found don’t take you through it step by step. I will, however, make assumptions like you know how to create an entity, add web resources to a form, etc. Here goes…
The overall solution is going to consist of:
- Create/Update plugins that will call the Bing Maps REST Services to geocode an address
- A web resource for an interactive Bing Map using the Bing Maps AJAX Control, Version 7.0
- A web resource for a static image from the Bing Maps REST Services
If you are a “yea yea, blog blah blah, just give me the code” type then jump to the bottom of the post.
Let’s get started. First, you will need the Developer Toolkit for Microsoft Dynamics CRM 2011 and Microsoft Dynamics CRM Online and NuGet installed. Let’s create an entity called GeocodeMapSample. As a habit, I tend to uncheck all the entity defaults after the Options for Entity section of the form. You can always go back and turn additional features on as you need them after you create the entity.
Next create the following fields (all of type single line of text):
Yours should look like mine except you will have a different prefix than dkdt_.
Finally, put everything on the form:
Once you’ve done all this, go ahead and Publish your changes. Next, create a new Dynamics CRM 2011 Package project called GeocodeMapSamplePackage:
Fill out the Connect to Dynamics CRM Server dialog:
If you are using CRM Online, then your discovery service is dev.crm.dynamics.com if you log in with a Live ID or disco.crm.dynamics.com if your org was provisioned through Office 365. Make sure you select HTTPS as the protocol if necessary. Add a Dynamics CRM 2011 Plug-in Library called GeocodMapSamplePlugins to the Visual Studio solution:
Find the GeocodeMapSample entity in the Entities node of CRM Explorer, right-click it and select Create Plug-in:
Make your dialog look like mine:
I am picking the Pre-Operation for the Pipeline Stage because I want to be able to throw an exception back to the caller and roll the transaction back if geocoding fails because my business requirement is that addresses must be valid. Create another plug-in for the same entity. This time, we want to do a few things differently. First, set the value of Message to Update, but DO NOT click OK yet:
We only want this plug-in to fire when address related fields change. Click the Filtering Attributes ellipsis (…) to bring up the following dialog:
Now it’s time to generate some early-bound types. The CRM SDK covers early-bound vs. late-bound here. Most developers prefer the early bound approach unless they truly need a late-bound for writing very generic, reusable code. This is because you become more productive and less error prone due to intellisense and compile time checking. While the developer toolkit does have the ability to generate strongly typed classes:
…it does not give you any control over what classes get generated. It just brute force creates one for each entity you have read permissions to. Therefore, you end up generating a bunch of unnecessary code that bloats your codebase and makes your plugin WAY BIGGER than it needs to be. Instead, I prefer to use this approach to generate the classes:
Which one you choose, is up to you. Generate Wrapper is OK for now since you are just learning, but take my advice and learn the approach above for production code. Add a new class to the plug-in project called GeocodeMapSampleCommon.cs. Replace the entire contents of the class declaration with the following code:
This code does all the geocoding work. Your generated classes will have different prefix values than dkdt_, so fix the errors by replacing dkdt_ with your prefix. You will also have to replace the [INSERT_YOUR_BING_MAPS_KEY] string with yours from http://dkdt.me/KH4pNx. Because of the way I am sharing this class across multiple plugins we, need to make a slight tweak to the Plugin.cs class. Change protected class Plugin : IPlugin to protected internal class Plugin : IPlugin. Now is a good time to build. If you get build errors, well fix em . It’s a blog post after all. Assuming you got your build errors fixed, there are a couple more things to do. Open PreGeocodeMapSampleCreate.cs and replace the contents of the ExecutePreGeocodeMapSampleCreate method with:
Open PreGeocodeMapSampleCreate.cs and replace the contents of the ExecutePreGeocodeMapSampleCreate method with:
Probably a good time to build and troubleshoot again. If your build is successful, then sign the plug-in assembly:
Ok, now you should be able to right-click the package project and deploy:
This will register your plug-in and messages. Now go create a new GeocodeMapSample entity through the CRM UI. Save, but don’t save and close. You will see Latitude and Longitude have values after the save. So now we have to present this stuff on a map. Let’s do the easy one first: static map image. Go back to Visual Studio and add a new web resource to the package project:
Replace the contents of StaticMap.htm with the following:
Again, replace dkdt_ with your prefix. You will also have to replace the [INSERT_YOUR_BING_MAPS_KEY] string with yours from http://dkdt.me/KH4pNx. Drop the web resource in the GeocodeMapSample entity form. Publish it all and you should find a static map image on the form next time you load/refresh it. Go through the same process to build a web resource named InteractiveMap.htm. Replace the contents of the file with the following:
Again, replace dkdt_ with your prefix. You will also have to replace the [INSERT_YOUR_BING_MAPS_KEY] string with yours from http://dkdt.me/KH4pNx. Drop the web resource in the GeocodeMapSample entity form. Drop the web resource in the GeocodeMapSample entity form. Publish it all and you should find a static map image on the form next time you load/refresh it. Finally, Latitude & Longitude really are just there for code interaction. They don’t need to be visible on the form. Go ahead and hide them.
That’s it! If you made it through the whole post, you now know the fundamentals of using plug-ins, web resources, and the Bing Maps SDKs to add basic “geospatial” functionality to CRM 2011. Of course, you probably won’t want to scatter your Bing Maps key through out your code, but I wanted to keep the walkthrough as simple to follow as possible. You can grab the unmanaged solution and Visual Studio source code here: