Archive

Archive for the ‘Tips and Tricks’ Category

Custom Charting Capabilities in Microsoft Dynamics CRM 2011

February 4, 2011 2 comments

Microsoft Dynamics CRM 2011 comes with in-built visual analytics. You can create charts to view aggregations of your CRM data over various dimensions, providing nice visual and interactive tools to analyze data. But, there is more to it.

It also provides you with some space alongside the records-grid. While this space is generally used for the built-in charts, it can potentially be used for well, anything. CRM 2011 also goes a long way in defining an extensibility story – a way to deploy your own custom pages on the server. Yes, you’ve got it right – I am referring to web resources. Would it not be great if you could get your web resource to show up alongside the grid? Well, that is precisely what we let you do.

Create your own custom chart

Let us start by creating a simple “Hello World” page, and making it show up alongside the Accounts grid.

1. Open your favorite text-editor, and type in the following HTML:

<html>

  <head>

    <title>Hello World Page</title>

  </head>

<body>

  <div style="height:49%" ></div>

  <div style="text-align:center">

  <b>A 'Hello World' web resource for the Accounts grid</b>

</div>

</body>

</html>

This is an elementary HTML page that shows a line of bold text centered horizontally as well as vertically.

2. Create an HTML Web Resource on CRM Server by uploading the above page. In case you are not familiar with web resources, you will need to do the following:

a. Navigate to Settings Customizations. Click on Customize the System to open up the Default Solution.

b. Click on New → Web Resource on the grid tool-bar to launch the Web Resource form.

c. Upload the file created in (1) above. Give the web resource a name, say new_helloWorld.

d. Click Save.

clip_image002

3. Now we will create a custom chart that uses this web resource. We can do so easily by using the Import Chart feature:

a. Navigate to Accounts grid and open the chart pane.

b. Click on Import Chart in the Charts tab of the ribbon.

clip_image004

Here’s the XML we want to import:

<visualization>

  <primaryentitytypecode>account</primaryentitytypecode>

  <name>Hello World</name>

  <webresourcename>new_helloWorld</webresourcename>

</visualization>

Note that the XML definition above contains a reference to the web resource created in (2).

Once the chart is successfully imported, we will see the following:

clip_image006

That was pretty easy, wasn’t it? But that was not a very useful chart though. Let us move on to something better.

Multiple charts sharing the same web resource

Consider a hypothetical problem. Let us say, I have accounts spread across different countries in the world and I would like to see their locations on a map beside the accounts grid. I would not want one map cluttered with all the accounts – rather I would want to focus on one country/region at a time, and see accounts located in only that country. To solve this problem, I would want to create different charts – each centering the map on a particular country (with a zoom factor according to the size of the country) and displaying only accounts from that country.

It would be possible to create multiple web resources addressing different map regions – however, that is not a very scalable solution. Creation of a web resource is generally a system customizer’s job – we would not want a system-customization for every new country/region that we would want to include.

Instead, what we will do is create a single ‘parameterized’ web resource. The web resource will contain the general logic for plotting accounts on a map – however, this logic would be driven by certain parameters which would be provided at runtime by the chart that is being rendered.

How does a web resource know which chart is being rendered?

If you have worked with web resources placed on forms/dashboards, you would be aware of the data query-string parameter. This parameter essentially lets the same web resource render differently in different contexts – you specify the value of this parameter (if required) at the time of adding the web resource to a particular form/dashboard.

For web resources rendering as charts, we do not let you explicitly specify a value for this parameter. Instead this parameter is always set to (a URL-encoded form of) the following format:

visid=<Visualization ID>&vistype=<Visualization Type>&viewid=<View ID>&viewtype=<View Type>

Therefore, we can get the ID and type of the chart being rendered by parsing the data query-string parameter.

Data and Presentation Descriptions of the Chart

Both System and User Charts have the following two fields.

  • DataDescription: This defines the data that is to be shown in the chart.
  • PresentationDescription: This defines the presentation and formatting of the chart.

For charts that use the in-built charting capabilities of CRM 2011, the values of the above fields have well-defined syntax and semantics. For our custom set of charts, we will continue using these fields to represent the data and presentation properties of the chart – however, we will define our own syntax and semantics for these fields based on our needs.

  • DataDescription: The country/region whose accounts are to be shown on the map.
  • PresentationDescription: This will need to convey two things: the coordinates of the center of the map, and the zoom factor. Let this be a comma-separated list of three numbers – a latitude, a longitude, and a zoom factor.

So here’s the basic idea – the web resource first figures out which chart is being rendered, then it reads the data and presentation descriptions of that chart, and parses them appropriately to extract the parameters that it needs to render the map at runtime.

Going into more detail, we will be doing the following in sequence.

  • Parse the query-string to extract the value of the data parameter. Parse this value again to obtain the ID and type of the visualization being rendered.
  • Retrieve DataDescription and PresentationDescription fields of the visualization using CRM oData end-point.
  • Parse the PresentationDescription to obtain the values of latitude, longitude and zoom-factor. Use Bing Map APIs to load a map with these values.
  • Get the country/region specified in DataDescription. Retrieve all Accounts from this country/region by making a GET request to a CRM oData URI with appropriate filters.
  • Geocode each of the retrieved account locations using Bing Map APIs, and plot them on the map.

