Saturday, December 3, 2011

CRM 2011 SDK 5.0.8 Released

Microsoft released the CRM 2011 SDK version 5.0.8!  You can find it here:http://www.microsoft.com/download/en/details.aspx?id=24004.  Here's a list of the updates in this release: http://msdn.microsoft.com/en-us/library/hh547453.aspx.

Some key updates include:

  • Information about Office 365 integration
  • Support for multiple languages
  • New sample for entity serialization
  • New sample for auditing user access

Monday, November 7, 2011

Tuesday, September 20, 2011

Sample Win 8 App: CRM 2011 Metro Style Contacts


I just got back from BUILD and I am very excited about the new possibilities of Windows 8 Metro style apps.  I was very eager to get my feet wet and see how easy it would be to pull records from CRM 2011 using HTML 5 and JavaScript and here is the result.

Disclaimer:  This is just a sample application and is not intended as a full working app.  This sample will NOT work with CRM Online and requires the device to have access to the on-premise CRM.  When the app loads it will prompt for credentials to the CRM organization.  To get around these limitations, a proxy service would need to be built to interface with CRM.

Notes:

  • Windows 8 Developer Preview and Visual Studio 11 Express for Developer Preview were used to create this Windows 8 app (http://msdn.microsoft.com/en-us/windows/apps/br229516).  
  • The source code for this solution can be found at http://crm2011metrocontacts.codeplex.com/.
  • This application will pull from the fullname, jobtitle, address1_line1, address1_city, address1_stateorprovince, address1_postalcode, address1_telephone1, and new_imageurl fields from the Contact record


First I decided to create a custom string attribute on the Contact entity called Image URL to populate the Metro style tiles with an image of the Contact:



Next I went into Visual Studio 11 Express and used the Grid Application template:



On top of the default JavaScript included in the Grid Application template, I added oDataMethods.js and jquery_1.4.1_min.js.  oDataMethods.js contains some helper methods to work with the CRM API and it also depends on jQuery.  You can find these files in the source code on CodePlex.  Once you add oDataMethods.js, you will want to update the serverUrl at the top of the file to point to your CRM Server:

var serverUrl = 'http://server/org',

At this point you can now run the app.  Here is what my app looks like with some test data set up:



And if you 'touch' a Contact tile:



Finally, here is the Contact data used for this demo:



Now to get into the code.  For the most part I left the Grid Application template alone but I will go into some depth about the changes I did make.  In landingPage.html I referenced the two scripts I added:

    <script type="ms-deferred/javascript" src="/js/jquery_1.4.1_min.js"></script>
    <script type="ms-deferred/javascript" src="/js/oDataMethods.js"></script>

The landingPage.html template just used a background color for the tiles which I switched to an image that populates from the Contact record.

    <div class="largeTileTextTemplateBackground">
       <img class="largeTileTextTemplateBackground" data-win-bind="src: largeImagePath"></img>
    </div>
    <div class="largeTileTextTemplateOverlay">
       <div class="largeTileTextTemplateLargeText" data-win-bind="textContent: title"></div>
       <div class="largeTileTextTemplateSmallText" data-win-bind="textContent: subtitle"></div>
       <div class="largeTileTextTemplateSmallText" data-win-bind="textContent: location"></div>
    </div>

By default in the Grid Application template, it uses the new data binding technique which you can learn about in this session by Chris Tavares around 35:00 -
http://channel9.msdn.com/Events/BUILD/BUILD2011/TOOL-501T

Next I updated the getGroups method in landingPage.js to just return a hardcode Contacts group instead of random fake data that the template uses.

     groups.push({
       key: 'Contact',
       title: 'Contacts',
       label: 'Get Started with Contacts',
       description: 'A contact is a person you do business with. Contacts are usually associated with accounts.',
       fullDescription: '',
     });

Then I updated the getItems method to retrieve all the active contacts in my CRM organization.

First I use the template code that loops through all the groups (which is now just our hardcoded Contacts group).  Then I use oDataMethods.js to retrieve all the active contacts.  For each contact I add an item object to the items array.  The items array is what is bound to the landingPage.html which will use the properties to display in the list view.  When a contact is 'touched', it passes the specific contact object into the detailsPage.html which binds the largeImagePath and content property to display the specific information about that contact.  toStaticHTML()  is used to strip out any scripts that might be contained in the HTML to prevent malicious attacks, otherwise the app will not display the HTML.

  for (var g = 0, gl = pageData.groups.length; g < gl; g++) {
       var filter = "?$filter=StateCode/Value eq 0";
       OData.retrieveMultiple(pageData.groups[g].key + "Set", filter,
       {
              async: false,
              success: function (data, textStatus, XmlHttpRequest) {
              for (var i = 0; i < data.length; i++) {
                     if (pageData.groups[g].key == "Contact") {
                           items.push({
                                  group: pageData.groups[g],
                                  key: data[i].ContactId,
                                  title: data[i].FullName,
                                  subtitle: data[i].JobTitle,
                                  location: data[i].Address1_City + ", " + data[i].Address1_StateOrProvince,
                                  largeImagePath: data[i].new_ImageURL,
                                  content: toStaticHTML(
                                         "<table><tr><td>Fullname:</td><td>" + data[i].FullName + "</td></tr>" +
                                         "<tr><td>Job Title:</td><td>" + data[i].JobTitle + "</td></tr>" +
                                         "<tr><td>Address:</td><td>" + data[i].Address1_Line1 + "</td></tr>" +
                                         "<tr><td>City:</td><td>" + data[i].Address1_City + "</td></tr>" +
                                         "<tr><td>State:</td><td>" + data[i].Address1_StateOrProvince + "</td></tr>" +
                                         "<tr><td>Zip:</td><td>" + data[i].Address1_PostalCode + "</td></tr>" +
                                         "<tr><td>Telephone:</td><td>" + data[i].Address1_Telephone1 + "</td></tr></table>"),
                                   description: ''
                            });
                     }                      
              }
}
       });
  }

So there you have it.  Although this demo is pretty simple, it only scratches the surface of the possibilities of interacting with CRM 2011 in a Windows 8 app.  I'm excited to continue to learn about Windows 8 development and uncover more of those possibilities!

Friday, September 9, 2011

BUILD

I'm very excited to be heading to BUILD next week!    It'll be my first time in California and my first time at a major development conference.  Hopefully the rumors of a Windows 8 tablet are true - http://thisismynext.com/2011/09/08/samsung-windows-8-tablet-build-developers-free-quad-core-arm/.

The session topics have been top secret so far but it's no secret that there will be a lot of talk about UI designing and HTML 5.  I'm excited to bring back some ideas to integrate with future CRM projects!

Stop by next week for an update!

Monday, September 5, 2011

CRM 2011 Help Visor Error

I've seen a few people on the CRM forums having an issue with the Getting Started Pane/Help Visor in CRM 2011.  It seems like the problem occurs when you install CRM on one port and then move it to a different port.

Here's the solution posted by xAirrick on this thread - http://social.microsoft.com/Forums/en/crm/thread/9399069a-8b7c-4bbe-ae5a-972faa0f007c

"We saw the the same problem with an CRM 2011 install.  Initially installed on http/port 80 and then we moved to https/port 443 but the help/getting started was still pointing to http/80.

There is a ConfigSettings table in MSCRM_CONFIG which has a column named HelpServerUrl which was still referencing http.  I changed this and did an iisreset and it resolved the problem."

Thursday, July 7, 2011

CRM 2011 Holiday Retrieval


Holidays in CRM are stored in the CalendarRules entity but unfortunately Retrieve and RetrieveMultiple messages are not supported for this entity.  Below is a snippet of code that will help to find the CalendarId that contains the holidays and how to retrieve the individual holidays themselves.

           var org = (from o in Context.OrganizationSet
                          select o).FirstOrDefault();

            var businessClosureCalendarId = org.BusinessClosureCalendarId.Value;
            var businessClosureCalendar = (from c in Context.CalendarSet
                                           where c.CalendarId == businessClosureCalendarId
                                           select c).FirstOrDefault();

            var calendarRules = businessClosureCalendar.CalendarRules;

Enjoy!

Thursday, June 16, 2011

CRM 2011 ConnectionDialog

 The CRM 2011 SDK contains a really helpful way to connect to CRM using the variety of connection types that CRM offers.

This hidden gem is a WPF control called ConnectionDialog and it can be found in the Microsoft.Xrm.Client.dll.  The SDK lists the ConnectionDialog class but it doesn't contain any examples of how to implement it so I'm providing the code I used to get it to work.

First I create the ConnectionDialog and then Activate it so it will bring the window to the foreground:

            ConnectionDialog dialog = new ConnectionDialog();
            dialog.Activate();

Then you can either show the window modeless or modal.  I chose to show it as modal and capture whether the User cancelled out without entering connection information:


            var result = dialog.ShowDialog();
            if (result == true)
            {
            }

If the User completed the connection wizard then the result will be set to true and then we can use the ConnectionString on the dialog to create an Organization Service like so:


            var connString = dialog.ConnectionString;
            var crmConnection = new CrmConnection(new ConnectionStringSettings("crm", connString));
            var orgService = CrmConfigurationManager.CreateService(_connection);

Now you have your Organization Service created from whichever connection type the User supplied and you can now access the services!

Here is the full snippet:


            ConnectionDialog dialog = new ConnectionDialog();
            dialog.Activate();
            var result = dialog.ShowDialog();
            if (result == true)
            {
                var connString = dialog.ConnectionString;
                var crmConnection = new CrmConnection(new ConnectionStringSettings("crm", connString));
                var orgService = CrmConfigurationManager.CreateService(_connection);
            }

And here is the dialog in action:





Enjoy!
         

Wednesday, June 15, 2011