Web Services Development in a Class Library Project
In this article you will find the detailed explanation of the creation of a Web Service in a Class Library project.
Intro
Some time ago I’ve come across a task to create a plug-in based system. One of the peculiarities was that each plug-in (dll) in the system had to be capable of hosting web-services. This problem was completely new to me, and my search on the Web gave no results. So I decided to sit down and think and finally found what seemed to me quite an elegant solution of the problem.
The .asmx HTTP Handler
My first step was to find the Web.Config file which is located in %windir%\Microsoft.NET\Framework\v2.0.50727\CONFIG and examine the following entry in the <httpHandlers> section:
<add path="*.asmx" verb="*" type="System.Web.Services.Protocols.WebServiceHandlerFactory, System.Web.Services, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" validate="False" />
All I needed to find out was that WebServiceHandlerFactory is responsible for building and returning an IHttpHandler in the GetHandler of the IHttpHandlerFactory, which I did using Reflector.
The Creation of the WebServiceBase Class
Further I acted as follows:
First of all I created a
new Class Library project. Within the project I created a new
class named
WebServiceBase
which will be the class for the
Web Services.
Being an abstract class, this
class could be anywhere. Here is the definition of the class:
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Reflection
Public MustInherit Class WebServiceBase
Inherits WebService
Implements IHttpHandlerFactory
Private Shared wshf As New WebServiceHandlerFactory
Private Shared coreGetHandlerMethod As MethodInfo = GetType(WebServiceHandlerFactory).GetMethod("CoreGetHandler", _
BindingFlags.Instance Or BindingFlags.NonPublic)
Public Function GetHandler(ByVal context As System.Web.HttpContext, ByVal requestType As String, ByVal url As String, _
ByVal pathTranslated As String) As System.Web.IHttpHandler Implements System.Web.IHttpHandlerFactory.GetHandler
Return DirectCast(coreGetHandlerMethod.Invoke(wshf, New Object() {Me.GetType, context, context.Request, context.Response}), IHttpHandler)
End Function
Public Sub ReleaseHandler(ByVal handler As System.Web.IHttpHandler) Implements System.Web.IHttpHandlerFactory.ReleaseHandler
End Sub
End Class
Pay attention to the Reflection hack needed to call the CoreGetHandler method from WebServiceHandlerFactory. The reason for this is that the CoreGetHandler method, which actually creates the IHttpHandler instance, is declared as Friend.
That is almost it! All we need to do now is create web services, which will be classes that inherit from the class defined above, just like in the example below:
Imports System.Web.Services
<WebService(Namespace:="http://tempuri2.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
Public Class WSTest
Inherits WebServiceBase
<WebMethod()> _
Public Function HelloWorld() As String
Return "Hello World"
End Function
End Class
It should be noted that all the things described above are included into the Class Library, so, all you need to do is compile the project and add it as a reference to the newly created website.
I gave this Class
Library the name of WSLibrary where
WSTest is just the
HttpHandler. Note that for each
new Web Service a new entry should be added to the web.config
file. For the example supplied above I added the following:
<httpHandlers>
<add path="WSTest.asmx" verb="*" type="WSLibrary.WSTest" validate="false"/>
</httpHandlers>
Since now each request made to WSTest.asmx will be handled by the WSLibrary Project. This is easily adjustable to suit your needs.
Summary
The
solution described above proved to work very well for the task I
was working on. No doubt there can be ways to find an even
better solution of the problem, for example, there can be only
one entry in the
httpHandlers
for all the Web Services you create.

