Referencing a web service using a non-standard port in Visual Studio .NET 2003
Twice now I’ve come across this issue, so I’m documenting it here.
Adding a web service reference that doesn’t use the standard port (80) through Visual Studio .NET 2003’s “Add Web Reference” interface will cause you all kinds of pain. The issue is that although you can include a port number when specifying the URL for the web service, the underlying tools that generate the proxy classes and the .disco file will strip it out without telling you.
So when I add a reference to “http://www.webserviceserver.com:5332/service.asmx”, the end result in the .disco and .cs files is a reference to “http://www.webserviceserver.com/service.asmx” which obviously doesn’t work.
So here’s the fix: (if someone knows a better one, please post it in the comments!)
- Add the web reference, but when it times out and fails, instruct VS.NET to continue processing the files. This will create the Reference.cs file (which will just contain a namespace), Reference.map, and the .disco file.
- Edit the .disco file in a text editor (VS.NET will work great), and alter the following:
- In the <contractRef> element, edit the “ref” and “docRef” attributes to include the correct port number
- In the <soap> element, edit the “address” element to include the correct port number
- Open a Visual Studio command prompt window (for my default install, I can get to this from “Start -> All Programs -> Microsoft Visual Studio .NET 2003 -> Visual Studio .NET Tools -> Visual Studio .NET 2003 Command Prompt”). This will open a command prompt with all the required paths set to access the Visual Studio .NET command-line tools.
- Navigate to your project folder, and go into the Web References\[webservice] subfolder. Use wsdl.exe to create the proxy class for use in Visual Studio:
- Type “wsdl.exe [full web service URL - with port number]” — This will generate a .cs file that has the same name as your .disco file (hopefully). Regardless, just look for the new .cs file that exists in the folder.
- If you’re interested in the wsdl.exe tool, type “wsdl.exe” at the command line to see the options available. If you’re implementing your web service properly, you should be familiar with this tool as you can use it to create your web service “contract-first”. Check out the blogs at pluralsight.com for more info on that important topic.
- Open Reference.cs and the newly created class file from step 4 in an editor (like VS.NET). You should notice that the Reference.cs file contains only the namespace keyword (along with a namespace identifier) and nothing else. Copy the “using” statements from the wsdl.exe generated class file above the “namespace [namespace id]” line in Reference.cs. Then copy the entire implementation portion of the web service proxy code from the generated class file into Reference.cs, inside the namespace declaration.
- [ALTERNATE STEP 5] Simply open the generated class file and wrap the entire thing (minus the “using” statements) in a namespace declaration. Then add the new .cs file into your project. Note that this won’t show up under “Web References”, however.
- Finally, edit the final file (depending if you did step 5 or 6), find the constructor for the main class (the class that derives from System.Web.Services.Protocols.SoapHttpClientProtocol), and change the “this.Url” property assignment line of code to point to the correct URL. This should just mean adding the port number into the URL string.
And there you have it. A pain in the butt? Yes. Which reminds me, attempt to refrain from right-clicking on the web reference and choosing “Update Web Reference” as this will overwrite your files (if you select “Continue” when it times out instead of choosing “Skip”). If you do need to update the web reference, you will have to repeat all these steps. Generate the proxy from the WSDL and copy the code into the Reference.cs file. Blech.
Another note is that using the disco tool doesn’t fare any better than the IDE (probably because the IDE uses the tool indirectly). It will also fail because it attempts to access the web service on port 80.
I apologize for the lack of screenshots, I am still trying to figure out the best way to host pictures on here.