locked
AJAX calls to a custom web Application are denied RRS feed

  • Question

  • Hello Everyone,

    I've never worked with CRM 4.0 but it's issues like this one that make me miss it...

    Let me explain my situation. I've written a web application which connects to our deployment of CRM 2011, performs some simple queries, builds XML for a menu and returns it as a response. The application works quite well however the fact that it must be hosted as a separate website is causing some serious problems thanks to Same Origin Policy.

    For example, our deployment of dynamics lives here at https://sample.com/org/ and my application can be accessed at http://sample.com:8080/gen/ Which according to Same Origin Policy is illegal, and sure enough I get an "Access Denied" error when I try sending a POST request to the app.

    So my question is this. How are you supposed to interact with your web application if it cannot live within the Dynamics site itself? ex ISV folder in CRM 4.0. Does any one know a way around this, or am I doing wrong entirely?

    If you have any idea or suggestion, please let me know. I will really appreciate it.


    Kirk Roerig

    Tuesday, June 19, 2012 1:32 PM

Answers

  • Hi Kirk,

    Your workaround actually is a valid one - and in use quite a bit today in various 'mash-up' APIs to get around the cross domain issue. A good example is widgets where you want to add some content to your site from some other source. Another example is the google tracking script that needs to post off to google.com. 

    As for the option points:

    2. You would need to host your webservice as a subdomain of sample.com - and map using host headers in IIS (rather than using a different port)

    3/4 - You simply map a virtual directory in IIS under the ISV folder and add it as an IIS application if you want different security/app pool settings.

    5 - No, not as such - you would have to have the Silverlight XAP available on the HTML page and accessible from the ribbon javascript. This would work for forms, but it wouldn't work for grid ribbons (I thought you were using CRM 4 by the way!!)

    hth,

    Scott


    Scott Durow
    Read my blog: www.develop1.net/public
    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    • Marked as answer by Kirk Roerig Thursday, June 21, 2012 5:35 PM
    Thursday, June 21, 2012 5:23 PM
    Answerer

