SSRS: How to open CRM Forms from Custom Reports

Just thought I would share how to add a URL in your SSRS reports to open a related CRM record. I spend a little bit of time figuring this out so here it is. I will skip the CRM/SSRS reporting 101 so if you are not familiar with building reports for CRM, you may want to familiarize yourself with basic concepts before you dive into this.

  1. Add a parameter to your report and make sure it prompts for the URL:

    This will return an URL that looks like this: http://YourOrganizationURL/CRMReports/viewer/drillopen.aspx?

  2. Now you can add the URL as an action when some of your elements are clicked. In my example, I have a few columns that when clicking on the value, will open a case, its owner or its customer.

    To do that, I select the column in the table that contains the data and head to the “Action” table; Select “Go to URL” as the action and then click on the function button to setup the URL.

  3. It’s time to use the URL parameter that was defined at step 1 that looks like this http://YourOrganizationURL/CRMReports/viewer/drillopen.aspx. To create a valid URL from here, we have 2 options that I know of… We can
  • Play around with VB to manipulate the String value and remove the part after the Organization URL highlighted in yellow above; from there we build the record URL as per Microsoft Dynamics CRM URL Patterns. It shouldn’t be complicated but I have not tried it.
  • Use a CRM\SSRS report built-in functionality that allows to simple pass the ID and logical name of the record we want to open to the URL received in parameter. It is able redirect to the appropriate form magically.

Obviously, I went with the 2nd option. You expression will look like this: Parameters!CRM_URL.Value & “?ID={” & Fields!incidentid.Value & “}&LogicalName=incident”)

Parameters!CRM_URL.Value : This is the parameter created in step 1
Fields!incidentid.Value: This is the ID of the record you want to navigate to
LogicalName=incident : This is the logical name of the record you want to valigate to

And just as a proof (although this really doesn’t prove anything!) J

And that’s it! It’s magical. Key takeaway here is the fact that if you ask CRM for the URL as a parameter to your report, you get a URL and you then have the flexibility to play around with it and create links to any page you need. The other takeaway is the functionality built in the report to open a record’s form by simple receiving the ID and logical name as parameters. Hope this saves some time for someone one day.

Retrieving Business Closure dates from Dynamics CRM

As developers, we are often asked to write plugins to calculate durations. A common example would be that the business wants to calculate how long an Opportunity was opened for. From a business perspective, it makes more sense to count only the business days, which is easy to do in C# (there are plenty of algorithms out there to filter out the weekends from a time interval). It makes even more sense to also exclude the holidays which are defined in the Business Closures calendar in CRM.

It is a nice feature and it integrates well with the out of the box Service module in the sense that you can configure it to prevent users from scheduling service activities on holidays.

From a development perspective however, it’s not that easy to deal with the Business Closures calendar for a few different reasons:

  • There is no clear documentation how to deal with them programmatically
  • In the Business Closures Calendar, we know they are stored in the related list of Calendar Rules, but the calendar rule entity doesn’t support Retrieve Multiple queries which makes the dates uneasy to retrieve
  • You can only retrieve the business closures by getting the business closure calendar, the latter supports Retrieve Multiple

You may get confused with the ExpandCalendarRequest that is out there. It is used to retrieve the calendar rules from a user’s calendar. The idea being to retrieve a set of time blocks with appointment information for a specific user (these are also CalendarRules). If you try to retrieve the rules for the business closures calendar, you get a rather obscure error: “Invalid time zone code”.

After spending some time on that route, I reverted back to the original recommendation by many on forums and blogs and I managed to make it work with the code below. The idea is to retrieve the business closure calendar ID of the organization and then return its list of CalendarRule. From there, it’s easy to use to result to do what you need.

private IEnumerable<Entity> GetBusinessClosureCalendarRules(IExecutionContext context, IOrganizationService service)
    // Get Organization Business Closure Calendar Id
    Entity org = service.Retrieve("organization", context.OrganizationId, new Microsoft.Xrm.Sdk.Query.ColumnSet("businessclosurecalendarid"));

    QueryExpression q = new QueryExpression("calendar");
    q.ColumnSet = new ColumnSet(true);
    q.Criteria = new FilterExpression();
    q.Criteria.AddCondition(new ConditionExpression("calendarid", ConditionOperator.Equal, org["businessclosurecalendarid"].ToString()));
    Entity businessClosureCalendar = service.RetrieveMultiple(q).Entities[0];
    if (businessClosureCalendar != null)
        return businessClosureCalendar.GetAttributeValue<EntityCollection>("calendarrules").Entities;
    return null;

With all this in place, you now know how to retrieve your business closures dates. My next step is to see if it is possible to restrict dates on the calendar rules that are retrieved. In the code above, the calendar is retrieved with all its business closure dates regardless of the year. If your CRM has been running a few years, it’s possible you have a lot of records in there and you may want to optimize your code by doing some fine tuning (get business closure dates from a specific date range). I’ll update this post after I get it to work if it ever happens J.