HTTP.SYS integration is one of the features I was expecting to find in WSE 3.0. Hosting ASMX in your own process just isn't easy enough with HttpListener (as you know if you read
my article on the subject). Basically, I want the WCF-like ability to host HTTP endpoints in any process via SoapReceivers.Add:
SoapReceivers.Add("http://localhost:8080/math/",
typeof(MathService));
I asked the WSE team about it when 3.0 was first becoming public but at that point it was too late; wasn't on the feature list. I didn't think about it when I wrote my
wish list. Oh well.
So I thought through how it could be done through the WSE extensibility architecture, specifically as a custom transport, and decided to write it once I found some time. Many months passed and I finally found some time. You'll find links to download the code + samples below.
Here's a quick snapshot of how it works. Assume the following ASMX 2.0 code:
[WebServiceBinding(Name="MathServiceBinding",
Namespace="http://example.org/math",
ConformsTo = WsiProfiles.BasicProfile1_1,
EmitConformanceClaims = true)]
public interface IMathService
{
[WebMethod]
double Add(double x, double y);
[WebMethod]
double Subtract(double x, double y);
[WebMethod]
double Multiply(double x, double y);
[WebMethod]
double Divide(double x, double y);
[WebMethod]
double Mod(double x, double y);
}
[WebService(Name="MathService",
Namespace="http://example.org/math")]
public class MathService : IMathService
{
#region IMathService Members
public double Add(double x, double y)
{
return x + y;
}
...
You can host this class in IIS/ASP.NET using the following .asmx file:
<%@ WebService Language="C#" Class="ServiceLibrary.MathService" %>
But with this custom HTTP.SYS transport, you can also write a console application, NT service, or a Windows app to host the same class using SoapRecievers. Here's a sample console app:
class Program
{
static void Main(string[] args)
{
try
{
SoapReceivers.Add("http://localhost:8080/math/",
typeof(MathService));
Console.WriteLine("MathService is listening.");
Console.WriteLine("Press [Enter] to terminate.");
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
All you have to do configuration-wise is tell WSE to use your custom HTTP transport instead of the built-in one for the "http" protocol scheme. You do this with the following configuration elements:
<configuration>
...
<microsoft.web.services3>
<messaging>
<transports>
<add scheme="http"
type="Skonnard.Samples.HttpSys.HttpSysTransport,
Skonnard.Samples.HttpSys"/>
</transports>
</messaging>
</microsoft.web.services3>
</configuration>
And you'll need a reference to Skonnard.Samples.HttpSys.dll in the hosting application so it can find it at runtime. Then, you're ready to go.
Clients don't need to use the adapter. They can simply use the built-in HTTP transport on the consuming side. Just update the proxy address before invoking methods as shown here:
MathServiceWse svc = new MathServiceWse();
svc.Destination = new EndpointReference(
new Uri("http://localhost:8080/math/"));
The proxy class, MathServiceWse, was generated using wsdl.exe against the IIS/ASP.NET hosted endpoint.
Update: the following bits run on RTM, and they support HTTP GET requests for WSDL. Simply browse to the exact same address supplied in the call to SoapReceivers.Add. When supplying an ASMX class to SoapReceivers.Add, you must wrap the type in an instance of WsdlEnabledReceiver in order for the WSDL generation to work properly. See the sample code for an example.
Downloads
Posted
Oct 14 2005, 02:54 PM
by
Aaron Skonnard