All replies

  • Hi Kirk,

    As you've discovered - it's IE's security features that stop cross-domain access. They are there for good reason, but can be real pain as well!

    A few options:

    1. The quickest work around is to add both sites to your trusted sites in IE and enable 'Access data sources across domains'. If you can control the client, you could deploy this via Group Policy in Active Directory.

    2. Another option is to ensure that the top-level domain is always the same, and use document.domain ='topleveldomain.com' on the client (see http://fettig.net/weblog/2005/11/28/how-to-make-xmlhttprequest-connections-to-another-server-in-your-domain/). This then lowers the origin domain so that any calls to subdomains of that domain will now be allowed.

    3. If you are using CRM 4 - you could deploy your web application to the ISV folder - but this is going to be a problem on upgrades.

    4. You could built a proxy service and deploy that to your ISV folder (e.g. http://netproxy.codeplex.com/) - but again with CRM 2011, you'll need to re-engineer it to use PlugIns.

    5. You could use Silverlight and add a clientaccesspolicy.xml to the root of the service you are calling - this then allows cross domain access.

    hth,

    Scott


    Scott Durow
    Read my blog: www.develop1.net/public
    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    Tuesday, June 19, 2012 6:52 PM
    Answerer
  • Hi Scott, 

    I apologize for the delayed response, and thanks for your reply.

    You had some great suggestions, but I'm in a bit of a tight spot and I don't believe I can use many of them.

    Here's why

    1. This would be a great solution. However not all of our users are on terminal machines, ie group policy couldn't reach all our users.
    2. Correct me if I'm wrong, but wouldn't this require me to host it from within the Dynamics site directory? Since navigating to https://sample.com/ will bring you directly to our Dynamics page.
    3. I tried deploying to the ISV folder, but I honestly didn't know exactly how. I tried deploying it as a standard application in IIS which didn't work. I'm assuming you must somehow associate the application with a particular org?
    4. Again, I'm unfamiliar with deployment to the ISV folder.
    5. This last suggestion would be a great one too and I may attempt it. Is it possible to invoke a silverlight component from the ribbon?

    I actually came up with a solution, but I feel like it's an awful one. I wrote a function which essentially creates a Script tag, then points the src property to my aspx page which resides athttp://sample.com:8080/gen it also concatenates some parameters onto that url. I then defined a function for the Script tag's onload event, which essentially invokes the callback which was intended for an AJAX request. Here's the code for that function.

              function CrossDomainPOST(url, params, success){

                                   var th = document.getElementsByTagName('head')[0];

                                   var s = document.createElement('script');

                                  

                                   s.src = url + params;

                                   s.onload = s.onreadystatechange = function(){

                                             success(crossDomainResponse);

                                             // clean up

                                             s.onload = s.onreadystatechange = null;

                                             th.removeChild(s);

                                             s = undefined;

                                             //delete crossDomainResponse;

                                   };

                                   th.appendChild(s);

              }

    Which would be called like so.

                                   var queryUrl = "http://sample.com:8080/gen/";

                                   var ctx = AMW.UI._getContext();

                                   var params = "?req=" + request + "&lang=" + ctx.getUserLcid();

                                  

                                   CrossDomainPOST(

                                             queryUrl,

                                             params,

                                             successCallback

                                   );

    Now here is where things start getting really bad. In my aspx page I had to add the following to get this hack to work.

                Response.Write("var crossDomainResponse = '"); // << new

                FlyoutGenerator.Generate(this);

                Response.Write("';"); // << new

                Response.ContentType = "text/javascript"; // << new

    So I'm letting this script tag interpret the text, which would normally be sent via AJAX, as a JavaScript string declaration. So to retrieve the "response" I simply retrieve the value of the variable crossDomainResponse. However, since IE enjoys making things more fun than they need to be I also have to call delete crossDomainResponse; from my callback. If I don't, next time a request is sent the response will not overwrite the previous value of crossDomainResponse.

    So in my mind this solution is terrible, or at the very least inelegant. It doesn't seem to perform too badly but I'm not sure how it will handle a high volume of traffic.

    Do you have any suggestions from a design stand point?

    Thanks for the help.


    Kirk Roerig

    Thursday, June 21, 2012 2:52 PM
  • Hi Kirk,

    Your workaround actually is a valid one - and in use quite a bit today in various 'mash-up' APIs to get around the cross domain issue. A good example is widgets where you want to add some content to your site from some other source. Another example is the google tracking script that needs to post off to google.com. 

    As for the option points:

    2. You would need to host your webservice as a subdomain of sample.com - and map using host headers in IIS (rather than using a different port)

    3/4 - You simply map a virtual directory in IIS under the ISV folder and add it as an IIS application if you want different security/app pool settings.

    5 - No, not as such - you would have to have the Silverlight XAP available on the HTML page and accessible from the ribbon javascript. This would work for forms, but it wouldn't work for grid ribbons (I thought you were using CRM 4 by the way!!)

    hth,

    Scott


    Scott Durow
    Read my blog: www.develop1.net/public
    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    • Marked as answer by Kirk Roerig Thursday, June 21, 2012 5:35 PM
    Thursday, June 21, 2012 5:23 PM
    Answerer
  • Hey Scott,

    No I've been using CRM 2011 sorry about the confusion! I was just wishing I were using 4.0 (since it seems to be better suited for the task im trying to accomplish)

    Excellent I think this will help. I'm going to give suggestions 2 - 4 another shot.

    Thanks for the assistance!


    Kirk Roerig

    Thursday, June 21, 2012 5:35 PM
  • Hi Kirk,

    No problem - let us know how you get on.

    Scott


    Scott Durow
    Read my blog: www.develop1.net/public
    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    Thursday, June 21, 2012 5:52 PM
    Answerer
  • Hey Scott,

    I tried those suggestions again without much success. I'm not sure why they won't work for me. Anyway I did some timing and performance testing on my scripts using the work around I described above and the results were surprisingly good (< 0.5sec/request). I'm just going to use the work around.

    Thanks for your help.


    Kirk Roerig

    Friday, June 22, 2012 1:04 PM