Here’s one way you may write the web resource.

<html>

<head>

    <title>Accounts on Bing Maps</title>

    <script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.3"></script>

    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>

    <script type="text/javascript" src="ClientGlobalContext.js.aspx"></script>

 

    <script type="text/javascript">

        var map;

 

        // Function to construct key-value pairs from a query string.

        function getParametersFromQuery(query) {

            var parametersDictionary = new Array();

            var parameters = query.split('&');

            for (var i = 0; i < parameters.length; i++) {

                var keyAndValue = parameters[i].split('=');

                parametersDictionary[unescape(keyAndValue[0])] = unescape(keyAndValue[1]);

            }

            return parametersDictionary;

        }

 

        // Function that makes a GET request to the CRM REST end-point, and invokes a callback with the results.

        function retrieveFromCrmRestApi(url, callback) {

            $.ajax({

                type: "GET",

                url: GetGlobalContext().getServerUrl() + "/XRMServices/2011/OrganizationData.svc" + url,

                contentType: "application/json; charset=utf-8",

                dataType: "json",

                success: function (data) {

                    callback(data.d);

                }

            });

        }

 

        // Function that retrieves the corresponding CRM chart, and invokes the callback when successful.

        function loadChartFromCrm(callback) {

            var parameters = getParametersFromQuery(window.location.search.substring(1));

            parameters = getParametersFromQuery(parameters["data"]);

 

            var id = parameters["visid"].substr(1, 36);

            var type = parameters["vistype"];

            var url = (type == "1111" ? "/SavedQueryVisualizationSet" : "/UserQueryVisualizationSet")

                + "(guid'" + id + "')?$select=DataDescription,PresentationDescription";

            retrieveFromCrmRestApi(url, callback);

        }

 

        var locations = new Array();

        function plotAccountLocations(accounts) {

            if (accounts.length > 0) {

                var account = accounts.pop();

                var address = account.Address1_City + ', ' + account.Address1_Country;

                map.Find(null, address, null, null, 0, 1, false, false, false, false,

                    function (shapeLayer, results, places, moreResults, error) {

                        if (null != places && places.length > 0) {

                            var place = places[0];

                            var newShape = new VEShape(VEShapeType.Pushpin, place.LatLong);

                            newShape.SetTitle(account.Name);

                            newShape.SetDescription(address);

                            locations.push(newShape);

                        }

                        // When we have found (or not found) the current account,

                        // recursively call the same function to find the next one.

                        plotAccountLocations(accounts);

                    });

            }

            else {

                var shapeLayer = new VEShapeLayer();

                map.AddShapeLayer(shapeLayer);

                shapeLayer.AddShape(locations);

            }

        }

 

        function loadAccountsFromCrm(dataDescription) {

            var url = "/AccountSet?$select=Address1_Country,Address1_City,Name";

            if (null != dataDescription) {

                // Filter accounts based on country specified in data description.

                url += "&$filter=Address1_Country eq '" + dataDescription + "'";

            }

            retrieveFromCrmRestApi(url,

                function (data) {

                    var results = data["results"];

                    var accounts = new Array();

                    for (resultKey in results) {

                        accounts.push(results[resultKey]);

                    }

                    // Once accounts are retrieved from CRM Server, plot their locations on map.

                    plotAccountLocations(accounts);

                }

            );

        }

 

        function getMap(presentationDescription) {

            // Set center and zoom defaults.

            var center = null;

            var zoom = 4;

            if (null != presentationDescription) {

                // Calculate map-center and zoom from the presentation description.

                var arguments = presentationDescription.split(',');

                if (arguments.length > 1) {

                    center = new VELatLong(arguments[0], arguments[1]);

                }

                if (arguments.length > 2) {

                    zoom = arguments[2];

                }

            }

            map = new VEMap("map");

            map.LoadMap(center, zoom, VEMapStyle.Road, true, VEMapMode.Mode2D, false, 0);

            window.onresize = function (event) { map.Resize(document.body.clientWidth, document.body.clientHeight); };

            window.onresize(null);

        }

 

        function loadMap() {

            // First, get the chart object from CRM Server.

            loadChartFromCrm(

                function (chart) {

                    // Once we have retrieved the chart, format the map based on the chart's presentation description.

                    getMap(chart.PresentationDescription);

                    // Get Accounts from CRM Server based on the chart's data description, and plot them on the map.

                    loadAccountsFromCrm(chart.DataDescription);

                }

            );

        }

    </script>

</head>

<body onload="loadMap()">

    <div id="map"></div>

</body>

</html>

The code-snippet above uses a bunch of asynchronous callbacks – however, the basic sequence of invocation of functions is the following.

  • loadMap: Handler for the body.onload event.
  • loadChartFromCrm: Retrieve DataDescription and PresentationDescription of the current chart from the CRM 2011 oData end-point. Note the double-call to a function that parses a query-string.

