Hairydruidy
Hairydruidy

Reputation: 107

dryioc controller.service is resolved during setup, not during api call

I have been searching a lot, both online, and debugging, re-read docs for dryioc and took a look at the samples. I don't think my issues lies with dryioc, or maybe I'm overlooking a silly mistake.

Project setup => service => owin + webapi2 Using attributerouting, swagger and apiversioning

This is how I setup my container

private IContainer SetupDependencyInjection(HttpConfiguration config)
{
        var container = new Container();
        container.WithWebApi(config, throwIfUnresolved: type => typeIsController());
        container.RegisterWebApiControllers(config);
        container.Register<IObjectFactory, ObjectFactory>(Reuse.Singleton);

        RegisterStoreServices(container);
        RegisterMetadata(container);

        var validate = container.Validate();
        var verify = container.VerifyResolutions();
        if (validate.Any() || verify.Any())
        {
            throw new Exception("Error occured while setting up service dependencies.");
        }

        using (var c = container.OpenScope(Reuse.WebRequestScopeName))
        {
            var songController = c.Resolve<Musify.WebApi.Controllers.v1._0.SongsController>();
            var GenresController = c.Resolve<Musify.WebApi.Controllers.v1._0.GenresController>();
        }
        return container;
}

Both RegisterStoreServices and RegisterMetadata only contain singleton or transient registrations.

When I try to call a controller method on my API controller, I get the following error

    {
  "message": "An error has occurred.",
  "exceptionMessage": "An error occurred when trying to create a controller of type 'SongsController'. 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.<SendAsync>d__1.MoveNext()",
  "innerException": {
    "message": "An error has occurred.",
    "exceptionMessage": "Unable to resolve Musify.Api.Service.Data.ISongRepository as parameter \"songRepository\"\r\n  in scoped Musify.WebApi.Controllers.v1._0.SongsController.\r\nWhere no service registrations found\r\n  and number of Rules.FallbackContainers: 0\r\n  and number of Rules.UnknownServiceResolvers: 0",
    "exceptionType": "DryIoc.ContainerException",
    "stackTrace": "   at DryIoc.Throw.It(Int32 error, Object arg0, Object arg1, Object arg2, Object arg3)\r\n   at DryIoc.Container.ThrowUnableToResolve(Request request)\r\n   at DryIoc.Container.DryIoc.IContainer.ResolveFactory(Request request)\r\n   at DryIoc.ReflectionFactory.CreateExpressionOrDefault(Request request)\r\n   at DryIoc.Factory.GetExpressionOrDefault(Request request)\r\n   at DryIoc.Factory.GetDelegateOrDefault(Request request)\r\n   at DryIoc.Container.ResolveAndCacheDefaultDelegate(Type serviceType, Boolean ifUnresolvedReturnDefault, IScope scope)\r\n   at DryIoc.Container.DryIoc.IResolver.Resolve(Type serviceType, Boolean ifUnresolvedReturnDefault)\r\n   at DryIoc.WebApi.DryIocDependencyScope.GetService(Type serviceType)\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)"
  }
    }

I know that in a lot of cases, this is because the service is not registered, but I did.

container.Register<ISongRepository, SongRepository>(Reuse.Singleton);

As you can see in the fist code snippet, I valide, verify, and I even tried container.openscope, to see if the container was registered. And on the container, I can see the songrepository being filled in as well.

So I'm guessing, somehow, the webapi doesn't use the controllers inujected into the container.

Am I doing something wrong in my dependency setup?

public void Configuration(IAppBuilder appBuilder)
    {
        SetupLogging();

        var config = new HttpConfiguration();
        SetupRouting(config);
        SetupVersioning(config);
        SetupJson(config);
        SetupDocumentation(config);
        SetupDependencyInjection(config);
        appBuilder.UseWebApi(config);
        appBuilder.UseErrorPage(ErrorPageOptions.ShowAll);
    }

I'm not sure if it matters, but I'm setting the container up, after everything else has been configured.

Upvotes: 1

Views: 498

Answers (1)

Hairydruidy
Hairydruidy

Reputation: 107

After some messing around, I got it working after adding the lines marked with //this

var container = SetupDependencyInjection(config);
        appBuilder.UseDryIocOwinMiddleware(container); //this
        appBuilder.UseWebApi(config);
        appBuilder.UseDryIocWebApi(config); //this

I would like an explenation though, if someone could give me one. Because on another post, I read that a guy had problems because of using both UseWebApi and UseDryIocWebApi.

But without the OwinMiddleware, it still wouldn't work. So what do both of these functions accomplish?

Or did I use a "wrong fix"?

Upvotes: 1

Related Questions