Redirect web services at run time
Well, this is not an advanced topic or anything like it. Actually it's a very simple thing to do. However, every so often I run into someone who is developing and consuming web services and don't know about this.
So here comes a typical scenario: you are developing a multi-tier application and some interactions between your tiers are done through web services. You develop the web service on your dev machine, you then consume it from an application also on your local machine. To do this you add a web reference to your local web service and everything just works. However, you are faced with the following problem (the common question that I'm getting a lot lately): when in production my tiers won't be in the same machine. I don't know the ip of the web services machine so, how can I prepare my application so it can work in that scenario? And, if the machine changes after some time, how can I update my application's web reference without recompiling?
Other typical scenario would be using the same web service but having to make a decision at runtime about the specific machine that will be used.
Ok....this is very simple and actually you should use this practice even in a situation that you perfectly control all your application deployment and maintenance. So… how to do it?
Let's get one thing straight right from the start: when you add a web reference you're not binding your client application to that specific URL. This operation is only intended to get the wsdl and creating the proxy class so you can get all the method and data type information you need to use the web service. After this, what you actually do is a soap request that can be directed anywhere.
Let's start by creating an entrance in web.config that configures your web service endpoint (meaning the URL). To do this, add the following section to your web.config file:
<configuration>
<appSettings>
<add key="WebServicesUrl" value="http://x.x.x.x/Services/books.asmx" />
</appSettings>
</configuration>
You should use the appSettings section to set some values that are used within your application and subject to change overtime. This way, you can change them at runtime because they are read using the ConfigurationSettings.AppSettings property as we shall see.
So, if you look at the code of your proxy class, you see that there is a property called 'Url'. Yes, that's just it. To find this you have to set the option in Solution Explorer to 'Show All Files', expand your web reference, expand Reference.map, and inside Reference.cs you'll find something like this:
public Books() {
this.Url = "http://x.x.x.x/Services/books.asmx";
}
We see that in the constructor of the proxy class a reference is set to specify where the web service is located.
So, you see that an easy way to do this is just to replace this code with the following lines:
public Books() {
this.Url = ConfigurationSettings.AppSettings["WebServicesUrl"]
}
This way, if the web service changes location you can simply change the web.config file to update your application on-the-fly. Because this property is also publicly available, you can also change it before invoking the web service methods.
So, like I said...it's pretty simple...no rocket science...but hopefully it will help some of you.