var parameters = getParametersFromQuery(window.location.search.substring(1)); parameters = getParametersFromQuery(parameters[“data”]);

[The value of the “data” parameter is essentially a query-string within a query-string.]

  • getMap: Use Bing Map APIs to load a map with the center and zoom-factor specified in presentation-description.
  • loadAccountsFromCrm: Retrieve account records from CRM 2011 oData end-point, filtered by the country specified in data-description.
  • plotAccountLocations: Add push-pins on the map to represent each of the account records retrieved above.

Now let us go ahead and create a web resource on CRM Server with the above HTML. Let us call it new_accountsOnMap. It would now be pretty simple to create various charts using it. Let us start with Accounts in the U.S.

Import the following chart Xml:

<visualization>

  <primaryentitytypecode>account</primaryentitytypecode>

  <name>Account Locations in U.S.</name>

  <datadescription>U.S.</datadescription>

  <presentationdescription>39.8,-98.5,4</presentationdescription>

  <webresourcename>new_accountsOnMap</webresourcename>

</visualization>

This is what you will see:

clip_image008

 

Similarly, the following chart Xml gives you Accounts in India.

<visualization>

  <primaryentitytypecode>account</primaryentitytypecode>

  <name>Account Locations in India</name>

  <datadescription>India</datadescription>

  <presentationdescription>21,78,4</presentationdescription>

  <webresourcename>new_accountsOnMap</webresourcename>

</visualization>

clip_image010

Essentially, you have created your own parallel charting infrastructure for CRM 2011 that others can use to create system or user charts as appropriate. Like any other chart, such charts will automatically show up in the chart selector beside the records grid. And yes, they can also be placed on dashboards if so desired.

I have made available for you a Microsoft Dynamics CRM 2011 Managed solution containing the web resource and two system charts based on it.

Cheers!

Arko Nasipuri

Microsoft Dynamics CRM 2011 Fiscal Settings and Goal Management

January 19, 2011 Leave a comment

Microsoft Dynamics CRM 4.0 had the capability of defining the fiscal setting for an organization but there was a limitation that this could only be defined once and cannot be modified thereafter. Primarily the fiscal settings were used in CRM 4.0 to set salesperson quotas. In Microsoft Dynamics CRM 2011 the fiscal settings feature is revamped and it now provides user the capability of modifying fiscal settings multiple times. With deprecation of the Quotas in CRM 2011 Goal Management is one of the primary consumers for fiscal settings. This blog post explains how the fiscal periods for the organization can be set and how it interacts with the goal management.

How to configure the fiscal settings for organization

Fiscal settings can be configured by navigating to Settings-> Business Management -> Fiscal Year Settings. The following dialogue provides the options for setting values for fiscal start date, fiscal period type and various display formats. Note that as opposed to CRM 4.0 where the fiscal settings were absent in an organization until set, CRM 2011 defaults fiscal period to quarterly starting January 1. Also the various input options for the fiscal settings are now context dependent which prevents user from entering conflicting values.

clip_image002

Fig: CRM 2011 Fiscal setting dialogue with defaulted values 

Following are the various fields required for organization fiscal settings:

  • Start Date: When the fiscal year is going to start from. This date typically would mark the start of the financial year in sales organization. 
  • Fiscal Period Template: What is the fiscal period type? Possible options are Annually, Semiannually, Quarterly, Monthly, 4- Week period. Once the start date and period type is defined the system can calculate the start and end dates of fiscal periods for various fiscal years.

Fiscal Display options help user to define the display format for various fiscal settings. For example consider the following monthly fiscal settings with Start Date as April 10. Note that we have selected the “Name Based on” value to “End Date” and “Fiscal Period” drop down has the options specific toMonthly fiscal period template.

clip_image004

Fig: Fiscal dialogue having Monthly fiscal period starting 10th April.

Goals and Fiscal settings

Fiscal periods are tied closely to goal management. Sales people usually have the quarterly sales targets, Customer service representatives need to achieve their goals for the case resolutions and so on. When the new Goal form is launched, Goal is defaulted to the current fiscal period automatically. Because for current fiscal period there are fixed start and end dates, the goal start and end dates are also displayed in read only mode.

For example if we have the monthly fiscal settings are per the fig above and user clicks new goal form, following fiscal values are defaulted on goal form (on 31 Dec 2010)

clip_image006

Fig: New goal form defaulting dates to current fiscal period.

FiscalPeriod: December (Based on fiscal period display value “Month Name”)

FiscalYear: FY2011(Based on Prefix:FY, YearFormat:YYYY, NameBasedOn:EndDate(on 31 Dec 2010))

From (Goal Start Date): 12/10/2010 (Based on 4/10/2010 fiscal start date)

To (Goal End Date): 1/9/2010 (Based on Goal Start Date above and monthly fiscal period type)

Updating Fiscal settings for organization

