Controlling CRM 2011 popup windows

Now and then, I hear from users that don’t like the fact that CRM loads screens in distinct windows in certain scenarios.  I can understand how these windows can get a little daunting if you have too many open and are switching context between multiple windows on your desktop.  However, this is actually a really nice to have capability when you are working in a multi monitor setup.  A tip that I have been sharing quite a bit lately, but have yet to blog about is to use the features of your browser to control the behavior if you prefer not having to deal with the separate windows.  Specifically, change your tabs configuration:

image

Now let’s walk through the behavior.  I’ll start by clicking an Account record:

image

Notice how the account opened in a new tab next to my first tab:

image

Again, I will click something that would traditionally give me a popup window.  Now there is a third tab:

image

There’s also a natural “breadcrumb effect” because the tabs are in order left to right of how I interacted with them.  Also, when I close the rightmost tab, I’m back where I came from, and so on.  So if you are in the “I don’t like all these popup windows” camp, this will hopefully help you out.

@devkeydet

Minify Selection in Visual Studio 2010

You learn something new every day!  One of the things I’ve been talking to CRM folks about a bit lately is Minifying your CRM 2011 JavaScript and CSS.  Well, I just discovered that when you install the Microsoft Ajax Minifier, you get a handy little context menu option to minify.

image

It shows up in both .js and .htm files when you select the JavaScript.  Pretty cool!

@devkeydet

Using the CRM 2011 OData service from a Metro style app

UPDATE: Fixed a few bugs in the downloadable sample including one where it wouldn’t work in Office 365 based CRM Online subscriptions.  Edited some text in the post for clarity.

UPDATE2: Added some text about how to get this working for Windows Authentication.

UPDATE3: I’ve just blogged about an update to the sample here.  The updates in the code might make following this post a little confusing.  The reason is that due to the final terminology for Windows Store Apps, I needed to refactor the solution/project files and class names.  While I plan on updating this post soon, I wanted to get the changes published.  Hopefully, the naming changes are obvious enough for folks until I update this post. 

Scenario:

“I want to build a Windows 8 Metro style application.  Since my app is going to just perform CRUD operations, I want to use the OData service using json so that I have the least amount of ‘data across the wire’ possible.”

DISCLAIMER: This a pretty hacky approach, but it works and is the only way I know of to do it.  If you like it, use it.  If not, wait until there’s an official sample in the SDK.  You’ve been warned.  I’m just a guy getting creative to solve a problemSmile.

First I will walk you through how to do it.  Then I will explain how it works.  To get started, download and import the following solution into you CRM 2011 organization:

http://sdrv.ms/S3MND1

Next, download the source code of my sample library:

http://sdrv.ms/RYzVzj

I say sample library very loosely.  This is FAR from being a complete, well tested library.  I have good intentions to make it one, but wanted to get a sample of the basic plumbing working for those of you who have asked me how to do it.  This sample should be enough to get you started, but you’ll have to finish out the rest of the functionality.  If anyone wants to take this sample and turn it into an open source project, YOU HAVE MY FULL PERMISSIONSmile.

USING THE SAMPLE

Create a new Metro style app.  I am going to use the Blank App template to keep things simple:

image

Add my sample library to the solution:

image

Don’t forget to right-click References nod of the Crm2011MetroStyleODataApp in Solution Explorer and a reference to the project you just added:

image

image

Find the Devkeydet.CrmMetroODataHelper.csproj file and add it.  Replace the default Grid in MainPage.xaml with the following:

<Grid x:Name="LayoutRoot" Background="{StaticResource ApplicationPageBackgroundThemeBrush}">

    <StackPanel x:Name="MainUIStackPanel" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Collapsed">

        <TextBlock x:Name="myTextBlock" Text="TextBlock" TextAlignment="Center" />

        <Button x:Name="queryButton" Content="Button" />

    </StackPanel>

</Grid>

In MainPage.xaml.cs, paste the following code into the OnNavigatedTo method:

var oDataHelperWebResource = "https://devkeydet.crm.dynamics.com/WebResources/dkdt_/MetroODataHelper.htm";

 

if (!CrmMetroODataHelper.IsLoggedIn)

