SelfHost WebApi with Owin and unity using a Nuget package

This post continues in from the previous blog Self Host WebApi with Owin and Unity

The blog project and nuget package can be downloaded from here:

nuget: https://www.nuget.org/packages/Unity.SelfHostWebApiOwin
code: https://github.com/damienbod/SelfHostWebApiWithOwinAndUnityUsingNuget

In this blog, a nuget packet will be created, so unity can be used with a self hosted web Api easily.

What is required in the nuget package:

  1. UnityDependencyResolver: so the controllers can be injected with unity
  2. UnityFilterAttributeFilterProvider: so the filters can be injected with unity

First create a new project: Unity.SelfHostWebApiOwin

Now add the following classes:

UnityDependencyResolver

using System;
using System.Collections.Generic;
using System.Web.Http.Controllers;
using System.Web.Http.Dependencies;
using Microsoft.Practices.Unity;

namespace Unity.SelfHostWebApiOwin
{
    /// <summary>
    /// An implementation of the <see cref="IDependencyResolver"/> interface that wraps a Unity container.
    /// </summary>
    public sealed class UnityDependencyResolver : IDependencyResolver
    {
        private IUnityContainer container;
        private SharedDependencyScope sharedScope;

        /// <summary>
        /// Initializes a new instance of the <see cref="UnityDependencyResolver"/> class for a container.
        /// </summary>
        /// <param name="container">The <see cref="IUnityContainer"/> to wrap with the <see cref="IDependencyResolver"/>
        /// interface implementation.</param>
        public UnityDependencyResolver(IUnityContainer container)
        {
            if (container == null)
                throw new ArgumentNullException("container");

            this.container = container;
            this.sharedScope = new SharedDependencyScope(container);
        }

        /// <summary>
        /// Reuses the same scope to resolve all the instances.
        /// </summary>
        /// <returns>The shared dependency scope.</returns>
        public IDependencyScope BeginScope()
        {
            return this.sharedScope;
        }

        /// <summary>
        /// Disposes the wrapped <see cref="IUnityContainer"/>.
        /// </summary>
        public void Dispose()
        {
            this.container.Dispose();
            this.sharedScope.Dispose();
        }

        /// <summary>
        /// Resolves an instance of the default requested type from the container.
        /// </summary>
        /// <param name="serviceType">The <see cref="Type"/> of the object to get from the container.</param>
        /// <returns>The requested object.</returns>
        public object GetService(Type serviceType)
        {
            try
            {
                return this.container.Resolve(serviceType);
                }
            catch (ResolutionFailedException)
            {
                return null;
            }
        }

        /// <summary>
        /// Resolves multiply registered services.
        /// </summary>
        /// <param name="serviceType">The type of the requested services.</param>
        /// <returns>The requested services.</returns>
        public IEnumerable<object> GetServices(Type serviceType)
        {
            try
            {
                return this.container.ResolveAll(serviceType);
            }
            catch (ResolutionFailedException)
            {
                return null;
            }
        }

        private sealed class SharedDependencyScope : IDependencyScope
        {
            private IUnityContainer container;

            public SharedDependencyScope(IUnityContainer container)
            {
                this.container = container;
            }

            public object GetService(Type serviceType)
            {
                return this.container.Resolve(serviceType);
            }

            public IEnumerable<object> GetServices(Type serviceType)
            {
                return this.container.ResolveAll(serviceType);
            }

            public void Dispose()
            {
                // NO-OP, as the container is shared.
            }
        }
    }
}

WebApiUnityActionFilterProvider

using System.Collections.Generic;
using System.Web.Http;
using System.Web.Http.Filters;
using System.Web.Http.Controllers;
using Microsoft.Practices.Unity;

namespace Unity.SelfHostWebApiOwin
{
    public class WebApiUnityActionFilterProvider : ActionDescriptorFilterProvider, IFilterProvider
    {
        private readonly IUnityContainer container;

        public WebApiUnityActionFilterProvider(IUnityContainer container)
        {
            this.container = container;
        }

