Wednesday, May 30, 2012

Why and How to use relative path in CRM2011 JavaScript

As CRM developers, we need to use the paths of the URLs, web services and other web resources in JavaScript code. I am talking about CRM URLs for e.g. we will use the following URLs to work with  REST(OData) organization data service

https://hp7.crm5.dynamics.com/xrmservices/2011/organizationdata.svc/ (CRM Online)
http://15.218.138.225/HPDECSStaging/xrmservices/2011/organizationdata.svc/ (On premise)

The highlighted part of the URLs represents the server and organization name of the CRM.
Instead of using the hard coded server name, we should use some generic function that can give us the server and  the organization name of the CRM. It will help to deploy the same code for different organizations, servers and deployments without making any changes.
Most of the Microsoft samples use Xrm.Page.context.getServerUrl() function to retrieve the server URL.I have written the following function to display message box with  the oData organization data service URL.

function test()
{
alert (Xrm.Page.context.getServerUrl() + "/xrmservices/2011/organizationdata.svc");
}
I executed this function on CRM Online and On-Premise deployments. I used the following URLs to start the CRM in the browser
I received the following results.

On CRMOnline, the function returned the following message.
image
This worked as expected.

On on-premise deployment, It returned the following message.
image
It returned the server name (aun.....23) instead of IP address(http://15.218.138.225/HPDECSStaging). I was using an IP address in the browser and it returned the server name. If I try to use this URL to retrieve any data, I will get an error message “access denied”. For this javascript to work properly, the server name part of URL in the browser has to match the server name part of the URL returned by Xrm.Page.context.getServerUrl() method. Xrm.Page.context.getServerUrl() returns the servername stored in the deployment manager. Have a look at the following screen shot.

image
So, if you are using the ip address or localhost in a browser to start the CRM and you are using Xrm.Page.context.getServerUrl() to generate the URL, then you will always get ”access denied” error in the JavaScript.
To overcome this problem, we should use the relative path as shown below
"/xrmservices/2011/organizationdata.svc"
There is one more catch to it. It will work with CRM Online as organization name is a part of the server URL(https://hp7.crm5.dynamics.com).
But to make it work with on-premise deployment, we need to add organization name in the relative path. something  like this
“/” + orgname + "/xrmservices/2011/organizationdata.svc".
You can read the organization name from the context by using Xrm.Page.context.getOrgUniqueName() method. Now we have two different URLs one for on premise and one online deployments. When we are writing JavaScript libraries, we want them to work with every deployment without making any changes. Here is the solution, use  Xrm.Page.context.prependOrgName() method . It will sort the organization name problem. Here is my new test function.
function test()
{
alert (Xrm.Page.context.prependOrgName("/xrmservices/2011/organizationdata.svc"));
}
The function will return “/xrmservices/2011/organizationdata.svc” for CRMOnline deployment. “orgname/xrmservices/2011/organizationdata.svc for On premise deployment. In short, use relative paths with  Xrm.Page.context.prependOrgName(), when working with the URLs in javascript. It will work with online, on premise and hopefully IFD. I did not test the code on IFD deployment.

15 comments:

  1. That's such a beautiful blog as usual. Plz keep the good stuff.

    BTW I tested prependOrgName method against IFD and worked exactly as CRM Online. Your above suggestion should work under IFD then.

    Regards,

    ReplyDelete
  2. Thanks for the feedback and the testing it on IFD mate

    ReplyDelete
  3. Microsoft Dynamics CRM training will help you manage and prioritize your business goals, customize.we teach MS Dynamics CRM training and class available at Hyderabad.

    ReplyDelete
  4. what about if the CRM has different url for organization data like in ADFS

    ReplyDelete
  5. As it is a relative path, it should not matter. If you access it from outside the network, it should will pick up external IFD URL and internal url for if you access it inside the network

    ReplyDelete
    Replies
    1. What is the result of prependOrgName for ADFS?
      Does it work like Online or Active Directory?
      Because if it is working like Active Directory for example https://organization.crm.com/organization/xrmservices/2011/organizationdata.svc
      While in ADFS, it has url https://organization.crm.com/xrmservices/2011/organizationdata.svc
      without the organization.

      Delete
    2. The function is smart enough to check what type of installation it is. For e.g for online it won't add the orgname after the server name.
      Anyway I ll check it again and come back to you.

      Delete
  6. Awesome post!, it has resolved my "Access Denied" issue in Jscript.

    Much appreciated, keep up the great posts!

    ReplyDelete
    Replies
    1. thank you very much, after wasting 5 hours I didn't realize this tiny but invisible problem, I was accessing my crm as http: localhost/crmorg , I was changing my server configuration over and over, rewriting code, and so on, thank you very very much Amreek. the best answer and the simplest answer.

      Delete
  7. Thank you very much. The content of this post is what I have been looking for since yesterday.

    The issue that I had was that my custom modal Dialog works properly when using the internal link but failed when using the external link. And then I found this and did the change and voila - it is now working either way.

    Again, thank you. I appreciate it very much.

    ReplyDelete
  8. Thank you very much. The content is very good.

    ReplyDelete