{

    CrmMetroODataHelper.SignIn(oDataHelperWebResource, LayoutRoot);

    CrmMetroODataHelper.SignInComplete = () => MainUIStackPanel.Visibility = Visibility.Visible;

}

Make sure to replace “https://devkeydet.crm.dynamics.com” with the right url for you.  You will have to add a using Devkeydet statement to the file.  Ok, now it’s time to “Add Service Reference” to the OData service.  Unless you are using Windows Authentication, you can’t point the “Add Service Reference” dialog to the data service url.  Instead, you need to download it and point to it locally, from Visual Studio:

image

image

Save it somewhere and point, then “Add Service Reference” by pointing Visual Studio to the file:

image

Add the following method to MainPage.xaml.cs:

private  async void ExecuteODataQueryAsync()

{

    var ctx =

        new devkeydetContext(new Uri("https://devkeydet.crm.dynamics.com/XRMServices/2011/OrganizationData.svc/"));

 

    // Use the generated DataServiceContext to compose the query using LINQ, 

    // but get the string of the query via ToString().

    // We still get to use the query composition capabilities of LINQ!

    var query = from a in ctx.AccountSet

                where a.Name.StartsWith("A")

                select new Account

                {

                    Name = a.Name

                };

 

    var accounts = await CrmMetroODataHelper.RetrieveMultipleRecordsAsync<Account>(query.ToString());

 

    myTextBlock.Text = accounts.First().Name;

}

Again, remember to replace “https://devkeydet.crm.dynamics.com” with the right url for you.  You will have to add a using statement based on the Namespace you gave the generated code and devkeydetContext will need to be replaced with your generated context name.  Now, wire up an event handler for the button (ex: double click the button on the design surface) and call the method:

ExecuteODataQueryAsync();

If your app is using Windows Authentication, then you need to double-click on the Package.appxmanifest and make sure you have the following Capabilities checked:

image

Go ahead and run the app.  You will be prompted for your credentials if necessary:

image

Sign in with your credentials, click the button, and the TextBlock should have the value of the Name property of the first result:

image

There you go!  You just issued an OData query from a C# Metro style app!

HOW THE SAMPLE WORKS

The sample wraps the WebView control.  The WebView control tries to load an html web resource from the CRM server (that’s what’s in the devkeydetMetroODataHelper_1_0.zip solution).  If you haven’t logged in, then the WebView is set to be visible and it will just present you with the web based login UI.  Once logged in, the WebView visibility is collapsed and the C# wrapper basically proxies OData calls through WebView via the web resource using a modified version of the SDK.REST.js file from the CRM 2011 SDK.  The major modification is that the default SDK.REST.js sample will turn the resulting json string into an JavaScript object.  Instead, I just pass the json string back to the C# wrapper and use JSON.NET to turn it into C# objects.

As I mentioned earlier, this is FAR from being a complete and reusable library.  I have good intentions to make it one, but wanted to get a sample of the basic plumbing working for those of you who have asked me how to do it.  This sample should be enough to get you started, but you’ll have to finish out the rest of the functionality.  I only implemented executing a query that returns multiple results.  Furthermore, I didn’t handle continuation tokens.  If anyone wants to take this sample and turn it into an open source project, YOU HAVE MY FULL PERMISSIONSmile.

@devkeydet

Populate Two Options values when creating a record in a dialog

Scenario:

“I have an entity with a field of type ‘Two Options’ that I would like to populate within a ‘Create Record’ activity in a CRM 2011 dialog.   The ‘Two Options’ type in CRM 2011 is a boolean.  The ‘Prompt and Response’ activity in a CRM 2011 dialog only gives me options for Text/Integer/Float.”

image

“Because of this, I can’t set the value of the answer to the field in the entity  within ‘Set Properties’ because the types don’t match.”

image

image

Custom workflow activities to the rescue!  I wrote a very simple workflow activity that converts the integer to a boolean.

image

image

image

Once you have the ‘Two Options’ typed value, you can map it to your field.

image

The code for the workflow activity is the simplest workflow activity I have ever created:

image

If you don’t want to build/deploy the code yourself, but just want to use the workflow activity to solve this problem, then you can download an unmanaged solution here:

https://skydrive.live.com/redir?resid=1F72DA7294089597!16571

I also have an end to end example in an unmanaged solution here:

