Thursday, December 24, 2015

How to Find Your CRM Online IP Address

I was recently asked to build a CRM extension to submit Opportunity records to an external API. We decided to build this as an asynchronous custom workflow activity so it would trigger upon Create, but also could be called manually. Behind the scenes I use C# to make an HTTPWebRequest, using values from the Opportunity record.  So, the user would create an Opportunity record, then run the workflow which gathers data from the Opportunity and sends it the the external API for processing.

Making a web call from CRM is generally straightforward, but this case was a little different - the external API required us to register our IP address with them for authentication, and then use that IP address in all subsequent calls.  At first I though finding CRM's IP address would be easy - I'd just use one of the many IP lookup sites out there and plug in the web url (e.g., "https://myorg.crm.dynamics.com"), and we'd be done.  But it's not that straightforward (it never is).  

CRM uses separate servers for asynchronous processes (asynchronous workflows included).  So while your front end application server ("https://myorg.crm.dynamics.com") has one IP address, the custom workflow activity will come from a different one.  How do you find the IP address of your asynchronous server?  After trying many methods, I used the code below to do this.  This code makes a WebRequest call to a site called "ipify", which tells you your IP address from programmatic calls.  It then reads the response (the IP Address) into an Output argument which the CRM workflow puts into a field on the Opportunity record.  

There may be easier ways to find your IP address, but I did it this way because of the limited access we have to server level information in the cloud.  I tried several DNS property calls and got security errors.  So the last way I could think was to record on the receiving end of the call (thanks https://www.ipify.org/ !!!).  

Disclaimer: CRM Online uses several IP ranges which you can find here.  While this code will tell your current IP address at the time of the call, your IP address can and will change unexpectedly.  That said, this will tell you want range you're in, and I hope this code is helpful to someone out there because I spent many hours before finally figuring this out.  

string tmaurl = "https://api.ipify.org";
WebRequest request = WebRequest.Create(tmaurl);                                    
WebResponse response = request.GetResponse();

WebHeaderCollection header = response.Headers;
using (var reader = new System.IO.StreamReader(response.GetResponseStream()))
{
    string responseText = reader.ReadToEnd();
    this.ServerMessage.Set(executionContext, responseText);
}

[Output("Server Message Output")]
public OutArgument<string> ServerMessage { get; set; }