Fiscal settings in MSCRM 2011 can be updated multiple times by using the same fiscal dialogue shown above and hence provides the supports for scenarios arising from mergers/acquisitions , partnership changes, financial restructuring etc. There can be goals existing in the CRM system which are already using the old fiscal settings. To better handle situations arising from fiscal changes which can lead to data inconsistency, MSCRM goal management offers the notification and realignment mechanism. For following examples consider the goal created with fiscal settings for the current (default) fiscal period. FiscalPeriod: December, FiscalYear: FY2011, From (Goal Start Date): 12/10/2010, To (Goal End Date): 1/9/2010.

Case 1: Fiscal period template remains same but the start dates changes:

CRM system administrator moves the fiscal start date ahead by 5 days i.e. from 4/10/2010 to 4/15/2010. In this case the fiscal period template remains the same but the start date has changed. Data in the goal record still retains the old values for all fiscal and date fields. When this goal record is opened the following warning message is displayed on the goal form to notify the fiscal settings change and provides user the option to realign.

Message: “The fiscal settings of your organization have changed since the time this goal was changed. You might want to realign to the new fiscal settings. ”

clip_image008

Fig: Fiscal change warning when the fiscal start date is changed.

Note that the “Align with Fiscal Period” ribbon button is now enabled for this goal record. Clicking this updates the new start and end dates for the goal which is now according to the current (new) fiscal settings. Realignment is optional for the goal manager based on the business need. Note that even after realignment goal fiscal period and year still remain same as there is only the change in the date. Also the warning message is now gone.

clip_image010

Fig: Goal form after the realigning the fiscal period.

Case 2: Fiscal period template changes:

CRM system administrator changes the fiscal period type from monthly to quarterly (3 months). In this case also the existing data is retained as is and there is a warning message on the goal.

Message: “The fiscal settings of your organization have changed since the time this goal was changed. You might want to realign to the new fiscal settings. ”

clip_image012

The goal manager on seeing this warning can either choose to switch to the new quarterly fiscal settings by changing the fiscal period to quarterly as shown in the above figure. Else he can convert this goal into the custom period goal by clicking on the “Goal Period Type” radio button and can retain the goal start and end date and also get rid of the fiscal change warning.

Fiscal settings upgrade

If the fiscal settings are configured for an organization in CRM 4.0 these are retained in CRM 2011 as is, otherwise the fiscal settings are defaulted to quarterly with January 1 as the start date. Additionally the existing CRM 4.0 quotas are also upgraded to CRM 2011 but the new quotas cannot be created as these are deprecated in favor of goal management.

Thanks,

Hemant Gaur

Accessibility in CRM 2011 lists

January 11, 2011 Leave a comment

Accessibility-compliance is one of the key new features of Microsoft Dynamics CRM 2011. We on the CRM team believe that no person should be denied from using the product even if one is visually challenged. Accessibility in CRM is useful not only to the visually challenged users but also to the user who prefers keyboard to mouse.

You can do almost everything in CRM 2011 lists quickly and easily using just a keyboard. For the visually challenged, using CRM 2011 lists with Job Access with Speech (JAWS) is a breeze. Also for them, we have also made enhancements to ensure that CRM lists display well in the high-contrast mode.

clip_image002

Sample Accounts list in CRM 2011

Compatible Screenreaders

Accessibility features in CRM 2011 work well in tandem with JAWS 11, the most widely-used screenreader in the world. We have also tested it on Window-Eyes, another popular screenreader.

Let us see how we can perform some of the common list operations in CRM 2011 using JAWS and keyboard.

Sorting

Sorting is one of the most commonly used functions in a list of records. Just follow the 2 simple steps below to sort on your favourite column using JAWS

1. Perform one of these actions:

    a. Press Ctrl+Insert+T to list all the tables in the current page. Scroll through the list and choose the table with the following title: From each column header, you can sort and filter the records.

OR

    b. Press Tab repeatedly until you get to the list header. When you reach the “Select/Clear All” checkbox, you are inside the list header.

2. Press Tab repeatedly until you reach the desired column in the header table. E.g. – To sort on Address 1: City (the 3rd column in the list), press TAB thrice. You will then hear “Table Nesting Level1 Column1 Row1 Address1: City link”.

3. Now press Enter to alphabetically sort the list based on Address 1: City. Press Enter again to sort it in reverse alphabetical order.

Similarly you can sort a list on any sortable column in the current view in increasing/decreasing order using JAWS. Simple, isn’t it?

Filtering

If sorting does not solve it for you and you need more advanced ways to filter your records, the Column Level Filtering feature in CRM is the way to go.

1. Tab to the link which reads “Filter button” Press Enter to enable filters on the list.

2. Now reach the list header using action 1 given in the sorting section given above.

3. To reach the desired column, use action 2 from the sorting section.

4. Press TAB again to go to the filter link. JAWS should read “Table Nesting Level 2 Column1 Row1 – ‘No filter applied’ link”

5. Once on the link, press Enter to open the filter menu. The filter menu has some common filters and a custom filter option as well.

6. Goto the desired filter option and press Enter to apply it on the list.