https://skydrive.live.com/redir?resid=1F72DA7294089597!16570

In the end to end example, I went ahead and created a ribbon button that will launch the dialog without having to select an entity in the grid.

image

I used the User entity trick from http://dkdt.me/KmqxOZ.  In putting together the sample, I was also inspired by http://dkdt.me/KmqwdV.  However, I took a shortcut.  I hard coded the CRM User guid for the ObjectId in the dkdt_/scripts/LaunchModalDialog.js file.  You will need to go into it and update it with an actual user in your CRM org for the sample to work.

If you want the source code for everything, you can grab it here:

https://skydrive.live.com/redir?resid=1F72DA7294089597!16569

NOTE: The code requires the Developer Toolkit for Microsoft Dynamics CRM 2011.

 

@devkeydet

REMINDER: SharePoint BCS connector for CRM

I’ve been going through a bunch of CRM integration scenarios to refresh my “hands on” abilities.  You have to do that in a job like mine, otherwise you’re just a talking head that doesn’t know what you’re talking aboutSmile.  Anyway, the topic of integrating CRM with SharePoint beyond what’s available out of the box comes up often.  Two sessions worth watching to understand some of the possibilities are:

http://dkdt.me/L5DcGW

http://dkdt.me/kUq33n

They are very similar sessions, but from two different presenters.  One of the things covered in these sessions is how to integrate CRM and SharePoint through BCS.  The trick to doing it productively is the sample code Chris and Girish made available here:

http://dkdt.me/L5DcH4

With this, you can now open up the world of possibilities that SharePoint BCS enables including cross entity searching.  See Configuring Business Connectivity Services (BCS) Search in SharePoint 2010 as an example.

@devkeydet

TIP: Associate a schema with an XML file in Visual Studio 2010

It’s been a while since I had to do it.  However, as I’ve started to need to tweak FetchXML after I’ve built the baseline using my little trick, I realized I was doing things the hard way.  I was looking at the FetchXML reference on MSDN and typing things “notepad" style” but with syntax highlighting.  Then I had that “DUH” moment.  Just point the file to the FetchXML schema in the SDK and you’ll get intellisense.  Here’s how:

Take a look at the Properties of your XML file in Visual Studio:

image

In the Properties pane, click on the ellipsis () for the Schemas property:

image

Click the Add… button:

image

Find the fetch.xsd file that’s in the schemas folder of wherever you unzipped the Microsoft Dynamics CRM 2011 Software Development Kit (SDK) and click the Open button:

image

Now you have XML intellisense for your FetchXML:

image

@devkeydet

Converting a SQL report to FecthXML

Scenario:

“I want to move to CRM Online, but I wrote all my SQL Server Reporting Services (SSRS) using the SQL Data Source.  How do I convert them to use FetchXML?”

Below I have three reports:

image

All three reports will look identical to the end user in the end.

facilityFetch.rdl – Written using the “Microsoft Dynamics CRM Fetch” Data Source available after you install the Microsoft Dynamics CRM 2011 Report Authoring Extension.

facilitySql.rdl – Written using the “Microsoft SQL Server” Data Source.

facilityConvertedSqlToFetch.rdl – Identical to facilitySql.rdl to start, but will be identical to facilityFetch.rdl once converted.

The key to a quick conversion is getting the results of the fetch query to look IDENTICAL to the sql query.  Basically, what you need to do is go through all your Datasets and update them with a matching fetch query.  In my example, facilityConvertedSqlToFetch.rdl DataSet1 uses a local Data Source called sqlds:

image

image

image

First step is to create a new fetch data source:

image

image

I tend to develop locally for developer productivity so I am pointing a local CRM 2011 deployment in my VM.  The format for the connection string is [root];[orgname].  Now that we have the fetch Data Source created, we need to create a matching fetch query.  My favorite way of going about this is here.  So let’s update the Dataset:

image

Make sure you update the Data Source to use the new fetch data source and replace the query with the right FetchXML query:

image

Again, the KEY here is that the shape of the Dataset is the same AND the column names are the same.  Save & Preview your new report.  It should “just work.”  For more advanced FetchXML scenarios, see Build Queries with FetchXML.

@devkeydet

Cross domain calls from JavaScript