        public new IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
        {
            var filters = base.GetFilters(configuration, actionDescriptor);
            var filterInfoList = new List<FilterInfo>();

            foreach (var filter in filters)
            {
                container.BuildUp(filter.Instance.GetType(), filter.Instance);
            }

            return filters;
        }
    }

}

And then add the required nuget packages as required.

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.AspNet.WebApi.Client" version="5.1.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.1.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Owin" version="5.1.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.OwinSelfHost" version="5.1.0" targetFramework="net45" />
  <package id="Microsoft.Owin" version="2.1.0" targetFramework="net45" />
  <package id="Microsoft.Owin.Host.HttpListener" version="2.1.0" targetFramework="net45" />
  <package id="Microsoft.Owin.Hosting" version="2.1.0" targetFramework="net45" />
  <package id="Newtonsoft.Json" version="5.0.8" targetFramework="net45" />
  <package id="Owin" version="1.0" targetFramework="net45" />
  <package id="Unity" version="3.0.1304.1" targetFramework="net45" />
</packages>

Now a nuget get package needs to be created:

Step 1: Download the latest nuget.exe (version 2.7.40906.213 or later)

Step 2: Create a Nuget package in the cmd console: nuget spec

Step 3: Edit the file and rename; for example Unity.SelfHostWebApiOwin.1.0.6-beta.nuspec

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
  <metadata>
    <id>Unity.SelfHostWebApiOwin</id>
    <title>Self Hosted Web Api using Owin and Unity</title>
    <version>1.0.11</version>
    <authors>damienbod</authors>
    <owners>damienbod</owners>
    <projectUrl>https://damienbod.wordpress.com/2013/10/12/self-hosted-web-api-using-owin-and-unity-nuget-package-documentation</projectUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Unity for self hosted WebApi</description>
	<iconUrl>http://www.gravatar.com/avatar/61d005637f57b5c3da8ba662cf04a9d6.png</iconUrl>
	<language>en-US</language>
	<tags>.NET ASP.NET Web Api Enterprise Library Unity Web WebApi</tags>
	 <dependencies>
      <dependency id="Unity" version="3.0.1304.1" />
	  <dependency id="Microsoft.Web.Infrastructure" version="1.0.0.0" />
      <dependency id="Microsoft.AspNet.WebApi.WebHost" version="5.1.0"  />
      <dependency id="Microsoft.AspNet.WebPages" version="3.1.0"  />
      <dependency id="Newtonsoft.Json" version="5.0.8"  />
	  <dependency id="Owin" version="1.0"  />
	  <dependency id="Microsoft.AspNet.WebApi.OwinSelfHost" version="5.1.0" />
	  <dependency id="Microsoft.AspNet.WebApi.Core" version="5.1.0" />  
	  <dependency id="Microsoft.AspNet.WebApi.Client" version="5.1.0" />
	  <dependency id="Microsoft.Owin" version="2.1.0" />
	  <dependency id="Microsoft.Owin.Host.HttpListener" version="2.1.0" />
    <dependency id="Microsoft.Owin.Host.SystemWeb" version="2.1.0" />
   </dependencies>
  </metadata>
  </package>
  

Step 4: Create the nuget structure:

  • MyPackage
    • content
      • Unity.SelfHostWebApiOwin
        • Startup.cs.pp
        • UnityHelpers.cs.pp
    • lib
      • net45
        • Unity.SelfHostWebApiOwin.dll

Files in the content folder will be copied directly into the target project.
Files into the lib will be added as references.

The following 2 files are added to the content. The files have a .pp ending, required by nuget
Startup.cs.pp

using Owin;
using System.Web.Http;
using Microsoft.Owin.Hosting;
using System;
using System.Linq;
using Microsoft.Practices.Unity;
using System.Web.Http.Filters;

namespace Unity.SelfHostWebApiOwin
{
    public class Startup
    {
        private static readonly IUnityContainer _container = UnityHelpers.GetConfiguredContainer();

