So i have gotten stuck while trying to get my asmx webservice to use dependency injection and using an IoC to do it. I want my webservice to be able to use my internal business
You can only have a parameter-less constructor on a WebService. However, what you could do, is have a property on the WebService class, and inside of the parameter-less constructor call something like _myDependency = container.resolve();
Unfortunately there isn't any way for one to perform constructor injection with web services in ASP.NET. It is a requirement of ASP.NET that you provide a default constructor. The constructor of MyService is about as close to the composition root that you can get with this type of web service, without using a DI container.
With ASP.NET it is not unusual to have multiple composition roots. Which can be the constructors of the individual web services and web pages. If you are using ASP.NET MVC it is the ControllerFactory, which is more DI friendly.
With your implementation the important part isn't to move the construction of the object graph from the web service, as this is your composition root. The main thing to do, is to keep the web service as thin as possible, keep most of the logic in the dependency so it can be tested, or reused. Pulling information out of the HTTP headers is an example of a task that the web service could to then pass off that information to the dependency.
A good book to refer to for DI patterns and techniques is Dependency Injection in .NET by Mark Seemann.
If your web service implemented System.Web.IHttpHandler
instead of deriving from System.Web.Services.WebService
you could implement your DI like so:
Global.ashx.cs
public class Global : HttpApplication
{
protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
var context = ((HttpApplication)sender).Context;
var needsMyBusinessService = context.Handler as INeedMyBusinessService;
if (needsMyBusinessService != null)
needsMyBusinessService.MyBusinessService = new MyBusinessService();
}
}
MyService.ashx.cs
public class MyService : IHttpHandler, INeedMyBusinessService
{
public IMyBusinessService MyBusinessService { get; set; }
public bool IsReusable { get { return true; } }
public void ProcessRequest(HttpContext context)
{
// uses my dependency
}
}
INeedMyBusinessService.cs
public interface INeedMyBusinessService
{
IMyBusinessService MyBusinessService { get; set; }
}
However the catch with this implementation is that is does not work with web services that implement System.Web.Services.WebService
as the web service object is not initialized until after the PreRequestHandlerExecute
event is call, which is the last event before ProcessRequest
is called.
The above example works if you want to have a unique instance for each web service. If you wanted to have the same instance (Singleton lifecycle) of MyBusinessService
for each web service request you could implement the Global.ashx.cs file like so:
public class Global : HttpApplication
{
private static IMyBusinessService businessService;
protected void Application_Start(object sender, EventArgs e)
{
Global.businessService = new MyBusinessService();
}
protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
var context = ((HttpApplication)sender).Context;
var needsMyBusinessService = context.Handler as INeedMyBusinessService;
if (needsMyBusinessService != null)
needsMyBusinessService.MyBusinessService = Global.businessService;
}
}