4
votes

I'm trying to add Ninject to a WCF service using the WCF Ninject extension.

I'm getting the error:

The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor. To fix the problem, add a default constructor to the type, or pass an instance of the type to the host.

The service has the Ninject Service Host factory:

<%@ ServiceHost Language="C#" Debug="true" CodeBehind="SchedulingSvc.svc.cs"
          Service="Scheduling.SchedulingSvc"
          Factory="Ninject.Extensions.Wcf.NinjectWebServiceHostFactory" %>

The global.asax file inherits from NinjectHttpApplication and CreateKernel returns a new Kernel with A NinjectModule:

public class Global : NinjectHttpApplication
{
    protected override IKernel CreateKernel()
    {
        return new StandardKernel(new NinjectServiceModule());
    }
}

The NinjectModule:

public class NinjectServiceModule : NinjectModule
{
    public override void Load()
    {
        this.Bind<ISchedulingService>().To<SchedulingSvc>();
        this.Bind<ISchedulingBusiness>().To<SchedulingBusiness>();
    }
}

The service with constructor injection:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class SchedulingSvc : ISchedulingService
{
    private ISchedulingBusiness _SchedulingBusiness = null;

    public SchedulingSvc(ISchedulingBusiness business)
    {
        _SchedulingBusiness = business;
    }

    public CalendarEvent[] GetCalendarEvents()
    {
        var calendarEvents = _SchedulingBusiness.GetCalendarEvents();
        return calendarEvents;
    }
    ...
}

The service with property injection:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class SchedulingSvc : ISchedulingService
{
    [Inject] public ISchedulingBusiness _SchedulingBusiness { get; set; }

    public SchedulingSvc()
    {
    }

    public CalendarEvent[] GetCalendarEvents()
    {
        var calendarEvents = _SchedulingBusiness.GetCalendarEvents();
        return calendarEvents;
    }
    ...
}

If I use constructor inject, I get the error mentioned at the top of the post. If I try to use property injection, the _ScheduleBusiness is always null.

What am I missing?

3
Have you registered all required dependencies for SchedulingBusiness?mipe34
@mipe34 Yes. When I plug the business into a console app with Ninject, all works as expected.もしもし

3 Answers

1
votes

The only time I encounter that error message is when attempting to use an Interceptor (through using the Ninject.Extensions.Interceptor library and/or Castle DynamicProxy.) That is the part that doesn't like constructors with parameters.

Otherwise, this should be working fine. It doesn't seem like you're using any Interceptors, so may I ask what is the purpose of this?:

this.Bind<ServiceHost>().To<NinjectServiceHost>();

I assume you're using some kind of custom service host here, but it shouldn't be necessary for what you're trying to do. All you need to get your above code working is:

1: The Factory attribute in the service markup (you have this) 2: The constructor dependency bound in your kernel (you have this)

I have this exact setup working right now, so I think something in your NinjectServiceHost is causing this problem and attempting to attach an interceptor of some sort.

1
votes

Okay, I think this should do it. Your Ninject setup may be off. I've had this happen before, as there are several "methods" to setting it up, but some of them don't always work.

I see you're using AspNet compatibility mode and hosting this through a Web project. You're using Ninject.Web, correct? You actually don't need to have your Global inherit from Ninject. Remove all Ninject references and code from Global, and get rid of your NinjectServiceModule. If you installed Ninject.Web from NuGet, it should have created file "NinjectWebCommon.cs" in your App_Start folder. This is where you set up your bindings, like so:

    private static IKernel CreateKernel()
    {
        var settings = new NinjectSettings { InjectNonPublic = true };

        var kernel = new StandardKernel(settings);
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

        RegisterServices(kernel);

        return kernel;
    }

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

It should already have those methods in there, with most of them already populated, so you should only have to populate RegisterServices with your bindings.

There should also be a NinjectWeb.cs in your App_Start folder. You shouldn't have to make changes to it; just verify it exists.

You may also need to change the Factory attribute in your service markup back to "Ninject.Extensions.Wcf.NinjectServiceHostFactory" afterward. Or try them both and see what works.

These 2 files are all it takes to get Ninject working. Try going down this route; I have a hunch it will fix it.

0
votes

I think WCF (or any web) service requires a parameter less constructor to instantiate a service. Since you have provided a parameterised constructor, Ninject might not have been able to initialize your service.

Pls. refer to this link as well http://social.msdn.microsoft.com/Forums/vstudio/en-US/550d82eb-a2bc-4c08-b846-e3fb1b966457/no-parameterless-constructor-error-in-wcf