Click here to Skip to main content
15,867,594 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I know this sounds ridiculous. Maybe some of you have encountered something like I have here. I have an old ASMX web service that's run on a single server for several years. Recently that server has been replaced with 2 with a load balancer (Windows Server 2012 R2). The way the Infrastructure team likes to configure web services is to put the SSL certificate on the load balancer and then strip the security before passing to whichever server is selected. So, on each of the web servers, the site is actually setup as HTTP.

The problem is that since this is a standard ASMX site, using .NET (4), the WSDL is generated by .NET. It knows the site is hosted as HTTP and not HTTPS on the server, so when it generates the WSDL, the endpoints section is also HTTP. Since the site name resolves to the load balancer then if you extract the endpoint from the WSDL, it tries to go to HTTP instead of HTTPS and of course fails. This doesn't seem to happen if you consume the web service using the traditional tools in Visual Studio. I guess when it builds the reference it must just use the WSDL URL which is secured and ignores the endpoints configured in the service. However, if you launch the web service dynamically (there are tons of examples online how to do this), without consuming it, you usually start with something like this:
System.Net.WebClient client = new System.Net.WebClient();
System.IO.Stream stream = client.OpenRead("http://localhost/webservicedemo/webservice.asmx?wsdl");
// Get a WSDL file describing a service.
ServiceDescription description = ServiceDescription.Read(stream);

The ServiceDescription you read in and use to launch dynamically a bit further down will use those endpoints.

The simplest way to see this without writing a lot of code was to access the web service in a browser, choose the method, type in the simple values, and hit Invoke. This promptly used the WSDL to open a new window calling the web service... as HTTP (which of course fails).

So, my question... Can I override the generated WSDL so that when the WSDL is requested, the endpoint section says to use HTTPS instead of HTTP, even though the site is technically configured on each server as HTTP?
Posted

If anyone ever rambling through the CodeProject forums in desperation for something like this, the answer is the SoapExtensionReflector Class. It does the trick by allowing you to override the WSDL through reflection on the fly. I found this after pouring through Google for a week. The link is here: http://blogs.msdn.com/b/kaevans/archive/2005/11/16/493496.aspx[^]

In case that ever goes away, just do this:

XML
using System;
using System.Web.Services.Description;

namespace Msdn.Web.Services.Samples
{
    public class HttpsReflector : SoapExtensionReflector
    {
        public override void ReflectMethod()
        {
            //no-op
        }

        public override void ReflectDescription()
        {
            ServiceDescription description = ReflectionContext.ServiceDescription;
            foreach (Service service in description.Services)
            {
                foreach (Port port in service.Ports)
                {
                    foreach (ServiceDescriptionFormatExtension extension in port.Extensions)
                    {
                        SoapAddressBinding binding = extension as SoapAddressBinding;
                        if (null != binding)
                        {
                            binding.Location = binding.Location.Replace("http://", "https://");
                        }
                    }
                }
            }
        }
    }
}
Using Visual Studio 2005, I created the class above and put it in the App_Code folder in my web site.  Then, in the web.config file, I added the following section within configuration/system.web:

<webServices>

<soapExtensionReflectorTypes>

<add type="Msdn.Web.Services.Samples.HttpsReflector, App_code"/>

</soapExtensionReflectorTypes>

</webServices>
 
Share this answer
 
Matt Philmon, your answer is great.
but what if i have some users that work with http and some with https.
the ReflectDescription will occur only once, is there a way to override this?
 
Share this answer
 
If it's all in the same environment... then I don't know. I deploy this to a dev, test, stage, and production environment. Therefore, we always push out the bit of code for the reflector (in the App_Code folder). If I don't want it used (like in the dev environment which isn't secured), I just leave that bit out of the web.config.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900