        // Your startup logic
        public static void StartServer()
        {
            string baseAddress = "http://localhost:8081/";
            var startup = _container.Resolve<Startup>();
             //options.ServerFactory = "Microsoft.Owin.Host.HttpListener"
            IDisposable webApplication = WebApp.Start(baseAddress, startup.Configuration);

            try
            {
                Console.WriteLine("Started...");

                Console.ReadKey();
            }
            finally
            {
                webApplication.Dispose();
            }
        }

        // This code configures Web API. The Startup class is specified as a type
        // parameter in the WebApp.Start method.
        public void Configuration(IAppBuilder appBuilder)
        {
            // Configure Web API for self-host. 
            var config = new HttpConfiguration();

			// Add Unity DependencyResolver
            config.DependencyResolver = new UnityDependencyResolver(UnityHelpers.GetConfiguredContainer());

			// Add Unity filters provider
            RegisterFilterProviders(config);

            //config.Routes.MapHttpRoute(
            //    name: "DefaultApi",
            //    routeTemplate: "api/{controller}/{id}",
            //    defaults: new { id = RouteParameter.Optional }
            //);

            // Web API routes
            config.MapHttpAttributeRoutes();

            appBuilder.UseWebApi(config);
        }

        private static void RegisterFilterProviders(HttpConfiguration config)
        {
            // Add Unity filters provider
            var providers = config.Services.GetFilterProviders().ToList();
            config.Services.Add(typeof(System.Web.Http.Filters.IFilterProvider), new WebApiUnityActionFilterProvider(UnityHelpers.GetConfiguredContainer()));
            var defaultprovider = providers.First(p => p is ActionDescriptorFilterProvider);
            config.Services.Remove(typeof(System.Web.Http.Filters.IFilterProvider), defaultprovider);
        }

    }
}

UnityHelpers.cs.pp

using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.Practices.Unity;
using System.Linq;

namespace Unity.SelfHostWebApiOwin
{
    public static class UnityHelpers
    {
        #region Unity Container
        private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
        {
            var container = new UnityContainer();
            RegisterTypes(container);
            return container;
        });

        public static IUnityContainer GetConfiguredContainer()
        {
            return container.Value;
        }
        #endregion

        //private static readonly Type[] EmptyTypes = new Type[0];

        public static IEnumerable<Type> GetTypesWithCustomAttribute<T>( Assembly[] assemblies)
        {
            foreach (var assembly in assemblies)
            {
                foreach (Type type in assembly.GetTypes())
                {
                    if (type.GetCustomAttributes(typeof(T), true).Length > 0)
                    {
                        yield return type;
                    }
                }
            }
        }

        public static void RegisterTypes(IUnityContainer container)
        {
		    // Add your register logic here...
            // var myAssemblies = AppDomain.CurrentDomain.GetAssemblies().Where(a => a.FullName.StartsWith("your_assembly_Name")).ToArray();

            container.RegisterType(typeof(Startup));

            // container.RegisterTypes(
            //     UnityHelpers.GetTypesWithCustomAttribute<ContainerControlledAttribute>(myAssemblies),
            //     WithMappings.FromMatchingInterface,
            //     WithName.Default,
            //     WithLifetime.ContainerControlled,
            //     null
            //    ).RegisterTypes(
            //             UnityHelpers.GetTypesWithCustomAttribute<TransientLifetimeAttribute>(myAssemblies),
            //             WithMappings.FromMatchingInterface,
            //             WithName.Default,
            //             WithLifetime.Transient);

        }

    }
}

Step 5: Create the nuget package in the cmd console: nuget pack
This produces a .nupkg file. This is the file which can be uploaded.

Step 6: Upload to nuget. nuget gallery
NuGetGalleryUpload

Now we are ready to use the nuget package. The next post will be the nuget package documentation/user manual.

Links:
nuget create package help

https://www.nuget.org/

http://docs.nuget.org/docs/creating-packages/creating-and-publishing-a-package

http://msdn.microsoft.com/en-us/magazine/dn451439.aspx

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: