Should OWIN self host app using Ninject OWINHost need system.web?
Asked Answered
P

2

12

I'm trying to create a Windows service with OWIN self hosted WebAPI with Ninject . I got it to work but I had to add a reference to system.web, which seems wrong. Without a reference to system.web I got these compile errors:

The type 'System.Web.Routing.RouteCollection' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

The type 'System.Web.Routing.Route' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

The errors showed up after I added Ninject according to this article Setting up a OWIN WebApi application

I also had to constrain the Microsoft.Owin to version 2.1.0 for Ninject to work. During the service startup Ninject is looking for Owin 2.1.0. If you get latest on Microsoft.Owin it will roll to 3.0.

The three main NuGet packages I'm using are:

Microsoft.AspNet.WebApi.OwinSelfHost

Ninject.Web.Common.OwinHost

Ninject.Web.WebApi.OwinHost

Here's all my packages (notice the constrain on Microsoft.Owin)

  <package id="Microsoft.AspNet.WebApi" version="5.2.2" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.2" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.2" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Owin" version="5.2.2" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.OwinSelfHost" version="5.2.2" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.2" targetFramework="net45" />
  <package id="Microsoft.Owin" version="2.1.0" targetFramework="net45" allowedVersions="(,2.1]" />
  <package id="Microsoft.Owin.Host.HttpListener" version="3.0.0" targetFramework="net45" />
  <package id="Microsoft.Owin.Hosting" version="2.0.2" targetFramework="net45" />
  <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net45" />
  <package id="Ninject" version="3.2.2.0" targetFramework="net45" />
  <package id="Ninject.Extensions.ContextPreservation" version="3.2.0.0" targetFramework="net45" />
  <package id="Ninject.Extensions.NamedScope" version="3.2.0.0" targetFramework="net45" />
  <package id="Ninject.Web.Common" version="3.2.2.0" targetFramework="net45" />
  <package id="Ninject.Web.Common.OwinHost" version="3.2.2.0" targetFramework="net45" />
  <package id="Ninject.Web.WebApi" version="3.2.1.0" targetFramework="net45" />
  <package id="Ninject.Web.WebApi.OwinHost" version="3.2.1.0" targetFramework="net45" />
  <package id="Owin" version="1.0" targetFramework="net45" />

Here's what the Program.cs of the windows service looks like

using Microsoft.Owin.Hosting;
using Ninject;
using Ninject.Web.Common.OwinHost;
using Ninject.Web.WebApi.OwinHost;
using Owin;
using System.Reflection;
using System.ServiceProcess;
using System.Web.Http;


namespace ServiceExample
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] 
            { 
                new Service1() 
            };


            using (WebApp.Start<Startup>("http://localhost:12345"))
            {
                ServiceBase.Run(ServicesToRun);  
            }
        }



        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                ConfigureWebAPI(app);

            }

            private void ConfigureWebAPI(IAppBuilder app)
            {
                var config = new HttpConfiguration();
                config.Routes.MapHttpRoute(
                    "DefaultApi",
                    "api/{controller}/{id}",
                    new {id = RouteParameter.Optional});

                app.UseNinjectMiddleware(CreateKernel).UseNinjectWebApi(config);
            }


            private static StandardKernel CreateKernel()
            {
                var kernel = new StandardKernel();
                kernel.Load(Assembly.GetExecutingAssembly());
                return kernel;
            }
        }
    }
}
Pigg answered 5/9, 2014 at 15:13 Comment(0)
T
14

Try to remove System.Web.Http.WebHost.dll from references.

references list with System.Web.Http.WebHost.dll


I had the same problem when I wanted to have an API project as class library and separate host projects (one using console and other IIS) as described in this great blog post

The problem was that when I executed Install-Package Microsoft.AspNet.WebApi to install ASP.NET Web API it also added reference to System.Web.Http.WebHost.dll and the result packages.json was:

<packages>
  <package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net452" />
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net452" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net452" />
  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net452" />
  <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net452" />
</packages>

so the solution was to remove reference to System.Web.Http.WebHost.dll and delete Microsoft.AspNet.WebApi and Microsoft.AspNet.WebApi.WebHost from packages.json so it won't install again when some will do nuget restore/reinstall:

<packages>
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net452" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net452" />
  <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net452" />
</packages>

And this is my packages.json from working class library ASP.NET Web API project:

<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net452" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net452" />
<package id="Microsoft.AspNet.WebApi.Owin" version="5.2.3" targetFramework="net452" />  
<package id="Microsoft.Owin" version="3.0.1" targetFramework="net452" />
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net452" />
<package id="Owin" version="1.0" targetFramework="net452" />
Tombolo answered 5/10, 2015 at 13:38 Comment(4)
I needed these 3, in addition to the ones you listed, to make mine work (.NET 4.5.1) as a windows service: "Microsoft.AspNet.WebApi.OwinSelfHost" "Microsoft.Owin.Host.HttpListener" "Microsoft.Owin.Hosting"Pigg
Adding Ninject (one of the NUGet packages) seemed to be adding the reference which seems to break this! Simple solution is to remove that reference!!Aardwolf
Adding to the above: manually adding reference to system.web also seems to make the error go away and presently going with this approach instead of removing reference to System.Web.Http.WebHost (at the moment it is not entirely clear if that reference is redundant).Aardwolf
Awesome, you've made my day!Hwang
D
4

I came across with the same problem as you, but without usign Ninject OwinHost, and indeed I think that the problem is not with Ninject but the Routing.

The problem is this code:

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

that uses System.Web.Routing wich is contained on System.Web namespace (Check here).

So, the alternative to this that I've found is using rooting with attributes. So you can replace the code above by this:

// Web API routes
config.MapHttpAttributeRoutes();

If you are not familiar with it, check this tutorial.

Using this approach you can delete the System.Web reference of your project.

Danicadanice answered 17/9, 2014 at 9:52 Comment(2)
Initially I had "app.UseWebApi(config)" so the "Routes.MapHttpRoute" part was there and it resolved without System.Web. But by adding Ninject, System.Web was required. I need Ninject for dependency injection, with the MapHttpAttributesRoutes() how do I startup Ninject?Pigg
This is a good, practical workaround, but I'm a bit confused as to why the call to config.Routes.MapHttpRoute requires a reference to System.Web. None of the types involved in the call (IHttpRoute, HttpRouteCollection, RouteParameter) are declared in that assembly, they're all from System.Web.Http.Routing. And the System.Web.Http assembly containing HttpCollection doesn't depend on System.Web. Can you explain how that dependency has arisen?Boozy

© 2022 - 2024 — McMap. All rights reserved.