The Evolution of .NET Dependency Resolution


Dependency Resolution (RS), Dependency Injection (DI) and Inversion of Control (IoC) are hot topics nowadays. Basically all frameworks are aware of it, or offer some mechanisms to help implement it. It all started a long time ago, however, and things are slightly confusing at the moment – but will get better!

In this post, I won’t go through all of the details of all dependency resolution libraries in existence, instead I will only focus on Microsoft libraries. Also, I will only talk about generic dependency resolution, leaving out more specialized usages, such as WCF, WF and SharePoint, which also use similar concepts.


It all started with the venerable IServiceProvider interface. It basically provided a single method, GetService, that gave answer to “get me an implementation for this type”. That was it, the single parameter was a Type, and the response, a single object. There were no public implementations of it, but Windows Forms designers – auto generated code – used it a lot to request services from the design surfaces (aka, Visual Studio designer). You were free to implement it in any way, the only recommendation was to return null in case no service could be found, instead of throwing an exception.


ASP.NET MVC started as a built-in template option in Visual Studio but then migrated to NuGet deployment, which is how Microsoft now delivers its fast-moving libraries. MVC 4 introduced its own dependency injection container and API. It was built around IDependencyResolver interface, which did not implement IServiceProvider. although it offered a GetService method that had exactly the same signature – and requirements – as IServiceProvider’s. It also added another method, GetServices, for retrieving all implementations of a given service, again identified by its Type.

This time we had a registration point, which was DependencyResolver.Current. You could set it to your custom implementation, or use the default, which didn’t really return anything.


Web API came out a bit later than MVC, and, while sharing its philosophy, and also being delivered through NuGet, offered its own APIs, namely, for dependency injection. There was also a IDependencyResolver interface, again, not inheriting from IServiceProvider, but with a slightly more complex inheritance: now we had also IDependencyScope, which was where the GetService and GetServices methods were declared, as well as IDisposable, supposedly so that we could have dependency resolution scopes. The well-known registration point was GlobalConfiguration.Configuration.DependencyResolver.


SignalR was something of an outsider in the ASP.NET stack. Like MVC and Web API, it was offered (and still is, for that matter) as a separate NuGet package. No wonder that it also offered its own dependency resolution API, in the form of IDependencyResolver. Again, not related to IServiceProvider, and as such offered a couple of other methods: besides the classic GetService (same signature and contract), we also had GetServices, and even a registration method (RegisterType with a couple of overloads). It was also IDisposable, perhaps to control registration scopes. The registration point was available as GlobalHost.DependencyResolver and there was a default implementation, appropriately named DefaultDependencyResolver.

Entity Framework 6

Leaving ASP.NET land for a moment, Entity Framework 6 also introduced its own (of course…) API for dependency resolution. The IDbDependencyResolver also offered the now classic GetService and GetServices methods, but this time, these also took an optional key parameter. GetService should not throw if a matching service was not found, and GetServices should return an empty enumeration likewise. The registration was done through DbConfiguration.DependencyResolver, no public default implementation. EF 6 expected a number of services to be supplied through dependency resolution, otherwise, it would use its own built-in defaults.

Entity Framework 7

Although still in pre-release, EF 7 shuffles things a bit. For once, the DbContext constructor can now take an instance of IServiceProvider. More details coming soon, I guess, but apparently it seems to be going back to the roots.


Unity is part of Microsoft’s Enterprise Library and long time readers of my blog should know that it’s what I normally use for inversion of control (IoC), dependency injection (DI) and aspect-oriented programming (AOP). Being an IoC container, it includes its own API, IUnityContainer, which also offered service resolution methods, besides lots of other stuff; this time, the names are Resolve and ResolveAll, with several overloads and generic as well as non-generic versions. Resolve can take an optional key, but a major difference is that the default implementation (UnityContainer) will throw an exception if a service is not found.

Common Service Locator