7. If you select Custom Filter, then the Custom Filters menu will open up which can be used to apply more powerful filters.

Opening primary/related records from the list

In CRM 2011 lists, all the primary field and lookup columns are hyperlinks which enables a JAWS user them to be able to open them.

1. Press Ctrl+Insert+T to list all tables in the current page.

2. Scroll through the list and select the table which reads “This list contains x Account records” where x is the number of records in the list. The focus moves to the table which contains the list of records.

3. Press TAB repeatedly until you get to the desired record. E.g. If you want to open the account with the name “Advanced Components”, press TAB until JAWS reads “Advanced Components Link

4. Press Enter to open the “Advanced Components” form.

Reading the contents of the list

Reading the contents of the list using JAWS is easier than ever before since the row/column headings are now read along with the value of a cell.

1. Goto the table which contains the list using the steps 2&3 described in the above section.

2. Use Ctrl+Alt+Arrow keys to navigate around the list.

3. Move horizontally to read the different fields of a record. When moving horizontally, the field name (column title) is read before the actual value of the cell.

4. Move vertically to read the same field from the previous/next record in the grid. When moving vertically, the record name (row title) is read before the actual value of the cell.

Selecting one or more records in the list

Selecting non-contiguous records in made easy in CRM 2011 lists with the introduction of row checkboxes.

1. Goto the table which contains the list using the steps 2&3 described two sections above.

2. To select the “Advanced Components” record, go to the checkbox corresponding to this record.

    a. Press Tab repeatedly until JAWS reads “Advanced Components, Checkbox unchecked”

    b. Press Space to check the checkbox thus selecting the record

3. Repeat the above step to select as many records as you want.

4. Once you have selected the desired record(s), you can perform edit, delete, share, assign and other record actions.

5. If you have selected multiple records, you can perform bulk operations on them like bulk delete, share, etc.

6. You can use the step 2 also to unselect a selected record.

Bye-bye Ctrl-Click!

We hope that this blog helps a bit in fulfilling our commitment to make CRM available everyone!

Cheers,

Aditya Agrawal

Introduction to Queues in Microsoft Dynamics CRM 2011

December 22, 2010 Leave a comment

Integrating Microsoft Dynamics CRM via App Fabric (using SAML token)

December 13, 2010 Leave a comment

In an earlier article called Integrating Microsoft Dynamics CRM via App Fabric, we saw how we can integrate Microsoft Dynamics CRM 2011 with an external application via the Windows Azure platform App Fabric. We converted a classical pull model of integration to a more efficient push model. The data was queried only when needed.

I would like to draw your attention to the authentication mechanism that was employed to authenticate with the Access Control Service (ACS). We used the management key approach and this implicitly made assumption that the key can be shared between CRM system and the owner of the syncing module. In many of the integration scenarios the CRM system and the external application (including the syncing module) may not be owned by the same business. The sharing of the ACS account’s management key is not possible.

Editor’s Note: For more overview material on AppFabric’s ACS there is an excellent article here: Access Control in the Cloud: Windows Azure AppFabric’s ACS.

Consider the scenario where an ISV has setup an endpoint on the App Fabric to which they want other CRM systems, its customers, to post data so that it can provide appropriate service. The ISV owns the Azure account and the rules on the ACS. It needs to enable its customer’s CRM systems to be able to post data to its endpoint and also be able to easily control and filter who is allowed to do so.

ACS provides the use of SAML tokens to authenticate and this is a good alternative for our need. Our goal is to allow CRM system to authenticate via SAML token and also allow ISV to configure rules in ACS based on the token’s issuer signature.

We start by first procuring an X509 certificate. You can use a self signed certificate too. Generate both private (.pfx) and public (.cer) certificate parts of the certificate. Add the .pfx certificate to the certificate store of the Async box, as we are running the plug-in asynchronously, under Computer account -> Local computer -> Personal -> Certificates.

Update the RetrieveAuthBehavior() show in the earlier blog sample with the code below.

