I just saw Andy Beaulieu’s post about dynamically chaging the endpoint for a WCF service. It’s a good post, I just wanted to share how I have solved this problem in my current project.
The problem with Andy’s solution is that it not that dynamic.
- What if the schema change (https)?
- What if the port change in the final distination environment, so you can’t use the “Use specific port” like in VS?
- What if the path/url for the WCF service is different at the distination environment?
These are the problems that Andy’s solution don’t solve and I actually have in my current project. Well, I have some of them, but my solution here should solve all of the above.
First, besides my solution is able to change the url/endpoint dynamically, it’s also able (or actually required) to take the path to the WCF in as a InitParameter. Please note, that we are taking a relative path from the root here. Which means something like /Services/PeopleService.svc. Somethings that start with a /. This tells the browser that we want to start from the root of the current domain.
So besides solving the problems stated above, my solution also shows how you can send in the relative path for the service as a InitParameter. It’s not rocket science, but good to know.
Let’s start in App.cs
private void Application_Startup(object sender, StartupEventArgs e) { //Insert InitParams into Global Resources foreach (string key in e.InitParams.Keys) { this.Resources.Add(key, e.InitParams[key]); } this.RootVisual = new Page(); }
We start out by taking all the potential InitParams and put them into the global Resources for the application. You could also just pass the Dictionary to the Page class, but I’ll do it like this in this case as I need to access the resources from different places in the application.
If we look in the web project in the HTML we see how and what we pass in here: Default.aspx
<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/Dummy_WCF_Application.xap" MinimumVersion="2.0.31005.0" Width="100%" Height="100%" InitParameters="DummyServicePath=/Services/DummyWCFService.svc" />
Ok, so now we have the initparams inside our silverlight application inside the resources. Let’s use it to set the endpoint of our application. This can be done anywhere you like, in my case I just have a DataProvider class and this is where my code is: DataProvider.cs
I applogize up front for the code looking a little wierd. I had to press the code together and on new lines where it isn’t logical or correct. It’s only for the code to be able to fit to the width of the page here.
public class DataProvider { public event EventHandler<DataResult> GetDataCompleted; private WCFServiceClassName service; private const string DummyServicePathKeyName = "DummyServicePath"; public DataProvider() { BasicHttpBinding basicHttpBinding = new BasicHttpBinding(); EndpointAddress endpointAddress; if (App.Current.Resources.Contains(DummyServicePathKeyName ) && !String.IsNullOrEmpty
(App.Current.Resources[DummyServicePathKeyName ] as string)) { string relativePath =
App.Current.Resources[DummyServicePathKeyName ] as string; string completePath = App.Current.Host.Source.Scheme
+ "://" + App.Current.Host.Source.Host + ":" + App.Current.Host.Source.Port + relativePath; endpointAddress = new EndpointAddress(completePath); service = new ChannelFactory<WCFServiceClassName>
(basicHttpBinding, endpointAddress).CreateChannel(); } else throw new Exception("Missing init param named: \"" + MapServicePathKeyName
+ "\" which is a relative Url to the WCF service."); } }
This is not a completely working sample, as I have removed curtain things to keep it simple. The most important part if the code above is actually this:
string relativePath = App.Current.Resources[DummyServicePathKeyName] as string; string completePath = App.Current.Host.Source.Scheme
+ "://" + App.Current.Host.Source.Host + ":" + App.Current.Host.Source.Port + relativePath;
Here we create the actual complete url used to access to WCF service with.
App.Current.Host.Source.Scheme: Returns https or http
App.Current.Host.Source.Host: Returns the host ex. “laumania.net” or “silverlight.laumania.net” if you were on a subdomain.
App.Current.Host.Source.Port: Returns the port number, typically 80, but could be anything actually. If the scheme were https the port would normally be 443 etc.
The code above would generate a url, if ran on this actual page:
http://laumania.net:80/Services/DummyWCFService.svc (The link wouldn’t work here, as I don’t have that service :) )
Now you should be able to make your own WCF service that you can change the endpoint of, in code.
Please let me say that Andy’s solution isn’t wrong and it will work just fine in most scenarios, it’s just different than mine, so I wanted to share this solution too. Hope you find it usefull, maybe in combination with Andy’s?
Enjoy!