Because there are lots of dependency resolution libraries out there, offering conceptually similar services but with different APIs, Microsoft sponsored an open-source library for defining a common interface for dependency resolution to which interested parties could comply, or, better, write an adapter for. The code is available in Codeplex and NuGet and several library authors provided adapters for the Common Service Locator, such as Unity, Castle Windsor, Spring.NET, StructureMap, Autofac, MEF, LinFu, Ninject, etc. See a list of NuGet packages matching Common Service Locator here. The Common Service Locator API only prescribes two families of methods in its IServiceLocator API: GetInstance and GetAllInstances. Interestingly, IServiceLocator inherits from IServiceProvider, and it also features an optional key for GetInstance, like EF6 and Unity, as this is the more general case – multiple registrations for the same type under different keys, the default key is null.


ASP.NET 5 is just around the corner, and Microsoft seems to me to be moving in the right direction. MVC, Web API and SignalR are merged together, so the dependency resolution mechanisms should be the same. The IServicesCollection (sorry, no public API documentation) interface allows for the registration and the resolution of services through the conventional Startup.ConfigureServices method and is made available in the HttpContext and IApplicationBuilder implementations as the ApplicationServices and RequestServices properties, of type IServiceProvider. Not that you typically need it, but the default implementation of IServicesCollection is ServicesCollection, and one key difference is that you do not have a global entrypoint to it, you can only access it through the current HttpContext reference, in most cases.


That’s it. Looking forward for your feedback on this.

Hosting HTTP Resources


How do I host thee? Let me count the ways!

You may not have realized that .NET offers a lot of alternatives when it comes to hosting an HTTP server, that is, without resorting to IIS, IIS Express or the now gone Visual Studio Web Development Server (aka, Cassini, rest in peace); by that, I either mean:

  • Opening up a TCP port and listening for HTTP requests, or a subset of them;
  • Running ASP.NET pages without a server.

In this post I am going through some of them. Some are specific to web services, but since they understand REST, I think they qualify as well as generic HTTP hosting mechanisms.

.NET HttpListener

Let’s start with HttpListener. This is included in .NET since version 2 and offers a decent server for static contents, that is, it cannot run any dynamic contents, like ASP.NET handlers, nor does it know anything about them. You merely point it to a physical folder on your file system, and it will happily serve any contents located inside it. Let’s see an example:

using (var listener = new System.Net.HttpListener())


    var url = "http://*:2000/";




    var ctx = listener.GetContext();


    var message = "Hello, World!";


    ctx.Response.StatusCode = (Int32) HttpStatusCode.OK;

    ctx.Response.ContentType = "text/plain";

    ctx.Response.ContentLength64 = message.Length;


    using (var writer = new StreamWriter(ctx.Response.OutputStream))







This is a very basic example that just listens on port 2000, for any host name and request, and just returns Hello, World! when contacted before shutting down.

ASP.NET ApplicationHost

Complementary to HttpListener, we have a way to execute ASP.NET handlers (ASPX pages, ASHX generic handlers and ASMX web services) in a self-hosted application domain. For that, we use the ApplicationHost class to create the ASP.NET application domain, and a regular .NET class for the server implementation. An example:

public class Host : MarshalByRefObject


    public void ProcessPage(String page, String query, TextWriter writer)


        var worker = new SimpleWorkerRequest(page, query, writer);





//strip out bin\debug, so as to find the base path where web files are located

var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location).Replace(@"\bin\Debug", String.Empty);


//we need to copy the assembly to the base path

File.Copy(Assembly.GetExecutingAssembly().Location, Path.Combine(path, "bin", Assembly.GetExecutingAssembly().CodeBase.Split('/').Last()), true);


var host = System.Web.Hosting.ApplicationHost.CreateApplicationHost(typeof(Host), "/", path) as Host;

host.ProcessPage("Default.aspx", null);

Notice the File.Copy call; this is necessary because the assembly referenced by the Default.aspx page needs to be located in the same folder as the page. An alternative to this would be to add a post build-event to the Visual Studio project:


