Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ninject error in WebAPI 2.1 - Make sure that the controller has a parameterless public constructor

I have the following packages and their dependencies installed in my WebAPI project:

Ninject.Web.WebApi Ninject.Web.WebApi.OwinHost

I am running this purely as a web-api project. No MVC.

When I run my application and send a POST to the AccountController's Register action I get the following error returned:

{
"message":"An error has occurred.",
"exceptionMessage":"An error occurred when trying to create a controller of type 'AccountController'. Make sure that the controller has a parameterless public constructor.",
"exceptionType":"System.InvalidOperationException",
"stackTrace":"   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)\r\n   at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()",
"innerException":{
"message":"An error has occurred.",
"exceptionMessage":"Type 'RPT.Api.Controllers.AccountController' does not have a default constructor",
"exceptionType":"System.ArgumentException",
"stackTrace":"   at System.Linq.Expressions.Expression.New(Type type)\r\n   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)\r\n   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)"
}
}

Can anyone help me as the only details I can find on Google seem to be from 2012.

Note: I've also tried AutoFac instead of Ninject and get the same error there too. Most frustrating.

Here's my NinjectWebCommon.cs:

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using RPT.Data;
using RPT.Services;
using RPT.Services.Interfaces;

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(RPT.Api.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(RPT.Api.NinjectWebCommon), "Stop")]

namespace RPT.Api
{
    using System;
    using System.Web;

    using Microsoft.Web.Infrastructure.DynamicModuleHelper;

    using Ninject;
    using Ninject.Web.Common;

    public static class NinjectWebCommon
    {
        private static readonly Bootstrapper bootstrapper = new Bootstrapper();

        /// <summary>
        /// Starts the application
        /// </summary>
        public static void Start()
        {
            DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
            DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
            bootstrapper.Initialize(CreateKernel);
        }

        /// <summary>
        /// Stops the application.
        /// </summary>
        public static void Stop()
        {
            bootstrapper.ShutDown();
        }

        /// <summary>
        /// Creates the kernel that will manage your application.
        /// </summary>
        /// <returns>The created kernel.</returns>
        private static IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            try
            {
                kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
                kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

                RegisterServices(kernel);


                return kernel;
            }
            catch
            {
                kernel.Dispose();
                throw;
            }
        }

        /// <summary>
        /// Load your modules or register your services here!
        /// </summary>
        /// <param name="kernel">The kernel.</param>
        private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<RptContext>().ToSelf();

            kernel.Bind<IUserStore<IdentityUser>>().To<UserStore<IdentityUser>>();
            kernel.Bind<UserManager<IdentityUser>>().ToSelf();

            kernel.Bind<IAccountService>().To<AccountService>();
        }
    }
}

Here's my AccountController:

using System.Threading.Tasks;
using System.Web.Http;
using System.Web.ModelBinding;
using Microsoft.AspNet.Identity;
using RPT.Api.Models;
using RPT.Services.Interfaces;

namespace RPT.Api.Controllers
{
    [RoutePrefix("api/account")]
    public class AccountController : ApiController
    {
        #region Initialisation

        private readonly IAccountService _accountService;

        public AccountController(IAccountService accountService) : base()
        {
            _accountService = accountService;
        }

        #endregion

        #region Actions

        [AllowAnonymous]
        [Route("register")]
        public async Task<IHttpActionResult> Register(UserRegistrationViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var result = await _accountService.RegisterUser(model.UserName, model.Password);

            var errorResult = GetErrorResult(result);

            return errorResult ?? Ok();
        }

        #endregion

        #region Internal

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _accountService.Dispose();
            }

            base.Dispose(disposing);
        }
        private IHttpActionResult GetErrorResult(IdentityResult result)
        {
            if (result == null)
            {
                return InternalServerError();
            }

            if (result.Succeeded) return null;
            if (result.Errors != null)
            {
                foreach (var error in result.Errors)
                {
                    ModelState.AddModelError("", error);
                }
            }

            if (ModelState.IsValid)
            {
                // No ModelState errors are available to send, so just return an empty BadRequest.
                return BadRequest();
            }

            return BadRequest(ModelState);
        }

        #endregion
    }
}
like image 924
Hades Avatar asked Jun 12 '14 22:06

Hades


3 Answers

Did you modify your OWIN Startup class to call app.UseNinjectWebApi and app.UseNinjectMiddleware rather than calling app.UseWebApi?

Startup.cs in the Ninject Web API samples does this...

like image 164
Dean Ward Avatar answered Nov 09 '22 15:11

Dean Ward


What worked for me was adding the NuGet package Ninject.Web.WebApi.WebHost as described here: https://github.com/ninject/Ninject.Web.WebApi/wiki/Setting-up-an-mvc-webapi-application

like image 40
Matt Slavicek Avatar answered Nov 09 '22 14:11

Matt Slavicek


In my case, the reason was resolver could not find a mapping. That is suppose say HomeController has a dependency on IDumb, the resolver could not find a concrete implementation of Dumb with implements IDumb. In other words the error message

**No parameterless constructor defined for this object
An error occurred when trying to create a controller of type 'ToDoListT1.WebApp.Controllers.HomeController'. Make sure that the controller has a parameterless public constructor**

is completely misleading. In my case I just resolved by adding a reference to the project of the class Dumb. It should have been something like "No mapping for IDumb could be found.". I am not sure the problem is with NInject or MS. What ever it took me hours to find this out.

like image 23
VivekDev Avatar answered Nov 09 '22 14:11

VivekDev