Making Cross Domain AJAX calls from CRM Form JScript

One of the cool things about JScript in CRM 2011 is that you can now use the jQuery $.ajax method to call, most notably the CRM REST endpoint. Now, one of the things that is sometimes required in customers’ solution is the ability to call other REST endpoints from a CRM form. An example of that use case would be to have a button that calls a web service in order to perform some sort of operation (e.g. modify your current record, or just send data over another systems for synchronization etc.) in a synchronous and interactive way. Another example would be to automatically fill fields on a form with information coming from another system (retrieve them via web service and set the values on the form). There are two main issues with doing that :

  • First, some browsers will simply not allow jQuery AJAX requests to run if they are made to a domain different than that of the running web application. The reason behind is that not all browsers can create XMLHttpRequest objects that have a withCredentials property. That is used to specify that we want to include the user credentials in a cross domain request. To always have that working, jQuery has the solution for us. Use the following statement in the code before making the AJAX call: jQuery.support.cors = true;
  • The other more complicated issue is that most browsers simply won’t allow JavaScript to make a cross domain request for security reasons. In most contexts, this sounds normal and reasonable.

Here are a few workarounds if you are facing the second issue.

  1. Try to transfer your logic to the server side. Can you do what you need by using a dialog or a workflow with a custom activity (server side code)? Can your logic be performed on a synchronous plugin (server side code)? If one of these solutions is acceptable, then this is what you should do.Applies to: CRM Online, On Premise, ADFS / IFD
  2. Use IIS URL Rewrite rules on your server. To illustrate, let’s say your CRM server URL is http://MyCrmServer/MyOrg and your external REST endpoint is http://RestEndpoint/RestService?params. You can create a URL rewrite rule that will transform all requests coming in as http://MyCrmServer/RESTENDPOINT/RestService?params to http://RestEndpoint/RestService?params. In other words, whenever IIS sees the string MyCrmServer/RESTENDPOINT in a URL it replaces it with RestEndpoint. It is simple to configure with Regular Expressions.

    This is a good solution because it handles the request on the server side. From a Jscript perspective, it is as if you are querying the CRM server and the request is transformed once it reaches the server. You can read more about IIS URL Rewrite here. The downside of this approach is that every single page that is opened from the CRM web app triggers a URL rewrite rule evaluation. Microsoft says the algorithm are optimized for performance and I have never experienced visible delays due to using the rewriter. Also worth noting that obviously, this is not supported for CRM Online since we don’t have access to Microsoft’s CRM Servers.

    Applies to: CRM On Premise, ADFS / IFD (if provider gives access to CRM Server)

  3. Enable Cross Domain browsing on the browser. In IE, this is blocked by default. You can change the settings by going to Internet Options Security and Custom Level Settings. In most case, this solution is not acceptable for an enterprise’s perspective for security reasons.


    Applies to: CRM On Premise, ADFS / IFD, (CRM Online? Not confirmed but it should work)

I personally think making requests to a cross domain web site via JavaScript should not be done if there are acceptable other options simply because it adds overhead somewhere based on the solution you go with. (e.g. if you go with solution 2 on premises, you have to make sure all your CRM servers have rewrite rules create and enable etc.).

[*** Update | 13/06/2014 ***] If you are using CRM 2013, see this article on how to use Action processes to get around this challenge.

Hope this helps!

Advertisements

8 thoughts on “Making Cross Domain AJAX calls from CRM Form JScript

  1. #2 is absolutely brilliant. I feel ashamed that I didn’t actually think of it.

    I have yet to test it, but if it works the way it should, it fixes a MAJOR issue for us.

    We’re on CRM 2013, with lots of custom entities with lookups to entities with lookups. The build in REST services only return data one level deep, so we’re having to create SQL views/stored procs, wrap them in our own web services, then call those to populate the UI. And of course, the main issue is that we lost ISV in 2013, so we had to create a separate web service site that generates a cross-domain error on AJAX.

    • It worked for us for sure!. One down side that annoyed me a little was that depending on how your servers/environment is structured, you add an additional component to your solution from a deployment perspective.

      It’ll also be interesting to evaluate what is the impact of the URL rewrite on the server’s performance.. Thinking out loud 🙂

  2. I tried this and it went into an endless loop which terminated the ADFS authentication with MSIS7042.I have proxy enabled for reverse proxy to work for me.
    For Example, I want to redirect https://crminternal.mydomain.com/ISV/GetData.aspx to https://isv.mydomain.com:444/GetData.aspx.
    It seems pretty straightforward and the new url is correct but I haven’t had any luck so far as fiddler shows it redirecting to
    Object moved
    Object moved to here.
    and then to:
    Object moved
    Object moved to here.
    and then back and forth in a loop until terminated. Any suggestions as to what might be wrong?

    • I’m curious to see your rewriting rule(s).. Can you share the methodology you used to set it up? Are you on 2011 or 2013?

      • I just tried a simple rewrite from https://crminternal.mydomain.com/isv/ajaxpage.aspx to https://crmisv.mydomain.com:444/ajaxpage.aspx (as an example). The rewriting worked but my single sign on code made it go into the authentication redirect loop. I had to give it up and, instead, created a dummy preauthentication.aspx page, which simply closes itself, on the isv site and opened that in a new small browser window. The code waits for that to close and then accesses the ajax url.

      • Ok, that makes sense. Glad you have it working!

        I was going to suggest if you are in CRM 2013 to use an action instead of URL rewriting. I have an upcoming post on how to do that. If you are in 2011, disregard this comment.

        Cheers

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s