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:
- 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();
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.
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.
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.