1

I've scoured the internet and stack overflow but simply cannot work out why my AutoFac flatly refuses to inject anything into any controller. My code is below - everything SEEMS to be in order but I receive the following message:

An error occurred when trying to create a controller of type 'SimpleController'. Make sure that the controller has a parameterless public constructor.

Startup.cs

using System.Reflection;
using System.Web.Http;
using Autofac;
using Autofac.Integration.WebApi;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler;
using Microsoft.Owin.Security.DataHandler.Serializer;
using Microsoft.Owin.Security.DataProtection;
using Owin;
using WebApiDependancyViaOwinTest.Models;

[assembly: OwinStartup(typeof(WebApiDependancyViaOwinTest.Startup))]

namespace WebApiDependancyViaOwinTest
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var builder = new ContainerBuilder();
            var config = new HttpConfiguration();
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); 
            builder.RegisterType<TestObject>().As<ITestObject>().InstancePerRequest();
            //ASP.NET Identity Related
            builder.RegisterType<ApplicationUserManager>().AsSelf().InstancePerRequest();
            builder.RegisterType<TicketDataFormat>().As<ISecureDataFormat<AuthenticationTicket>>();
            builder.RegisterType<TicketSerializer>().As<IDataSerializer<AuthenticationTicket>>();
            builder.Register(c => new DpapiDataProtectionProvider().Create("Test")).As<IDataProtector>();
            var x = ApplicationDbContext.Create();
            builder.Register(c => x);
            builder.Register(c => new UserStore<ApplicationUser>(x)).AsImplementedInterfaces();
            builder.Register(c => new IdentityFactoryOptions<ApplicationUserManager>
            {
                DataProtectionProvider = new DpapiDataProtectionProvider("Test")
            });

            var container = builder.Build();
            config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
            app.UseAutofacMiddleware(container);
            app.UseAutofacWebApi(config);
            app.UseWebApi(config);

            ConfigureAuth(app);
        }
    }

    public interface ITestObject
    {
        string Name { get; set; }
    }
    public class TestObject : ITestObject
    {
        public string Name { get; set; }
    }
}

StartUp.Auth.cs

using System;
using Microsoft.AspNet.Identity;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OAuth;
using Owin;
using WebApiDependancyViaOwinTest.Providers;

namespace WebApiDependancyViaOwinTest
{
    public partial class Startup
    {
        public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

        public static string PublicClientId { get; private set; }

        // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
        public void ConfigureAuth(IAppBuilder app)
        {
            // Configure the db context and user manager to use a single instance per request
            //app.CreatePerOwinContext(ApplicationDbContext.Create);
            //app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

            // Enable the application to use a cookie to store information for the signed in user
            // and to use a cookie to temporarily store information about a user logging in with a third party login provider
            app.UseCookieAuthentication(new CookieAuthenticationOptions());
            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

            // Configure the application for OAuth based flow
            PublicClientId = "self";
            OAuthOptions = new OAuthAuthorizationServerOptions
            {
                TokenEndpointPath = new PathString("/Token"),
                Provider = new ApplicationOAuthProvider(PublicClientId),
                AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
                // In production mode set AllowInsecureHttp = false
                AllowInsecureHttp = true
            };

            // Enable the application to use bearer tokens to authenticate users
            app.UseOAuthBearerTokens(OAuthOptions);
        }
    }
}

Global.asax.cs

using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace WebApiDependancyViaOwinTest
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }
}

SimpleController.cs

using System.Web.Http;

namespace WebApiDependancyViaOwinTest.Controllers
{
    public class SimpleController : ApiController
    {
        private readonly ITestObject _testObject;
        public SimpleController(ITestObject testObject)
        {
            _testObject = testObject;
        }

        [AllowAnonymous]
        [HttpGet]
        public string TestInjection()
        {
            return (_testObject == null).ToString();
        }
    }
}

AccountController.cs (Snippet)

[Authorize]
[RoutePrefix("api/Account")]
public class AccountController : ApiController
{
    private const string LocalLoginProvider = "Local";
    private ApplicationUserManager _userManager;
    private readonly ITestObject _testObject;

    public AccountController(ApplicationUserManager userManager,
        ISecureDataFormat<AuthenticationTicket> accessTokenFormat,
        ITestObject testObject)
    {
        UserManager = userManager;
        AccessTokenFormat = accessTokenFormat;
        _testObject = testObject;
    }

    [AllowAnonymous]
    [HttpGet]
    public string TestInjection()
    {
        return (_testObject == null).ToString();
    }
Luke Baughan
  • 4,658
  • 3
  • 31
  • 54
  • Are the controllers located in the same assembly as the `Startup` class? – fknx Aug 22 '16 at 11:09
  • Yeah, Ive got it working now just haven't written up the answer. In the docs it says you need to do the standard WebAPI autofac stuff in Global.asax using the Global.Configuration AND the Owin stuffin Startup.cs for the owin pipeline - I missed the fact i had to do then builder in BOTH places. – Luke Baughan Aug 22 '16 at 11:35
  • 1
    Generally it's not good to try mixing and matching OWIN with non-OWIN. You will probably run into additional odd and insidious errors if you try that. For example, two different container builders == two different containers. Weird dependency problems. Just be prepared for that. – Travis Illig Aug 22 '16 at 15:54
  • Yeah I here you (definitly not ideal) but Im using WebAPI and ASP.NET Identity (Identity sits in OWIN) so I need to be able to use controllers and such forth from web api (not owin) and identity via OWIN in the controllers so as far as I can tell I have to do both. Really the OWIN bit is just injecting Identity bits, its not a self hosted owin app in its own right. – Luke Baughan Aug 23 '16 at 08:28
  • I have a demo solution I can send, witht he code in from above if anyone fancies having a quick look and pointing out my idiocy. I love AutoFac but when things like this happen Im left scratching my head. – Luke Baughan Aug 23 '16 at 10:13

0 Answers0