It’s exciting times for web developers.  Many of the hoops we used to have to jump through are being eliminated as more browsers support more of the HTML5 spec and more people are using modern browsers.  One of the things that has me excited is Cross-origin resource sharing (CORS)

In the context of Dynamics CRM, it means that more can be done from HTML and JavaScript web resources without having to do things like proxy calls through a server.  It also reduces the scenarios that require you to implement Cross domain calls to the parent CRM 2011 form.  The need to replace window.parent with window.postMessage when you truly do need to communicate cross domain across iFrames.  However, I’ve used the window.postMessage approach to have a hidden iFrame in a CRM form that is a blank ASP.NET page that calls a third party web service from server-side code, then passes the response to a the client, which then passes the results to the CRM form using window.postMessage and the form code prefills controls in the form.  All this hoop jumping is necessary because of the way older browsers work.  The complexity could be reduced with CORS. 

The rub is that there are still browsers out there that don’t support CORS.  The wikipedia link covers which.  The good news is that modern browser adoption is growing fast.  We’re approaching a time where there is a small enough group of the older browsers where you might feel comfortable displaying a message to your users saying “Are those cobwebs I see on your browser?  Please upgrade to use this app.”  Not everyone can do that, but if you can, then read on.

IE10 supports CORS through the XMLHttpRequest object.  IE8 & 9 support it, but the through the XDomainRequest object.  I don’t know about you, but I don’t XMLHttpRequest directly anyway.  I typically use the jQuery $.get(), $.getJSON(), or $.ajax() methods.  There is a helper library for jQuery called jQuery.iecors that allows you to use jQuery unchanged.  The last thing you need to know is that the server you are calling to has to allow CORS.  Thanks to enable-cors.org, you have a handy reference to know how enable it on your server. 

@devkeydet

Design for Online

UPDATE (30MAY2013): Have a look at this post for some tangible examples of Windows Azure with CRM to address some of these scenarios.

DISCLAIMER: This post is not official guidance from Microsoft.  It’s the thoughts and opinion of one guy who has been spending a fair amount of time talking to customers and partners about what I’ve been calling the “Design for Online” principles.  These are just my “brain dump” notes of what I’ve learned along the way.  Therefore, feel free to leave comments and provide feedback to make this post better.

In many ways, this post is a different spin on my CRM Online myth busters post.  However, instead of forcing you to reverse engineer “Design for Online” principles from a bunch of busted myths, I decided to lay out what I believe to be the key design decisions and pointers you need to make sure you have a solution that will run relatively unchanged in any deployment environment: CRM 2011 installed in your datacenter (OnPrem), CRM Online, or another hosting provider.  I think that everyone should be forcing themselves to embody these principles in ANY solution they build on top of CRM 2011.  Why?  It gives you deployment flexibility.  I’ve worked with a few folks who wanted to move to CRM Online and were disappointed that their solution wasn’t built in such a way that could get them there without major rework.  If they had built with “Design for Online” in mind, then they would be much happier right now.  Also, I just think that on-prem apps shouldn’t be designed with “legacy design principles.”  They should be designed with modern design principles including separation of concerns and the isolation you get when you stick to these principles.  At a high level, the principles can be summed up as:

  • Use Claims-based authentication
  • Run everything under SSL
  • Deploy all .NET assemblies (plugins / workflow activities) to the sandbox / database
  • Use ILMerge with third party assemblies
  • Put full trust code somewhere else
  • Configure any UI mash up integration for Single Sign-on
  • Pretend the Filtered Views don’t exist
  • Build all of your Reporting Services reports using FetchXML

 

Use Claims-based authentication

As I mentioned in my CRM Online myth busters post, CRM Online supports ADFS 2.0.  Claims-based authentication doesn’t mean you have to have an Internet Facing Deployment (IFD).  However, if you want to go IFD, you have to use Claims-based authentication anyway.  If you have the option, you should always go with this as your authentication choice.  This is also a key to enabler to Single Sign-On (SSO) with other pieces of your application (ASP.NET pages, SharePoint, etc.) whether you are on your corporate network or accessing CRM from any internet connection.  A good place to start is Configuring Claims-based Authentication for Microsoft Dynamics CRM 2011.  Also, the Microsoft Dynamics CRM 2011 Implementation Guide has a specific whitepaper called Microsoft Dynamics CRM 2011 and Claims-based Authentication.doc you should have a look at as well.

 

