Mar 072011
 

This page is nolonger current. Please view: http://mscrmblogger.com/2011/05/11/crm-2011-making-the-state-field-a-drop-down/

Do you want a drop down box for the state, but you don’t want to break core CRM functionality?

In CRM 4.0 I had posted an article about changing the CRM Address State to a drop down box. I have went back and updated the code a little (fixed a bug) and it will work with CRM 2011.

Ok, this script uses the same methods I used in CRM 4 to show the states for the United States and Canada (You can always modify it to have more options). This will help restrict what people put in the state field by providing them a drop down box. It will also allow them to view the old text box and enter any custom information just by clicking on ‘* ENTER A CUSTOM PROVINCE *’.

This script will work on the onload for a lead, contact, account, and sales-contact.

This script does use the _d html objects, which, to my knowledge is considered unsupported in CRM 2011. CRM 2011 does expose these data elements and control elements using Xrm.Page and this script doesn’t use them, and I may come back and update this script, but since it works in CRM 4 and in CRM 2011, I figured I’d repost it.

StateDropDown.js Jscript Code:

function ddlState ()
{

    // Get the state or province cell.
    var provinceid = 'stateorprovince';
    var statecell = document.getElementById(provinceid + '_d');

    if (!statecell)
    {
        provinceid = 'address1_stateorprovince';
        statecell = document.getElementById(provinceid + '_d');
    }

    var stateobject = document.getElementById(provinceid);
    stateobject.style.display = 'none';

    var statevalue = stateobject.value;

    var ddl = document.createElement('select');
    ddl.setAttribute('id','new_stateorprovince');
    ddl.setAttribute('class','ms-crm-SelectBox');
    ddl.setAttribute('req','2');
    ddl.setAttribute('height','4');
    ddl.setAttribute('style','IME-MODE: auto');

    // Build some lists.
    var CStateName = new Array();
    var CStateAbbr = new Array();
    var USStateName = new Array();
    var USStateAbbr = new Array();

    // If nothing is entered for state, show SELECT A STATE
    var found=false;
    if (statevalue.length<1)
    {
        stateoption=document.createElement('option');
        stateoption.setAttribute('value','');
        stateoption.innerHTML = ' ** SELECT A STATE ** ';
        ddl.appendChild(stateoption);
        found=true;
    }

    // Build Canada Array
    CStateName[0]  = "Alberta";                   CStateAbbr[0]  = "AB";
    CStateName[1]  = "British Columbia";          CStateAbbr[1]  = "BC";
    CStateName[2]  = "Manitoba";                  CStateAbbr[2]  = "MB";
    CStateName[3]  = "New Brunswick";             CStateAbbr[3]  = "NB";
    CStateName[4]  = "Newfoundland and Labrador"; CStateAbbr[4]  = "NL";
    CStateName[5]  = "Northwest Territories";     CStateAbbr[5]  = "NT";
    CStateName[6]  = "Nova Scotia";               CStateAbbr[6]  = "NS";
    CStateName[7]  = "Nunavut";                   CStateAbbr[7]  = "NU";
    CStateName[8]  = "Ontario";                   CStateAbbr[8]  = "ON";
    CStateName[9]  = "Prince Edward Island";      CStateAbbr[9]  = "PE";
    CStateName[10] = "Quebec";                    CStateAbbr[10] = "QC";
    CStateName[11] = "Saskatchewan";              CStateAbbr[11] = "SK";
    CStateName[12] = "Yukon";                     CStateAbbr[12] = "YT";

    // Build US Array
    USStateName[0]  = "Alabama";        USStateAbbr[0]  = "AL";
    USStateName[1]  = "Alaska";         USStateAbbr[1]  = "AK";
    USStateName[2]  = "Arizona";        USStateAbbr[2]  = "AZ";
    USStateName[3]  = "Arkansas";       USStateAbbr[3]  = "AR";
    USStateName[4]  = "California";     USStateAbbr[4]  = "CA";
    USStateName[5]  = "Colorado";       USStateAbbr[5]  = "CO";
    USStateName[6]  = "Connecticut";    USStateAbbr[6]  = "CT";
    USStateName[7]  = "District of Columbia"; USStateAbbr[7]  = "DC";
    USStateName[8]  = "Delaware";       USStateAbbr[8]  = "DE";
    USStateName[9]  = "Florida";        USStateAbbr[9]  = "FL";
    USStateName[10]  = "Georgia";       USStateAbbr[10]  = "GA";
    USStateName[11] = "Hawaii";         USStateAbbr[11] = "HI";
    USStateName[12] = "Idaho";          USStateAbbr[12] = "ID";
    USStateName[13] = "Illinois";       USStateAbbr[13] = "IL";
    USStateName[14] = "Indiana";        USStateAbbr[14] = "IN";
    USStateName[15] = "Iowa";           USStateAbbr[15] = "IA";
    USStateName[16] = "Kansas";         USStateAbbr[16] = "KS";
    USStateName[17] = "Kentucky";       USStateAbbr[17] = "KY";
    USStateName[18] = "Louisiana";      USStateAbbr[18] = "LA";
    USStateName[19] = "Maine";          USStateAbbr[19] = "ME";
    USStateName[20] = "Maryland";       USStateAbbr[20] = "MD";
    USStateName[21] = "Massachusetts";  USStateAbbr[21] = "MA";
    USStateName[22] = "Michigan";       USStateAbbr[22] = "MI";
    USStateName[23] = "Minnesota";      USStateAbbr[23] = "MN";
    USStateName[24] = "Mississippi";    USStateAbbr[24] = "MS";
    USStateName[25] = "Missouri";       USStateAbbr[25] = "MO";
    USStateName[26] = "Montana";        USStateAbbr[26] = "MT";
    USStateName[27] = "Nebraska";       USStateAbbr[27] = "NE";
    USStateName[28] = "Nevada";         USStateAbbr[28] = "NV";
    USStateName[29] = "New Hampshire";  USStateAbbr[29] = "NH";
    USStateName[30] = "New Jersey";     USStateAbbr[30] = "NJ";
    USStateName[31] = "New Mexico";     USStateAbbr[31] = "NM";
    USStateName[32] = "New York";       USStateAbbr[32] = "NY";
    USStateName[33] = "North Carolina"; USStateAbbr[33] = "NC";
    USStateName[34] = "North Dakota";   USStateAbbr[34] = "ND";
    USStateName[35] = "Ohio";           USStateAbbr[35] = "OH";
    USStateName[36] = "Oklahoma";       USStateAbbr[36] = "OK";
    USStateName[37] = "Oregon";         USStateAbbr[37] = "OR";
    USStateName[38] = "Pennsylvania";   USStateAbbr[38] = "PA";
    USStateName[39] = "Rhode Island";   USStateAbbr[39] = "RI";
    USStateName[40] = "South Carolina"; USStateAbbr[40] = "SC";
    USStateName[41] = "South Dakota";   USStateAbbr[41] = "SD";
    USStateName[42] = "Tennessee";      USStateAbbr[42] = "TN";
    USStateName[43] = "Texas";          USStateAbbr[43] = "TX";
    USStateName[44] = "Utah";           USStateAbbr[44] = "UT";
    USStateName[45] = "Vermont";        USStateAbbr[45] = "VT";
    USStateName[46] = "Virginia";       USStateAbbr[46] = "VA";
    USStateName[47] = "Washington";     USStateAbbr[47] = "WA";
    USStateName[48] = "West Virginia";  USStateAbbr[48] = "WV";
    USStateName[49] = "Wisconsin";      USStateAbbr[49] = "WI";
    USStateName[50] = "Wyoming";        USStateAbbr[50] = "WY";

    // Build the drop down
    var stateoption;
    stateoption=document.createElement('option');
    stateoption.setAttribute('value','');
    stateoption.innerHTML = '---United States--------';
    ddl.appendChild(stateoption);

    var i=0;
    for(i=0;i<USStateName.length;i++)
    {
        stateoption=document.createElement('option');
        stateoption.setAttribute('value',USStateAbbr[i]);
        if (USStateAbbr[i]==statevalue)
        {
            stateoption.setAttribute('selected','selected');
            found = true;
        }
        stateoption.innerHTML = USStateAbbr[i] +
        ' (' + USStateName[i] + ')';
        ddl.appendChild(stateoption);
    }

    stateoption=document.createElement('option');
    stateoption.setAttribute('value','');
    stateoption.innerHTML = '---Canada---------------';
    ddl.appendChild(stateoption);

    var i=0;
    for(i=0;i<CStateName.length;i++)
    {
        stateoption=document.createElement('option');
        stateoption.setAttribute('value',CStateAbbr[i]);
        if (CStateAbbr[i]==statevalue)
        {
            stateoption.setAttribute('selected','selected');
            found = true;
        }
        stateoption.innerHTML = CStateAbbr[i] + ' (' + CStateName[i] + ')';
        ddl.appendChild(stateoption);
    }

    stateoption=document.createElement('option');
    stateoption.setAttribute('value','customselection');
    stateoption.innerHTML = ' ** ENTER A CUSTOM PROVINCE ** ';

    if (found==false)
    {
        stateoption=document.createElement('option');
        stateoption.setAttribute('value',statevalue);
        stateoption.setAttribute('selected','selected');
        stateoption.innerHTML = statevalue + ' (Custom)';
        ddl.appendChild(stateoption);
    }

    ddl.appendChild(stateoption);

    // Add the drop down and size accordingly.
    statecell.appendChild(ddl);
    ddl.onchange = textState;
    ddl.style.width = '100%';
}

