26

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 layer services. The webservice is to be used by an external client from a different domain and will mainly be used to send and recieve information about entities such as Orders and Customers.

An example would be:

public class MyService : System.Web.Services.WebService
{
    [WebMethod]
    public string HelloWorld()
    {
        return new MyBusinessService().MyMethod();
    } 
}

public class MyBusinessService : IMyBusinessService
{
    public string MyMethod()
    {
        return "hello";
    }
}

I want to use dependency injection to eliminate the need for "newing" up my service but i cant figure out a way to do this. I can get it to work using poor mans DI, or at least i think it's called "poor mans".

like this:

public class MyService : System.Web.Services.WebService
{
    private IMyBusinessService _myService;

    public MyService(IMyBusinessService myService)
    {
        _myService = myService;
    }

    public MyService() : this(new MyBusinessServie()) { }

    [WebMethod]
    public string HelloWorld()
    {
        return _myService.MyMethod();
    }
}

But I simply cant get my head around how to use a IoC container to inject my dependencies because i cant get the service to run without a parameterless constructor. Please be kind, i am not an experienced programmer and have just started to test dependency injection and got it to work fine on my windows forms application with structuremap but got stuck on this one.

Anders Wendt
  • 359
  • 2
  • 7
limlim
  • 395
  • 1
  • 6
  • 14

3 Answers3

43

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;
    }
}
JG in SD
  • 5,427
  • 3
  • 34
  • 46
3

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();

Evaldas Raisutis
  • 1,628
  • 4
  • 18
  • 32
1

This is an old question and unlikely to help very many people, but you basically need IDependencyResolver and IDependencyScope implementations that when ServiceProvider::GetService() fails to return an instance of a requested type, the type is explicitly instanced (ideally using the container to resolve ctor parameters.)

The type can be "explicitly instanced" using reflection, or, using something modern like ActivatorUtilities.GetServiceOrCreateInstance(...)

By default, when the dependency resolver does not provide an instance of a requested type for a controller, page, module (webservice), etc the runtime will attempt to use the de facto Activator class to create an instance, and Activator can only create instances of types which have a public, parameterless constructor.

So to say that your type requires a public, parameterless ctor is only partially true.. if you are unable/unwilling to create IDependencyResolver / IDependencyScope implementations. A custom dependency resolver impl is a trivial thing to implement, and MSDN has articles and examples of basic implementations.

The only other thing you require is the obvious DI container with type registrations, and an IDependencyResolver registered with ASP.NET that leverages your DI container. Today that would likely be something like Microsoft.Extensions.DependencyInjection but for the date and content of the question it could also have been Unity (the dependency injection framework, not the game engine.) Configuring and integrating a DI container is a bit beyond the scope of a Q&A, and there may be other Q&As already which cover doing that. I will note that if you're building your own IDependencyResolver, you also have the options of using a more modern DI framework (such as the one used within ASP.NET Core scaffolds) even though you may be using an ASP.NET version from the 2000s. The underlying DI framework is irrelevant, the Dependency Resolver is what is key here.

See Also:

HTH!