Run everything under SSL

This is actually a requirement for Claims-based authentication, but I felt it was worth calling out by itself.

 

Deploy all .NET assemblies (plugins / workflow activities) to the sandbox / database

This is the first place I hear a fair amount of developer / solution architect angst.  Lots of “Yea, but what if…” retorts.  I’ll get to those.  Keep reading.  If you aren’t familiar with the sandbox, then make sure you read Plug-in Isolation, Trusts, and Statistics.  Do not change the registry key mentioned at the end of the article.  If you are Using the Plug-in Registration Tool for Microsoft Dynamics CRM 2011, then make sure you set Step #3: Specify the Isolation Mode to Sandbox and Step #4: Specify the Location where the Assembly should be stored to Database when Registering a Plug-in or Custom Workflow Activity.  If you are using the Developer Toolkit for Microsoft Dynamics CRM 2011 and Microsoft Dynamics CRM Online, then it defaults to this form of registration.

 

Use ILMerge with third party assemblies

Code within sandbox deployed assemblies is constrained to using .NET Framework assemblies, the public assemblies that are part of the Microsoft Dynamics CRM 2011 Software Development Kit (SDK), and the code inside the assembly itself.  If you need to leverage a third party assembly, then consider using ILMerge.  There are two blog posts I find useful to get this configured here and here.  The second post is a little old and talks about .NET 3.5.  Ignore that part.  The useful part of the second post is how to configure Visual Studio to use ILMerge as a post build activity.

 

Put full trust code somewhere else

Sometimes, you just have to write code that won’t run in the sandbox.  Resist the urge to violate the Deploy all .NET assemblies (plugins / workflow activities) to the sandbox / database principle.  Instead, put the code requiring elevated trust behind a web service hosted in a separate process that you own.  Call it from the plugin / workflow assembly.    In the OnPrem world, the web service will probably be running on Windows Server in its own web site.  In CRM Online, the web service will probably be running in a Windows Azure Web Role.  Also, OnPrem this can run on the same physical server as the CRM 2011 front-end servers even though you are going to have to run the site on a separate subdomain.  See Binding multiple domains to a wildcard SSL on a single IP in IIS 7.5 for more details.  There are some key implementation details for this to work:

  • Use the trusted subsystem pattern to authenticate from the plugin code to the external web service using a single identity.
  • If the code running behind your web service needs to call back into Dynamics CRM, then:
    • The web service code in turn uses the trusted subsystem pattern to authenticate back to CRM via the Organization Service using a single identity.  This is typically a CRM user you’ve created specifically for trusted subsystem use.  There are a number of samples for connecting to the Organization Service from .NET code, but the Simplified Connection to Microsoft Dynamics CRM really does make it simple!
    • If you need the CRM Organization Service to execute under the context of the original user the plugin code ran under, then you will need to Impersonate Another User.  Therefore, you will need to pass CallerId from the plugin code to your web service code, which will then passes it back to the CRM Organization Service.

This all seems a little daunting when you first hear/read it, but after you’ve done it once you will realize it isn’t as daunting as it sounds.  Consider this scenario the exception, not the rule.  A few other little tidbits of information to help you implement this scenario:

    • Consider making your web service a REST service.  There is generally less overhead and a smaller data payload across the wire especially if you use JSON serialization.  There really isn’t anything about these services that require SOAP, unless you just prefer the SOAP service programming model better.
    • If you prefer to use a SOAP service, then have a look at:
<customBinding>

  <binding name="NetHttpBinding">

     <binaryMessageEncoding />

     <httpsTransport />

  </binding>

</customBinding>

      • If you use binary encoding, then modify the code in the Calling WCF Service in Plugin in CRM link to reflect it:
BindingElementCollection elements = new BindingElementCollection();

elements.Add(new BinaryMessageEncodingBindingElement());

 

elements.Add(new HttpsTransportBindingElement());

 

CustomBinding binding = new CustomBinding(elements);

 

Configure any UI mash up integration for Single Sign-on