function textState()
{
    // Find drop down and real textbox
    provinceid = 'stateorprovince';

    var stateobject = document.getElementById(provinceid);
    if (!stateobject)
    {
        provinceid = 'address1_stateorprovince';
        stateobject = document.getElementById(provinceid);
    }
    var ddl = document.getElementById('new_stateorprovince');

    // if dropdown value is customselection, show real textbox
    if (ddl.value=='customselection')
    {
        // Get the state or province cell.
        var statecell = document.getElementById(provinceid + '_d');
        statecell.removeChild(ddl);
        stateobject.style.display = 'inline';
    } else {
        // if dropdown is not customselection,
        // put value from ddl into real textbox.
        stateobject.value = ddl.value;
    }

}

Then in the form’s onload event, just add the method ddlState with no parameters.

May 202010
 

Bing Maps are great. You can geocode and correct your addresses. Depending on your level of queries and types of usage you may need to purchase credits to query Bing Maps, but I thought it was pretty straight forward. If you need to get a Bing Maps account, go here.

The thing that makes this great is it is workflow. It is not tied down to an entity. You can use it on your custom entities, you can geocode your addresses, and correct them. You can do address verification and geocoding. You can control what you do using workflow.

Ok, while this isn’t anything complicated, I thought it was a good example of a custom workflow that used an external webservice. Please don’t forget to create a signed key for your project.