I leave as an exercise to the interested readers how we can combine this with HttpListener! Winking smile


Moving on to more recent technologies, we now have OWIN. In case you’ve been living in another world and haven’t heard of OWIN, I’ll just say that it is a standard for decoupling .NET from any particular web servers, like IIS or IIS Express. It also happens to have a self-hosting implementation – which, by the way, uses HttpListener underneath.

We need to add a reference to the Microsoft.Owin.SelfHost NuGet package:


After that, we just register an instance of WebApp with the default parameters, add an handler, and we’re done:

class Program


    public static void Configuration(IAppBuilder app)


        app.Use(new Func<AppFunc, AppFunc>(next => (async ctx =>


            using (var writer = new StreamWriter(ctx["owin.ResponseBody"] as Stream))


                await writer.WriteAsync("Hello, World!");





    static void Main(String[] args)


        using (WebApp.Start<Program>("http://*:2000"))






Again, no fancy dynamic stuff, just plain and simple HTTP: it waits for a request and just returns Hello, World!. It is possible to run ASP.NET MVC on top of OWIN, that is the goal of project Helios, which is currently in alpha stage. Do check out the Helios NuGet package at


WCF ServiceHost

Since its release, WCF offers a way for it to be self-hosted in a .NET process. The class responsible for that is ServiceHost, or one of its descendants, like WebServiceHost, more suitable for REST. I will show an example using REST, which can be easily tested using a web browser:


public interface IRest


    [WebGet(ResponseFormat = WebMessageFormat.Json)]


    String Index();



public class Rest : IRest


    public String Index()


        return "Hello, World!";




using (var host = new WebServiceHost(typeof(Rest)))


    var url = new Uri(@"http://localhost:2000");

    var binding = new WebHttpBinding();


    host.AddServiceEndpoint(typeof(IRest), binding, url);





This example listens for a request of /Index on port 2000 and upon receiving it, returns Hello, World! in JSON format – because we are only sending a string, it will be wrapped in . WCF REST out of the box only supports returning data in XML or JSON format, no Text or HTML, but, to be fair, that’s not what it was meant to. Should be possible to return HTML, but, honestly, it would probably mean more work than it’s worth.

Web API HttpServer

Another web services technology in the .NET stack is Web API. Web API uses a concept similar to MVC, with controllers, models and action methods, but no views. It can be self-hosted as well, using the HttpServer class. In order to use it, install the Microsoft.AspNet.WebApi.SelfHost NuGet package. You will notice that its description claims that it is legacy, and has been replaced for another based on OWIN, yet, it is fully functional, if you don’t required it to be OWIN-compliant:


Because of the Web API architecture, we need to implement a controller for handling requests, :

public class DummyController : ApiController



    public IHttpActionResult Index()


        return this.Content(HttpStatusCode.OK, "Hello, World!");



In this example, we do not take any parameters and just return the usual response.

Here’s the infrastructure code:

var url = "http://localhost:2000";

var config = new HttpSelfHostConfiguration(url);

config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{action}");


using (var server = new HttpSelfHostServer(config))




The DummyController is found by reflecting the current executing assembly and applying conventions; any HTTP requests for /api/Dummy/Index will land there and the outcome will be plain text.

IIS Hostable Web Core

Now, this one is tricky. IIS, from version 7, allows hosting its core engine in-process, that is, from inside another application; this is called IIS Hostable Web Core (HWC). We can supply our own Web.config and ApplicationHost.config files and specify a root folder from which IIS will serve our web resources, including any dynamic contents that IIS can serve (ASPX pages, ASHX handlers, ASMX and WCF web services, etc). Yes, I know, this contradicts my introduction, where I claimed that this post would be about hosting web resources without IIS… still, I think this is important to know, because it can be fully controlled through code.

You need to make sure HWC is installed… one option is using PowerShell’s Install-WindowsFeature cmdlet:

Or the Server Manager application:


Features page


Because HWC is controlled through an unmanaged DLL, we have to import its public API control functions and call it with .NET code. Here’s an example:

public class Host : IDisposable


    private static readonly String FrameworkDirectory = RuntimeEnvironment.GetRuntimeDirectory();

    private static readonly String RootWebConfigPath = Environment.ExpandEnvironmentVariables(Path.Combine(FrameworkDirectory, @"Config\Web.config"));


    public Host(String physicalPath, Int32 port)


        this.ApplicationHostConfigurationPath = Path.Combine(Path.GetTempPath(), Path.GetTempFileName() + ".config");

        this.PhysicalPath = physicalPath;

        this.Port = port;


        var applicationHostConfigurationContent = File.ReadAllText("ApplicationHost.config");

        var text = String.Format(applicationHostConfigurationContent, this.PhysicalPath, this.Port);


        File.WriteAllText(this.ApplicationHostConfigurationPath, text);








    public String ApplicationHostConfigurationPath



        private set;



    public Int32 Port



        private set;



    public String PhysicalPath



        private set;



    public void Dispose()






    protected virtual void Dispose(Boolean disposing)





    public void Start()


        if (IisHostableWebCoreEngine.IsActivated == false)


            IisHostableWebCoreEngine.Activate(this.ApplicationHostConfigurationPath, RootWebConfigPath, Guid.NewGuid().ToString());




    public void Stop()


        if (IisHostableWebCoreEngine.IsActivated == true)




            this.PhysicalPath = String.Empty;

            this.Port = 0;




            this.ApplicationHostConfigurationPath = String.Empty;




    private static class IisHostableWebCoreEngine


        private delegate Int32 FnWebCoreActivate([In, MarshalAs(UnmanagedType.LPWStr)] String appHostConfig, [In, MarshalAs(UnmanagedType.LPWStr)] String rootWebConfig, [In, MarshalAs(UnmanagedType.LPWStr)] String instanceName);

        private delegate Int32 FnWebCoreShutdown(Boolean immediate);


        private const String HostableWebCorePath = @"%WinDir%\System32\InetSrv\HWebCore.dll";

        private static readonly IntPtr HostableWebCoreLibrary = LoadLibrary(Environment.ExpandEnvironmentVariables(HostableWebCorePath));


        private static readonly IntPtr WebCoreActivateAddress = GetProcAddress(HostableWebCoreLibrary, "WebCoreActivate");

        private static readonly FnWebCoreActivate WebCoreActivate = Marshal.GetDelegateForFunctionPointer(WebCoreActivateAddress, typeof(FnWebCoreActivate)) as FnWebCoreActivate;


        private static readonly IntPtr WebCoreShutdownAddress = GetProcAddress(HostableWebCoreLibrary, "WebCoreShutdown");

        private static readonly FnWebCoreShutdown WebCoreShutdown = Marshal.GetDelegateForFunctionPointer(WebCoreShutdownAddress, typeof(FnWebCoreShutdown)) as FnWebCoreShutdown;


        internal static Boolean IsActivated



            private set;



        internal static void Activate(String appHostConfig, String rootWebConfig, String instanceName)


            var result = WebCoreActivate(appHostConfig, rootWebConfig, instanceName);


            if (result != 0)





            IsActivated = true;



        internal static void Shutdown(Boolean immediate)


            if (IsActivated == true)



                IsActivated = false;





        private static extern IntPtr LoadLibrary(String dllname);



        private static extern IntPtr GetProcAddress(IntPtr hModule, String procname);



In order for this to work, we need to have an ApplicationHost.config file, a minimum working example being:

<?xml version="1.0" encoding="UTF-8" ?>



        <sectionGroup name="system.applicationHost">

            <section name="applicationPools" />

            <section name="sites" />



        <sectionGroup name="system.webServer">

            <section name="globalModules" />

            <section name="modules" />

            <section name="handlers" />

            <section name="staticContent" />

            <section name="serverRuntime" />

            <sectionGroup name="security">

                <section name="access"/>

                <sectionGroup name="authentication">

                    <section name="anonymousAuthentication" />

                    <section name="windowsAuthentication" />

                    <section name="basicAuthentication" />


                <section name="authorization" />

                <section name="requestFiltering" />

                <section name="applicationDependencies" />

                <section name="ipSecurity" />


            <section name="asp" />

            <section name="caching" />

            <section name="cgi" />

            <section name="defaultDocument" />

            <section name="directoryBrowse" />

            <section name="httpErrors" />

            <section name="httpLogging" />

            <section name="httpProtocol" />

            <section name="httpRedirect" />

            <section name="httpTracing" />

            <section name="isapiFilters" allowDefinition="MachineToApplication" />

            <section name="odbcLogging" />






            <add name="AppPool" managedPipelineMode="Integrated" managedRuntimeVersion="v4.0" autoStart="true" />




            <site name="MySite" id="1">


                    <binding protocol="http" bindingInformation="*:{1}:localhost" />


                <application path="/" applicationPool="AppPool" >

                    <virtualDirectory path="/" physicalPath="{0}" />








            <add name="StaticFileModule" image="%windir%\System32\inetsrv\static.dll" />

            <add name="AnonymousAuthenticationModule" image="%windir%\System32\inetsrv\authanon.dll" />

            <add name="ManagedEngine" image="%windir%\Microsoft.NET\Framework\v4.0.30319\webengine4.dll" />




            <add name="StaticFileModule" />

            <add name="AnonymousAuthenticationModule" />

            <add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" preCondition="managedHandler" />

            <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" preCondition="managedHandler" />

            <add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule" preCondition="managedHandler" />

            <add name="AnonymousIdentification" type="System.Web.Security.AnonymousIdentificationModule" preCondition="managedHandler" />



        <handlers accessPolicy="Read, Script">

            <add name="PageHandlerFactory-Integrated" path="*.aspx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.PageHandlerFactory" preCondition="integratedMode" />

            <add name="StaticFile" path="*" verb="*" modules="StaticFileModule" resourceType="Either" requireAccess="Read" />




            <mimeMap fileExtension=".html" mimeType="text/html" />

            <mimeMap fileExtension=".jpg" mimeType="image/jpeg" />

            <mimeMap fileExtension=".gif" mimeType="image/gif" />

            <mimeMap fileExtension=".png" mimeType="image/png" />




And all we need to start hosting pages on the port and physical path specified by ApplicationHost.config is:

using (var host = new Host(path, port))






A couple of notes:

  • Because it calls unmanaged functions, can be terrible to debug;
  • The ApplicationHost.config needs to be in the application’s binary build directory and must have two placeholders, {0} and {1}, for the physical path and HTTP port, respectively;
  • It refers to .NET 4.0, if you want to change it, you will to change a number of modules and paths;
  • Only very few modules are loaded, if you want, get a full file from %HOMEPATH%\Documents\IISExpress\config\ApplicationHost.config and adapt it to your likings.

.NET TcpListener

And finally, one for the low-level guys. The TcpListener class allows the opening of TCP/IP ports and the handling of requests coming through them. It doesn’t know anything about the HTTP protocol, of course, so, if we want to leverage it, we need to implement it ourselves. Here’s a very, very, basic example:

var listener = System.Net.Sockets.TcpListener.Create(2000);



using (var client = listener.AcceptTcpClient())


    using (var reader = new StreamReader(client.GetStream()))

    using (var writer = new StreamWriter(client.GetStream()))


        var request = reader.ReadLine();


        writer.WriteLine("HTTP/1.1 200 OK");

        writer.WriteLine("Content-type: text/plain");


        writer.WriteLine("Hello, World!");






Here we’re just reading any string content and responding with some HTTP headers plus the usual response. Of course, HTTP is quite complex, so I wouldn’t recommend you try to implement it yourself.


I presented a couple of solutions for hosting web resources, servicing HTTP requests or running ASP.NET handlers. Hopefully you will find one that matches your needs.