At my current client, security is taken to a whole new level, which is a good thing. But as a result, sometimes there is more of a challenge to resolve issues you may not normally encounter. For example, I was tasked with writing a web service which would facilitate file transfers of documents and images from a web page (and Windows client), store them on a secured server, and serve them up to an authenticated user on the internet. To do so, we have to deal with proxy server issues and firewall issues.
After writing and testing the web service locally, I deployed it to our production server. Locally, it all worked fine. However, when I deployed the web portion of the application to our test server outside our intranet, the real fun began. The next several posts I will discuss the problems I encountered, and how I ultimately resolved the issue. Hopefully this will help any readers out there who have a similar issue, as well as become documentation for the process I used so I can later reference it.
The first issue I saw was the following error:
The <To> header must match the value of an incoming message's HTTP Request Url if the soap receiver does not have an actor name.
I'd love to give the person I found the solution at credit, but it's been such a long time I can't find the original document I used. I modified the solution to make it a little more "generic" so that the web service can be moved without requiring a recompile of the application.
First, you'll need to locate the Reference.cs file for the web service reference(for C# users. Reference.vb is the similar file for VB.Net, but all code here will be in C#). In this file, add the following reference:
using Microsoft.Web.Services2.Addressing;
Next, locate the consructor for the WSE portion of the Reference.cs. In this case, mine will be FileServiceWse(). Here's the code you'll need to replace the this.Url reference already in there.
public FileServiceWse()
{
//these two setting are the <TO> and Response URLs. For example, in our case the response was
//coming back with the redirected port appended to the url.
//The Web service <TO> looked like https://mycompany.com/FileService/FileService.asmx
//but the response was https://mycompany.com:1234/FileService/FileService.asmx
//The endpointreference call to the Destination tells the application to expect the return url to look differently than the
//<TO> reference
string urlSetting = System.Configuration.ConfigurationSettings.AppSettings["FileService"];
string urlReturnSetting = System.Configuration.ConfigurationSettings.AppSettings["FileService.ReturnURL"];
if ((urlSetting != null) && (urlReturnSetting != null))
{
Uri sourceUri = new Uri(urlSetting);
Uri returnUri = new Uri(urlReturnSetting);
this.Destination = new EndpointReference(sourceUri, returnUri);
}
else
{
if ((urlSetting != null))
{
this.Url = string.Concat(urlSetting, "");
}
else
{
//this is the default URL of the file service if all else fails.
this.Url = "https://mycompany.com/FileService/FileService.asmx";
}
}
}
What this code does is set the Destination property (if the FileService and FileService.ReturnURL settings are placed in the web.config file) to expect a different response than the requested web service URL. In our case, since our request was going through a firewall which remapped the ports, we had a port attached to the url for our web service which triggered this error.
The code also has failover. If I forget to make the settings, it will try the original URL reference. In my case the call won't work, but I believe in at least attempting to code some failover when human error can take place in moving files, etc.
But this only solved one of the many challenges I encountered in deploying this web service. Stay tuned for the next resolution to tricky WSE issues!