Introduction
This article describes content based web service routing using WSE 3.0. We can use webservice routing for load balancing or to hide internal web service from external world.
Background
A background knowledge of ASP.NET 2.0, C#, WebService & WSE 3.0 is required.
Using the Code
In this sample application, I have three webservices:
CBRoutingService
PremiumService
StandardService
and client web application.
As per the above figure, client web application will consume CBRoutingService
. SoapHeader
will have user id stored in it. CBRoutingService
will route the request to the StandardService
or PremiumService
based on the user id. If user id is less than 100, then it will route the request to the StandardService
otherwise it will route it to PremiumService
. So this is simple routing application which we will build.
Let’s do the following steps in VS 2005:
- Create Standard service
- Create Premium service
- Create & configure Routing service
- Create & configure client website
1) Create Standard Service
To create the StandardService
as ASP.NET Web Service. Go to File -> New -> Web Site -> ASP.NET Web Service. Give the location as http://localhost/StandardService. Remove default Service.asmx and Service.cs files and add new web service StandardService.asmx. We will add new web method called GetServiceString
in StandardService.cs as below:
[SoapHeader("authheader", Direction = SoapHeaderDirection.InOut)]
[WebMethod]
public string GetServiceString()
{
return "This is Standard Service Customer";
}
We also have to add AuthHeader
class in StandardService.cs for passing user id in the SoapHeader
and write SoapHeader
attribute above GetServiceString
web method.
public class AuthHeader : SoapHeader
{
public string UserId;
}
2) Create Premium Service
Create PremiumService
in the same way, just give the location as http://localhost/PremiumService and web service name as PremiumService.asmx. We also need to change return string
in GetServiceString
web method of PremiumService
.
[WebMethod]
public string GetServiceString()
{
return "This is Premium Service Customer";
}
3) Create and Configure Routing Service
Now we will create routing service by same way with http://localhost/CBRouter as location. Add new web service and give name as CBRoutingService.asmx.
Keep the default setting as it is for now. We will change it latter.
Now we need to have handler which will intercept the request to CBRoutingService
. So we need to add class library project for that by right click on solution -> Add -> New Project and select Class Library template. Now add new class called CBRoutingHandler
.
Add the following references to your project:
Microsoft.Web.Services3
System.Web.Service
We have to derived Microsoft.Web.Services3.Messaging.SoapHttpRouter in CBRoutingHandler
class and implement ProcessRequestMessage method to intercept the web service request.
using System;
using System.Configuration;
using System.Xml;
using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Messaging;
namespace CBRouter
{
public class CBRoutingHandler : Microsoft.Web.Services3.Messaging.SoapHttpRouter
{
static readonly string PremiumNamespaceUri =
"http://schemas.contoso.com/cbr";
static readonly string PremiumHeaderName = "authheader";
Uri premiumServiceUri;
Uri standardServiceUri;
public CBRoutingHandler()
{
string premiumServiceUrl =
"http://localhost/PremiumService/PremiumService.asmx";
string standardServiceUrl =
"http://localhost/StandardService/StandardService.asmx";
if (premiumServiceUrl == null || premiumServiceUrl.Length == 0)
{
throw new ConfigurationException("There was no \"Premium Web Service\"
entry in the <appsettings /> section of the router's configuration file.");
}
this.premiumServiceUri = new Uri(premiumServiceUrl);
this.standardServiceUri = new Uri(standardServiceUrl);
}
protected override Uri ProcessRequestMessage(SoapEnvelope message)
{
if (!string.IsNullOrEmpty(message.Header.InnerText))
{
if (Convert.ToInt32(message.Header.InnerText) > 100)
{
return premiumServiceUri;
}
}
return standardServiceUri;
}
}
}
Add CBRoutingHandler
project reference in CBRouter
web service.
Now you have to enable WSE based routing in CBRoutingService
. To do this, follow the below steps:
- In Visual Studio 2005, right-click the
CBRouter
project and select WSE Settings 3.0. - On the General tab, select the checkboxes for the following options:
- Enable this project for Web Services Enhancements
- Enable Microsoft Web Services Enhancement SOAP Protocol Factory
- Click OK
Now click on Routing tab. Click Add to add routing handlers and give CBRoutingHandler
information as below, type = “CBRouter.CBRoutingHandler, CBRouter
” Path=” CBRoutingService.asmx” and Verb=”POST
”.
You can see the changes in web.config file. It has added httphandlers
in web.config.
Now we have to give WSDL to the client so that they can generate the proxy and consume it.
Save WSDL of StandardService
or PremiumService
as .wsdl file. Open this file in editor and change the URL to CBRoutingService
URL as below:
<wsdl:service name="StandardService">
<wsdl:port name="StandardServiceSoap" binding="tns:StandardServiceSoap">
<soap:address location="http://localhost/CBRouter/CBRoutingService.asmx" />
</wsdl:port>
<wsdl:port name="StandardServiceSoap12" binding="tns:StandardServiceSoap12">
<soap12:address location="http://localhost/CBRouter/CBRoutingService.asmx" />
</wsdl:port>
</wsdl:service>
So now we have .wsdl file, but it points to CBRouter
.
4) Create and Configure Client Website
Now create client web site. Here, do not add web reference for StandardService
instead create proxy class with wsdl.exe using modified WSDL file.
Open .net command prompt and give following command:
Wsdl /out:C:/StandardServiceProxy.cs C:/Standardservice.wsdl
Now add this StandardServiceProxy.cs to your website project.
Add textbox and button on the page. On button click, we will pass the textbox value to web service call.
protected void Button1_Click(object sender, EventArgs e)
{
try
{
StandardService standardSer = new StandardService();
AuthHeader auth = new AuthHeader();
auth.UserId = txtUserId.Text;
standardSer.AuthHeaderValue = auth;
string str = standardSer.GetServiceString();
lbl.Text = str;
}
catch (Exception ex)
{
lbl.Text = ex.Message;
}
}
Now run the website and enter any user id. You will get the response based on user id as below:
Thus, you can use WSE to route the web service call to other webservice.
Notes
If you want to make StandardService
& PremiumService
as WSE enabled services, then you have to apply SoapActor
attribute above the service class name.
using Microsoft.Web.Services3.Messaging;
[SoapActor("*")]
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class StandardService : System.Web.Services.WebService
{
SoapActor
attribute indicates that this web service can handle routed messages, which is not originally requested to it. ‘*
’ means any service can route the messages to this webservice
. You can give router service’s URL to indicate service will handle routed message from a particular URL.
History
- 27th August 2010: Initial post