Workflow Class:

using System;
using System.ServiceModel;
using System.Text;
using System.Workflow.Activities;
using System.Workflow.ComponentModel;
using BingWorkflow.BingMapsGeo;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Workflow;
using Microsoft.Win32;

namespace BingWorkflow
{
    [CrmWorkflowActivity("Bing Maps", "Geocode")]
    public class VerifyAddressUsingBingMapsActivity :
        SequenceActivity
    {
        // Activity code goes here. 

        public static DependencyProperty AddressCityProperty = DependencyProperty.Register(
            "AddressCity", typeof (string), typeof (VerifyAddressUsingBingMapsActivity));

        public static DependencyProperty AddressCountryProperty = DependencyProperty.Register(
            "AddressCountry", typeof (string), typeof (VerifyAddressUsingBingMapsActivity));

        public static DependencyProperty AddressLine1Property = DependencyProperty.Register(
            "AddressLine1", typeof (string), typeof (VerifyAddressUsingBingMapsActivity));

        public static DependencyProperty AddressPostalCodeProperty = DependencyProperty.Register(
            "AddressPostalCode", typeof (string), typeof (VerifyAddressUsingBingMapsActivity));

        public static DependencyProperty AddressStateProperty = DependencyProperty.Register(
            "AddressState", typeof (string), typeof (VerifyAddressUsingBingMapsActivity));

        public static DependencyProperty BingKeyProperty = DependencyProperty.Register(
            "BingKey", typeof (string), typeof (VerifyAddressUsingBingMapsActivity));

        public static DependencyProperty OutputCityProperty = DependencyProperty.Register(
            "OutputCity", typeof (string), typeof (VerifyAddressUsingBingMapsActivity));

        public static DependencyProperty OutputCountryProperty = DependencyProperty.Register(
            "OutputCountry", typeof (string), typeof (VerifyAddressUsingBingMapsActivity));

        public static DependencyProperty OutputLatitudeProperty = DependencyProperty.Register(
            "OutputLatitude", typeof (CrmFloat), typeof (VerifyAddressUsingBingMapsActivity));

        public static DependencyProperty OutputLine1Property = DependencyProperty.Register(
            "OutputLine1", typeof (string), typeof (VerifyAddressUsingBingMapsActivity));

        public static DependencyProperty OutputLongitudeProperty = DependencyProperty.Register(
            "OutputLongitude", typeof (CrmFloat), typeof (VerifyAddressUsingBingMapsActivity));

        public static DependencyProperty OutputMultipleFoundProperty = DependencyProperty.Register(
            "OutputMultipleFound", typeof (CrmBoolean), typeof (VerifyAddressUsingBingMapsActivity));

        public static DependencyProperty OutputPostalCodeProperty = DependencyProperty.Register(
            "OutputPostalCode", typeof (string), typeof (VerifyAddressUsingBingMapsActivity));

        public static DependencyProperty OutputStateProperty = DependencyProperty.Register(
            "OutputState", typeof (string), typeof (VerifyAddressUsingBingMapsActivity));

        [CrmInput("Address City")]
        public string AddressCity
        {
            get { return (string)GetValue(AddressCityProperty); }
            set { SetValue(AddressCityProperty, value); }
        }

        [CrmInput("Address Country")]
        public string AddressCountry
        {
            get { return (string)GetValue(AddressCountryProperty); }
            set { SetValue(AddressCountryProperty, value); }
        }

        [CrmInput("Address Line 1")]
        public string AddressLine1
        {
            get { return (string)GetValue(AddressLine1Property); }
            set { SetValue(AddressLine1Property, value); }
        }

        [CrmInput("Address Postal Code")]
        public string AddressPostalCode
        {
            get { return (string)GetValue(AddressPostalCodeProperty); }
            set { SetValue(AddressPostalCodeProperty, value); }
        }

        [CrmInput("Address State Or Province")]
        public string AddressState
        {
            get { return (string)GetValue(AddressStateProperty); }
            set { SetValue(AddressStateProperty, value); }
        }

        [CrmInput("Bing API Key")]
        public string BingKey
        {
            get { return (string)GetValue(BingKeyProperty); }
            set { SetValue(BingKeyProperty, value); }
        }

        [CrmOutput("City")]
        public string OutputCity
        {
            get { return (string)GetValue(OutputCityProperty); }
            set { SetValue(OutputCityProperty, value); }
        }

        [CrmOutput("Country Or Region")]
        public string OutputCountry
        {
            get { return (string)GetValue(OutputCountryProperty); }
            set { SetValue(OutputCountryProperty, value); }
        }

        [CrmOutput("Latitude")]
        public CrmFloat OutputLatitude
        {
            get { return (CrmFloat)GetValue(OutputLatitudeProperty); }
            set { SetValue(OutputLatitudeProperty, value); }
        }

        [CrmOutput("Line 1")]
        public string OutputLine1
        {
            get { return (string)GetValue(OutputLine1Property); }
            set { SetValue(OutputLine1Property, value); }
        }

        [CrmOutput("Longitude")]
        public CrmFloat OutputLongitude
        {
            get { return (CrmFloat)GetValue(OutputLongitudeProperty); }
            set { SetValue(OutputLongitudeProperty, value); }
        }

        [CrmOutput("Multiple Address Found")]
        public CrmBoolean OutputMultipleFound
        {
            get { return (CrmBoolean)GetValue(OutputMultipleFoundProperty); }
            set { SetValue(OutputMultipleFoundProperty, value); }
        }

        [CrmOutput("Postal Code")]
        public string OutputPostalCode
        {
            get { return (string)GetValue(OutputPostalCodeProperty); }
            set { SetValue(OutputPostalCodeProperty, value); }
        }

        [CrmOutput("State Or Province")]
        public string OutputState
        {
            get { return (string)GetValue(OutputStateProperty); }
            set { SetValue(OutputStateProperty, value); }
        }

        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            // Reset Outputs
            OutputLatitude = new CrmFloat();
            OutputLongitude = new CrmFloat();
            OutputLine1 = String.Empty;
            OutputCity = String.Empty;
            OutputState = String.Empty;
            OutputPostalCode = String.Empty;
            OutputMultipleFound = new CrmBoolean {Value = false};

            var key = BingKey;
            if (String.IsNullOrEmpty(key) || key.ToLower() == "registry")
            {
                key = GetAPIKeyFromRegistry();
            }

            // Create Bing Maps Request
            var bingRequest = new GeocodeRequest
                              {
                                  Credentials = new Credentials {ApplicationId = key},
                                  Query = AddressLine1 + ", " +
                                          AddressCity + ", " +
                                          AddressState + ", " +
                                          AddressPostalCode + ", " +
                                          AddressCountry
                              };

            // Filter for High Confidence
            var filters = new ConfidenceFilter[1];
            filters[0] = new ConfidenceFilter {MinimumConfidence = Confidence.High};
            bingRequest.Options = new GeocodeOptions {Filters = filters};

            // Create Client
            GeocodeServiceClient bingClient = null;
            try
            {
                var geoBinding = new BasicHttpBinding(BasicHttpSecurityMode.None)
                                 {
                                     Name = "BasicHttpBinding_IGeocodeService",
                                     CloseTimeout = new TimeSpan(0, 1, 0),
                                     OpenTimeout = new TimeSpan(0, 1, 0),
                                     ReceiveTimeout = new TimeSpan(0, 10, 0),
                                     SendTimeout = new TimeSpan(0, 1, 0),
                                     AllowCookies = false,
                                     BypassProxyOnLocal = false,
                                     HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
                                     MaxBufferSize = 65536,
                                     MaxBufferPoolSize = 524288,
                                     MaxReceivedMessageSize = 65536,
                                     MessageEncoding = WSMessageEncoding.Text,
                                     TextEncoding = Encoding.UTF8,
                                     TransferMode = TransferMode.Buffered,
                                     UseDefaultWebProxy = true
                                 };

                var geoEA =
                    new EndpointAddress("http://dev.virtualearth.net/webservices/v1/geocodeservice/GeocodeService.svc");

                bingClient = new GeocodeServiceClient(geoBinding, geoEA);

                var bingResponse = bingClient.Geocode(bingRequest);

                if (bingResponse.Results != null && bingResponse.Results.Length > 0)
                {
                    if (bingResponse.Results.Length > 1)
                    {
                        OutputMultipleFound.Value = true;
                    }

                    var bingResult = bingResponse.Results[0];

                    if (bingResult.Locations != null && bingResult.Locations.Length > 0)
                    {
                        var bingLocation = bingResult.Locations[0];
                        OutputLatitude.Value = bingLocation.Latitude;
                        OutputLongitude.Value = bingLocation.Longitude;
                    }

                    var bingAddress = bingResult.Address;

                    OutputLine1 = bingAddress.AddressLine;
                    OutputPostalCode = bingAddress.PostalCode;
                    OutputCountry = bingAddress.CountryRegion;

                    OutputCity = String.IsNullOrEmpty(bingAddress.PostalTown)
                                     ? bingAddress.Locality
                                     : bingAddress.PostalTown;
                    OutputState = String.IsNullOrEmpty(bingAddress.AdminDistrict)
                                      ? bingAddress.District
                                      : bingAddress.AdminDistrict;
                }
            }
            catch (Exception ex)
            {
                throw new WorkflowTerminatedException(
                    "There was an error openning the connection to Bing Maps.", ex);
            }
            finally
            {
                // Close the client
                if (bingClient != null)
                {
                    bingClient.Close();
                }
            }


            return base.Execute(executionContext);
        }

        private static string GetAPIKeyFromRegistry()
        {
            // Opening the registry key
            var key = Registry.LocalMachine;
            if (key != null)
            {
                key = key.OpenSubKey("Software\\Microsoft Geocoder");
            }

            return key != null ? key.GetValue("APIKey").ToString() : null;
        }
    }
}