private TransportClientEndpointBehavior RetrieveAuthBehavior() { // Behavior TransportClientEndpointBehavior behavior = new TransportClientEndpointBehavior(); behavior.CredentialType = TransportClientCredentialType.Saml; behavior.Credentials.Saml.SamlToken = GetTokenString(); return behavior; } private string GetTokenString() { // Generate Saml assertions.. string issuerName = "localhost"; Saml2NameIdentifier saml2NameIdentifier = new Saml2NameIdentifier(issuerName); // this is the issuer name. Saml2Assertion saml2Assertion = new Saml2Assertion(saml2NameIdentifier); Uri acsScope = ServiceBusEnvironment.CreateAccessControlUri(SolutionName); saml2Assertion.Conditions = new Saml2Conditions(); saml2Assertion.Conditions.AudienceRestrictions.Add( new Saml2AudienceRestriction(acsScope)); // this is the ACS uri. saml2Assertion.Conditions.NotOnOrAfter = DateTime.UtcNow.AddHours(1); saml2Assertion.Conditions.NotBefore = DateTime.UtcNow.AddHours(-1); X509Certificate2 localCert = RetrieveCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, issuerName); if (!localCert.HasPrivateKey) { throw new InvalidPluginExecutionException("Certificate should have private key."); } saml2Assertion.SigningCredentials = new X509SigningCredentials(localCert); // Add organization assertion. saml2Assertion.Statements.Add( new Saml2AttributeStatement( new Saml2Attribute("http://schemas.microsoft.com/crm/2007/Claims", "Org1"))); // The submitter should always be a bearer. saml2Assertion.Subject = new Saml2Subject(new Saml2SubjectConfirmation(Saml2Constants.ConfirmationMethods.Bearer)); // Wrap it into a security token. Saml2SecurityTokenHandler tokenHandler = new Saml2SecurityTokenHandler(); Saml2SecurityToken securityToken = new Saml2SecurityToken(saml2Assertion); // Serialize the security token. StringBuilder sb = new StringBuilder(); using (XmlWriter writer = XmlTextWriter.Create(new StringWriter(sb, CultureInfo.InvariantCulture))) { tokenHandler.WriteToken(writer, securityToken); writer.Close(); } return sb.ToString(); }

The code generates a self-signed token to authenticate to the app fabric. We could add any claims to the generated token, for example, adding the organization claim would be quite useful.

Configuring new rules in the App fabric

Since we are trying to authenticate via the signed SAML token, we would need to add the issuer and rules into the ACS to identify the token and issue “Send” claim in response. I am using the acm.exe that ships with the App Fabric sdk to configure rules in ACS.

First create the issuer entry in ACS-SB.

>Acm.exe create issuer -name:LocalhostIssuer -issuername:localhost -certfile:localhost.cer -algorithm:X509

Object created successfully (ID:’iss_334389048b872a533002b34d73f8c29fd09efc50′)

Next retrieve the base scope of the service bus: >Acm.exe getall scope

Use the scope id and issuer id to create the following rule.

>Acm.exe create rule -scopeid:scp_b693af91ede5d4767c56ef3df8de8548784e51cb -inclaimissuerid:iss_334389048b872a533002b34d73f8c29fd09efc50 -inclaimtype:Issuer -inclaimvalue:localhost -outclaimtype:net.windows.servicebus.action -outclaimvalue:Send -name:RuleSend

The rule basically says to output “Send” claim when the input claim (any claim) is signed by the specific issuer

With the above rule in place any organization in the customers CRM system will be allowed to post. If the CRM system is multi tenant, i.e. with multiple organizations, we can make the rule more granular to allow only certain organizations.

Rule using organization claim.

>Acm.exe create rule -scopeid:scp_b693af91ede5d4767c56ef3df8de8548784e51cb -inclaimissuerid:iss_334389048b872a533002b34d73f8c29fd09efc50 -inclaimtype: http://schemas.microsoft.com/crm/2007/Claims -inclaimvalue:Org1 -outclaimtype:net.windows.servicebus.action -outclaimvalue:Send -name:RuleOrgSend

Cheers,

Shashi Ranjan

Bulk Activity Management

December 9, 2010 Leave a comment

Activities form a major part of Microsoft Dynamics CRM. Sometimes it becomes necessary to perform operations on many of these activities at once. Microsoft Dynamics CRM 2011 provide ways to manage multiple activities at once. With the new grid view of Dynamics CRM 2011 you just have to select the multiple activities you want to manage together using the checkboxes. You do not have to hold down the control key like in CRM 4.0 for multiple selections. The only bulk operations supported by Microsoft Dynamics CRM 4.0 was Assign to operation.

Bulk Activity Editing

Microsoft Dynamics CRM 4.0 provided Bulk Editing capabilities for various records. Bulk edit was not supported for Activities. With the new Dynamics CRM 2011 bulk edit support has been provided for most activities. Activities that do not allow bulk editing include Recurring Appointments. You cannot bulk edit components of different activity types. This is because each Activity will have its own unique bulk edit form. Also some fields also might be disabled if incompatible for bulk editing.

Let us assume that we want to send letters to 3 personalized emails to 3 different Contacts informing them about the new Dynamics CRM 2011. First we create 3 Emails each of them having different recipients.

clip_image001

Select the three different emails and click on Edit.

clip_image002

An “Edit Multiple Record” form appears. We can now place in the text about how much we like CRM and how awesome it is in the fields we want.

clip_image003

All entries that are left blank indicate that you do not want to update the original entry in the Email. So now if you actually check the individual mails, you can find a personalized mail for each user.

clip_image004

Note that there is no way to blank off any entry using the bulk edit feature.

Other Bulk Management Operations

Bulk operations such as Mark Complete and Cancel require that the activities be of the same type. When either of them is selected there is a pop up window where you can select the status of the activities. So if I have to set the status of three Letters as Sent

clip_image005

Operations such as Set Regarding, Add Note and Add to Queue support activities of different types. Lets assume that we want to perform Set Regarding operation on the three emails and maybe a couple of corresponding appointments to a particular campaign. We can use advanced find to actually find the records we want to perform the bulk operation. Select all of them.

clip_image006

Then select Set Regarding. A lookup dialog box pops up where we can select the appropriate campaign we want.

clip_image007

Note that some of these operations that are not supported for certain activities. So these operations will not act upon these activities in bulk also. For example, Email activity does not support Mark Complete operation.

Cheers,

Girish Rao

Goal Management: Behind the scenes

November 26, 2010 Leave a comment

What is goal management?

In today’s world, any competitive organization has well defined goals for its members – measurable, and time bound, and with a clear ownership. Goal management in Microsoft Dynamics CRM 2011 lets you set such goals for members in your organization, and also lets you track the progress being made against them. You can set goals with complex queries spanning across multiple records, goal trees spanning organizational hierarchy, monitor their progress on a day-to-day basis, and all this with perfect ease.

So while you are wondering on the immense possibilities in which you can use this feature, our PM buddy Manu has already done a great job summarizing how you can use this feature to cater end-to-end scenarios here.

And now, for those of you, who want to dig deep into this magic vault, and understand what is happening behind the scenes, so that you can build your own applications on top of this, here’s your share of the pie.

Goal Management comprises of four different entities: goal, goal metric, rollup field, and rollup query.

In colloquial language, if you say: In the Quarter 3 of FY2010, Nancy needs to bring in $250000 revenue through opportunities in New York City, this is how this information maps to goal management entities:

image

I can generalize the above as:

1. Goal:

     a. Who does it?

     b. How much?

     c. In what time?

2. Metric: Is sort of metadata to goal. What is the type of goal you are setting? Types can be

     a. Count: Goal based on number of records. Like number of phone calls made by David.

     b. Amount: Goals based on aggregated amounts which come from some fields in a CRM entity. Like actual revenue. This has three sub types:

          i. Money

          ii. Integers

          iii. Decimals

3. Rollup Field:

     a. The record on which goal is based.

     b. The attribute in the record which contributes towards the target set in the goal

     c. The date type attribute which is compared against the timelines of the goal to decide if a record contributes towards this goal or not.

     d. The value of state/status that the record should have in order to be able to contribute towards a goal.

4. Rollup Query: What all records contribute?

You’ll notice that there’s a slight overlap of “what all records contribute?” between rollup field and rollup query. Here’s my take on it:

If you want your records to be filtered based only on dates, and statecode/statuscode(for example: closed opportunities), then metric will suffice.

Additionally, if you want to consider only those records which are owned by the goal owner, use the ConsiderOnlyGoalOwnersRecords field set to true for this.

But if you ask for anything more than this, while filtering records, you’ll need to use rollup query to define your query. Let’s say, you want to roll up only those opportunities which are in the city of New York, and have estimated revenue greater than $10,000 and are owned by your team, and have the originating lead also owned by your team, all you need to do is: Create a rollup query which has all the above clauses, and associate it to the rollup field you want to use the query for.

Now, that we understand, what each entity is used for, it’s time for some of my developer secrets to be unveiled. Let’s talk about some of the nuances that you need to know while programming for goal:

Goal timelines:

Goals can be of two types: custom period goal and fiscal period goal.

A fiscal period goal’s timelines match the organization’s fiscal settings. For example if the organization’s fiscal period is quarterly, then you can set quarterly goals, and the start dates and end dates of these goals will align with the organization’s quarter start and end date respectively.

If you do not want to use your org’s fiscal settings, then you can choose your own dates by creating a custom period goal.

Goal Metric: Whenever you create a goal, you associate it with a metric. A metric is not just a reference in goal, but it carries its properties: metricType and goalType to the referring goal as well.

Goal Rollup:

Let us first talk about what we mean by goal rollup.

Goal entity has certain fields that we use to indicate the progress made against the goal. The gathering of this data is termed as rollup.

A goal rollup is a two phase process:

1. For each individual goal, queries are performed based on the rollup fields they are associated with, and aggregates are updated in the goal.

Let’s run this through an example:

We’ll use the out-of-box metric: Revenue for this purpose.

Let’s take the same goal for Nancy that uses the Revenue metric as an example.

If you open Revenue, it has two rollup fields:

clip_image004

So a rollup on Nancy’s goal above will result in two aggregate queries on opportunities:

The Actual(money) field will be updated with an aggregate for Actual Revenue of all opportunities closed as won in Q3 FY20101 in New York.

The In-Progress(Money) field will be updated with an aggregate for Est. Revenue of all opportunities active in Q3 FY2010 in New York.

2. A goal can have one or more child goals, and hence you can create trees of goals to represent goals for an organizational hierarchy. In such scenarios, a child goal contributes towards a parent goal. Let’s say, Nancy reports to David, and David to Kevin. So we have the following hierarchy:

Kevin-> David->Nancy

Hence Nancy’s goal contributes towards David’s, and David’s goal in turn contributes towards Kevin’s goal.

So in the second phase, the child goal’s contribution is rolled up to the parent goal, all the way up to the root goal of the goal tree.

Rollup only from child goals field:

While creating a goal, you can choose not to roll up any data from participating records into the goal. The rollup fields in this case will contain data aggregated only from the child goals. So the step 1 in goal rollup section above will not be executed for this goal.

When does goal rollup happen?

Goal rollup has two modes: asynchronous and synchronous.

There’s a recurring async job that performs the rollup with a frequency configurable in organization settings.

Also, there’s a Recalculate button that you can use to do the rollup for a specific goal tree on an on-demand basis.

Goal targets:

You set a target in a goal. The target can be one of the three types: money, decimal, integer, and hence we have the following target fields respectively:

1. targetmoney

2. targetdecimal

3. targetinteger

Based on the metric you are referring, you will use only one of these at any given point of time.

Goal Rollup Fields:

In order to measure how the goal owner is doing, we have a set of rollup fields: Actuals, In-Progress, and Custom.

Actuals – This indicates the actual amounts achieved so far. Example, in case of revenue goals, this can indicate all opportunities closed as won.

In Progress – This is an indicator of the amounts you expect to achieve. Example, in case of revenue goals, this can indicate all open opportunities.

Custom – In case you need to track anything else as a performance indicator, you can use this field. For example, for revenue goals, you have two indicators: open opportunities with rating = hot strongly indicate potential revenue, while those with rating = warm indicate potential revenue, but much less likely than the former. In this case, you can use the In-Progress field for one, and the custom rollup field for another case.

Each of these is again of the three type variants. So we get the matrix:

  Money Integer Decimal
Actual ActualMoney ActualInteger ActualDecimal
In Progress InProgressMoney InProgressInteger InProgressDecimal
Custom CustomRollupFieldMoney CustomRollupFieldInteger CustomRollupFieldDecimal

 

Once you select a metric, which has one or more rollup fields, mapping to actual, in progress or custom rollup fields in goal, then while working on goal entity, you should use the respective field from rollup field, and respective type from the metric’s goal type.

Rollup Queries:

Again, based on the metric’s goal type, you’ll have a rollup query for your actual, in-progress, and custom rollup fields. Following is the table mapping for rollup query lookup fields and goal’s rollup fields:

Rollup Query Lookup
Goal Rollup Field
RollupQueryActualIntegerId ActualInteger
RollupQueryActualDecimalId ActualDecimal
RollupQueryActualMoneyId ActualMoney
RollUpQueryInprogressIntegerId InProgressInteger
RollUpQueryInprogressDecimalId InProgressDecimal
RollUpQueryInprogressMoneyId InProgressMoney
RollUpQueryCustomIntegerId CustomRollupFieldInteger
RollUpQueryCustomDecimalId CustomRollupFieldDecimal
RollUpQueryCustomMoneyId CustomRollupField

 

Based on your metric’s goal type again, there will be at max three rollup queries in use at any given point.

Auto-computed Attributes:

A set of auto calculated fields have been provided for making your life easy:

Field Name
Description
ComputedTargetAsOfTodayMoney Indicates what should be the actual target value as of today based on the target value and the goal’s start date.

Used when goal is a money type goal.

ComputedTargetAsOfTodayDecimal Indicates what should be the actual target value as of today based on the target value and the goal’s start date.

Used when goal is a decimal type goal.

ComputedTargetAsOfTodayInteger Indicates what should be the actual target value as of today based on the target value and the goal’s start date.

Used when goal is an integer type goal.

ComputedTargetAsOfTodayPercentageAchieved Indicates what percentage of the target should the actual be as of today based on the target value and the goal’s start date.
Percentage Indicates what is the actual achieved percentage of the goal against the target.

Uses target and actual fields to compute this.

 

Overriding goal rollups:

In normal course of things, goal rollups happen in background with a fixed frequency and the rollup fields are updated by the rollup job. However, if you explicitly want to override what the rollup job has calculated for the rollup fields, you can set the isoverride, and isoverridden fields = true and update the rollup fields.

If you set isoverridden to false, then the next rollup on that goal will overwrite these values with calculated values again.

Please note that you can do this only using SDK. The UI does not allow you to do this.

Goal owner vs goal manager: Looking at goal SDK, you’ll find two attributes: goalownerid, and ownerid. Goalownerid stands for the person/team for which the goal is being set. Ownerid is in traditional sense the CRM owner of the record, but since in real life scenarios, a manager governs her reportees goals, hence ownerid is named as Manager in the UI.

A goal rollup always happens in the context of goal’s manager.

Goal trees:

In a given goal tree, the following attributes will be same across the tree:

1. Goalperiodtype

2. Goalstartdate/goalenddate

3. Goalmetric

Goal currency: A goal’s currency is defaulted to organization’s currency, and is not valid for update.

Recalculate message: Goal rollup can be done synchronously using the Recalculate message. A recalculate for a goal will recalculate the entire goal tree. For code samples, you can refer to the SDK documentation.

By now you have enough insights to get started with goal management in CRM. Time to get your hands dirty!

Cheers!

Your friendly dev,

Nimisha Saboo