While less prevalent with the advent of web resources in CRM 2011, there are still times where you want to write custom ASP.NET code or even REST services that you want to integrate (or mash up) into the CRM UI, but need to write server side code for them.  The only supported way to do that in CRM 2011 is to have a companion site and Implement Single Sign-on from an ASPX Webpage or IFRAME.  In the OnPrem world, the content will probably be running on Windows Server in its own web site.  In CRM Online, the content will probably be running in a Windows Azure Web Role.  By doing taking this approach, you can no longer use window.parent for cross frame communication because you will be in a cross domain scenario. See Cross domain calls to the parent CRM 2011 form.  Another scenario that you may not realize is a UI mash up integration is the out of the box SharePoint integration for CRM 2011.  More details here.  However, if you’ve configured single sign-on across these three sites (CRM/SharePoint/Companion Site), then it all just works at the UI layer.  This is why principle #1 is Use Claims-based authentication.

 

Pretend the Filtered Views don’t exist

Plain and simple, CRM Online doesn’t support direct access to the database.  Therefore, in the world of CRM Online, the Filtered Views don’t exist.  Write all of our code against the CRM web services.

 

Build all of your Reporting Services reports using FetchXML

In order to build FetchXML SSRS reports, you need to install the Microsoft Dynamics CRM 2011 Report Authoring Extension on the same PC in which you have Business Intelligence Development Studio (BIDS) installed.  This adds a Fetch XML data source.  From there, you just follow the directions in Create Custom Reports Using Business Intelligence Development Studio.  SSRS reports in CRM Online are Sandboxed.  See RDL Sandboxing for Microsoft Dynamics CRM Online for more details.  One of the objections I often hear is “but I really want to write my queries in SQL because that’s what I know.”  I “get it.”  For now, FetchXML it is.  For most, I recommend using the Advanced Find feature of the CRM UI to compose the query, then click the Download Fetch XML button. 

image

For advanced query capabilities of FetchXML that aren’t possible through Advanced Find, you will need to start with Advanced Find, then modify the XML yourself.  See Build Queries with FetchXML for more details.  Personally, I’m not “GUI Query Tool” guy.  I like to write my queries by hand.  Let’s face it, no one wants to learn “yet another query language” which is what you have to do with FetchXML.  I shield myself from this by using LINQ.  I use LINQPad + LINQPad Plugin for Microsoft Dynamics CRM 2011.  The one gotcha is that the plugin doesn’t produce FetchXML.  There’s a feature request here to enhance the plugin to do so.  VOTE it up!  However, through extensibility of LINQPad, I created an extension method to do the conversion.  See Getting FetchXML from LINQPad for more details.

 

What about integrating with systems behind my firewall from CRM Online?

This isn’t exactly a “Design for Online” principle as much as an answer to the “How do I do it in CRM Online?” question. While CRM Online doesn’t provide any specific capability to securely cross the internet and talk to systems behind an organizational firewall, you can still do it.  CRM Online is from Microsoft.  Microsoft is a platform company that happens to have a platform that already enables such scenarios.  It’s called Windows Azure.  I address this scenario and others in my CRM Online + Windows Azure = Many Possibilities post.  While these approaches enable “from CRM Online” scenarios, meaning code running inside CRM Online calling out, it’s equally important to understand that some integration needs can be met with data integration that can be achieved through tools such as  CozyRoc and Scribe.  Of course, your scenarios will dictate what integration approach is most appropriate.  Also, building optimized data migration code becomes more important when you are calling across the internet moving data from a legacy system to a cloud environment.  I have a post about called Data Migration with CRM 2011 that covers this topic.

 

Summary

Ok, so now I finally have a blog post to point people to that comprehensively covers what I think of as the “Design for Online” principles.  The last point, Yes, I have tried all of this stuff out.  However, I have tried each out in isolation.  I’m planning on putting together a fairly simple reference sample that brings all of this together and demonstrates it running in CRM OnPrem + Windows Server as well as CRM Online + Windows Azure.

@devkeydet

CRM Online myth busters presentation

I’ve created a presentation version of my CRM Online myth busters post.  The goal of the deck is the same as the post, which is to share common misconceptions I run into about CRM Online when speaking with folks.  The presentation is geared towards those who aren’t interested in the technical details from the post.

Direct link: http://dkdt.me/JNFJEm

@devkeydet