I have a WebAPI controller that (should) looks like this:
public class MyController : ApiController
{
private IRepository repository;
public MyController(IRepository repository)
{
this.repository = repositor;
}
// REST implementations
}
WebApiConfig is configured like that:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Unity configuration
var container = new UnityContainer();
container
.RegisterType<IRepository , CustomRepository>();
config.DependencyResolver = new UnityResolver(container);
// Web API routes
// CORS
}
}
then in Global.asax.cs I have something like:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
}
// CORS
protected void Application_BeginRequest(object sender, EventArgs e)
{
// some CORS config
}
}
and finally I have a Startup.cs:
[assembly: OwinStartup(typeof(Path.To.Startup))]
namespace ZeroCode.ConfigurazioneServizio.Web.Api
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
new Mapping().Bootstrap();
}
}
}
To me everything looks ok, the code builds and I can launch the controller but as soon I make a request I get error cause parameterless constructor isn't present.
So I've added the default constructor but this will instantiate the controller so IRepository will never be injected.
I've searched for a possible solution. One of them tried to implement IHttpControllerActivator and so i've realized something like this:
public class UnityHttpControllerActivator : IHttpControllerActivator
{
private IUnityContainer _container;
public UnityHttpControllerActivator(IUnityContainer container)
{
_container = container;
}
public IHttpController Create(System.Net.Http.HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
return (IHttpController)_container.Resolve(controllerType);
}
}
At this point I've modified the WebApiConfig.cs inserting this line
config.Services.Replace(typeof(IHttpControllerActivator), new UnityHttpControllerActivator(container));
right after the config.DependencyResolver but this doesn't resolve the issue and exception is raised inside the Create method. I don't know what else I can do.
There's a nice little Nuget Package - Unity.Webapi. If you add that, you can simply plug in your container into your HttpConfiguration
public static void Register(HttpConfiguration config)
{
// Unity configuration
var container = new UnityContainer();
container.RegisterType<IRepository , CustomRepository>();
config.DependencyResolver = new UnityResolver(container);
//this
config.DependencyResolver = new UnityDependencyResolver(container);
// Web API routes
// CORS
}
Then you can bypass the extra class and web.config changes.
The first answer states to add Unity.WebApi. It is correct. After adding this package use it as is described in this link Using Unity.Mvc5 and Unity.WebApi together in a project. I did like this and my problem was solved.
With version 5 or higher for unity, you will have to add the Unity.AspNet.WebApi NuGet package. Then you can simply follow the instructions in the NuGet package to register your types and register your dependency resolver like the below:
using Unity.AspNet.WebApi;
config.DependencyResolver = new UnityDependencyResolver(container);
Link to NuGet package: https://github.com/unitycontainer/aspnet-webapi
You need to set up Unity as the dependency resolver for WebAPI.
Add the following NuGet package to your project: https://www.nuget.org/packages/Unity.WebAPI/
And then configure WebAPI to use the right resolver adding the following to your WebApiConfig.cs
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
This is 3 step process :
Register
Resolve
Link resolver to GlobalConfiguration
It appears you have not added resolving code and neither does above solutions.
Add this line before attaching DependencyResolver to GlobalConfiguration.
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
I had the same problem. For me the solution to this exact error was that all other controllers constructors also was loaded at request time.
And one of them had not a valid parameter in the constructor. It was not registered with Unity.
So I got the resolution fail from Unity.
But after fixing that other controller everything worked fin.
Related
I am trying to inject my logger as dependency in a .Net Framework 4.7.2 web api project by following these instructions:
https://scottdorman.blog/2016/03/17/integrating-asp-net-core-dependency-injection-in-mvc-4/
This works great for MVC web application but fails on the webapi project with the "parameterless constructor missing" error.
How do I successfully inject using just the default assembly: Microsoft.Extensions.DependencyInjection in framework?
public class Startup
{
public void Configuration(IAppBuilder app)
{
var services = new ServiceCollection();
ConfigureServices(services);
var resolver = new DefaultDependencyResolver(services.BuildServiceProvider());
DependencyResolver.SetResolver(resolver);
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersAsServices(typeof(Startup).Assembly.GetExportedTypes()
.Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
.Where(t => typeof(IController).IsAssignableFrom(t)
|| t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)));
services.AddSingleton<IMyInterface , MyClass>();
}
}
public class DefaultDependencyResolver : IDependencyResolver
{
protected IServiceProvider serviceProvider;
public DefaultDependencyResolver(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
public object GetService(Type serviceType)
{
return this.serviceProvider.GetService(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return this.serviceProvider.GetServices(serviceType);
}
}
public static class ServiceProviderExtensions
{
public static IServiceCollection AddControllersAsServices(this IServiceCollection services,
IEnumerable<Type> controllerTypes)
{
foreach (var type in controllerTypes)
{
services.AddTransient(type);
}
return services;
}
}
Getting "Parameterless constructor is missing" error with an injection like this:
private IMyInterface _my;
public HomeController(IMyInterface my)
{
_my= my;
}
Registration Explanation
One issue is that you are registering your DependencyResolver with the MVC resolver registration API which unfortunately is different from the WebAPI resolver registration API. What you want to do instead is:
public void Configuration(IAppBuilder app)
{
var services = new ServiceCollection();
ConfigureServices(services);
var resolver = new DefaultDependencyResolver(services.BuildServiceProvider());
HttpConfiguration config = new HttpConfiguration();
config.DependencyResolver = resolver;
app.UseWebApi(config);
}
Also note that the IDependencyResolver interface is defined separately in System.Web.Http, so your DefaultDependencyResolver class needs to be updated to derive from it instead.
One thing that has changed on that interface is that there is a BeginScope API. To implement that, call the CreateScope Extension Method exposed on IServiceProvider in Microsoft.Extensions.DependencyInjection to get a new scope. Then pass the provider from that scope to a new instance of your DefaultDependencyResolver.
public IDependencyScope BeginScope()
{
return new DefaultDependencyResolver(this.serviceProvider.CreateScope().ServiceProvider);
}
Full Example
The blog example you were following for MVC was using OWIN. When I set out to make a full example, I hit the same error as you, and it was because I hadn't correctly configured OWIN so Startup was never being called. Here is a full working example of Microsoft.Extensions.DependencyInjection being used to inject into both MVC and WebAPI Controllers:
https://github.com/ryandle/MVC_WebApi_DI_Example
Are you using [Serializable] on your HomeController? If so, when using it you need a constructor without parameters.
Try add this: public HomeController() { } and run again.
More info: parameter less constructor error
Here's my UnityConfig.cs:
public class UnityConfig
{
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
RegisterTypes(container);
return container;
});
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IProjectContext, ProjectContext>(new PerRequestLifetimeManager());
}
}
Here's my UnityWebApiActivator.cs:
public static class UnityWebApiActivator
{
public static void Start()
{
Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
var container = UnityConfig.GetConfiguredContainer();
var resolver = new Microsoft.Practices.Unity.WebApi.UnityDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
}
public static void Shutdown()
{
var container = UnityConfig.GetConfiguredContainer();
container.Dispose();
}
}
Stepping through the code, I can see my container getting created with the appropriate registrations.
Here is a sample WebAPI controller:
[Authorize]
public class ProjectApiController : BaseApiController
{
private readonly ProjectService _projectService;
public ProjectApiController(ProjectService projectService)
{
_projectService = projectService;
}
[Route("api/project")]
[AcceptVerbs("POST")]
public HttpResponseMessage SendProject(ProjectDto projectDto)
{
return Request.CreateResponse(HttpStatusCode.OK, _projectService.SendProject(GetUsername(), projectDto));
}
}
While my ProjectService constructor looks like this:
public class ProjectService : BaseService
{
public readonly ProjectContext _db;
public readonly NotificationService _notificationService;
public ProjectService(ProjectContext db, NotificationService notificationService)
{
_db = db;
_notificationService = notificationService;
}
// methods here
}
Both MVC controllers and API controllers depend on ProjectService, yet WebAPI requests behave differently. When an MVC request is served, I get a single instance of ProjectContext created as desired. When a WebAPI request is served, every injection creates a new instance. This is not desired.
Why is this happening?
Update:
Per the below answer, I have changed
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
to
DependencyResolver.SetResolver(new UnityHierarchicalDependencyResolver(container));
This resulted in:
The type
Microsoft.Practices.Unity.WebApi.UnityHierarchicalDependencyResolver
does not appear to implement
Microsoft.Practices.ServiceLocation.IServiceLocator. Parameter name:
commonServiceLocator
Which led me here, where the recommended solution leads to:
I currently have:
Unity 4.0.1
Unity.AspNet.WebApi 4.0.1
Unity.Mvc 4.0.1
Unity.MVC5 1.2.3
Upgrading packages is last-resort right now.
We had similar issue with our dbContext (EF Core) in net core 2.2 app along with SimpleInjector library. The dbContext lifetime was not getting set properly irrespective of whatever lifetime value we provided. The worst part was that the failure was intermittent making it even harder to figure it out.
What we discovered was we were registering dbContext twice, once in netcore's DI container and second time with SimpleInjector container which was causing all sorts of issues.
Hence, I would recommend to check if you are also registering it twice. Just fyi, if it is the case, then recommendation would be to get rid of one them as setting same lifetime values did not work for us.
I am pretty new to DI pattern. I was trying to implement DI in one of my controller classes. But the service is not resolved by Unity. Here is what I have done:
Using Unity.MVC5 package:I have the following class:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<IProductServices, ProductServices>();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
I have registered my service in the above class.
next i called this class from global.asax as below:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
UnityConfig.RegisterComponents();
}
Following is my controller:
private readonly IProductServices productServices;
/// <summary>
/// Public constructor to initialize product service instance
/// </summary>
public ProductController(IProductServices p)
{
this.productServices = p;
}
When i run the application, it throws an error saying the "there is no parameterless constructor present". Am i doing something wrong? Any help will be appreciated. All the tutorials I have researched do the same thing.
I finally found the reason. I was trying to implement unity in a Web API project using unity.mvc hoping that it would be the same. The error was resolved after the installed the unity.Asp.webapi package. Silly me.
This question already has an answer here:
How to inject webapi AccountController in WebApi
(1 answer)
Closed 5 years ago.
My controller is like :
public class AccountController : ApiController
{
private const string LocalLoginProvider = "Local";
private ApplicationUserManager _userManager;
private readonly ApplicationRoleManager _roleManager;
public AccountController()
{
}
public AccountController(ApplicationUserManager userManager,
ISecureDataFormat<AuthenticationTicket> accessTokenFormat,
ApplicationRoleManager roleManager)
{
UserManager = userManager;
AccessTokenFormat = accessTokenFormat;
_roleManager = roleManager;
}
}
In UnityConfig.cs I try to configure like this way :
public static void RegisterTypes(IUnityContainer container)
{
// NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
// container.LoadConfiguration();
// TODO: Register your types here
container.RegisterType<AccountController>(new InjectionConstructor());
container.RegisterType<ApplicationUserManager>();
container.RegisterType<ApplicationRoleManager>();
container.RegisterType<ISecureDataFormat<AuthenticationTicket>, SecureDataFormat<AuthenticationTicket>>();
}
In WebApiConfig.cs :
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
UnityConfig.RegisterTypes(container);
//Set the unity container as the default dependency resolver
config.DependencyResolver = new UnityHierarchicalDependencyResolver(container);
}
}
And in Global.asax.cs :
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register); // At the beginning, register with HttpConfiguration
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
But when i try to retrieve role using roleManager (var role = await _roleManager.FindByIdAsync(model.RoleId);) it says :
Object reference not set to an instance of an object.
I see there is a similar question here, but it can't solve my problem.
Based on how the code in the question looks I believe you are using Unity bootstrapper for ASP.NET Web API which should wire up a UnityDependencyResolver.
container.RegisterType<AccountController>(new InjectionConstructor());
This registers the AccountController and instructs Unity to use the paramterless constructor. This is why all of your dependencies are null. If you want to use the other constructor remove the AccountController registration and Unity will use the constructor with the most parameters. However if you do this then you will get a runtime error attempting to resolve the AccountController because ISecureDataFormat<> is not registered and Unity will not know how to map that interface to a concrete type.
If you register a mapping to SecureDataFormat<> then there are some additional dependencies that will need to be registered.
container.RegisterType(typeof(ISecureDataFormat<>), typeof(SecureDataFormat<>));
container.RegisterType<ITextEncoder, Base64UrlTextEncoder>()
container.RegisterType<IDataSerializer<AuthenticationTicket>, TicketSerializer>()
container.RegisterType<IDataProtector>(new ContainerControlledLifetimeManager(),
new InjectionFactory(c => new DpapiDataProtectionProvider().Create("App Name")));
Note that the above registrations are not tested. Not sure if you should configure OWIN with data protection (and perhaps get the protection provider from the OWIN config).
The following two registrations are not strictly required since Unity knows how to resolve a concrete type without a registration and no additional InjectionMembers are being provided (e.g. lifetime, parameters overrides etc.).
container.RegisterType<ApplicationUserManager>();
container.RegisterType<ApplicationRoleManager>();
Following the answer from this other post I am trying to configure autofac for both an ASP .Net MVC 5 project and a Web Api 2 one.
For the Web Api project I used the Autofac.Integration.WebApi library that I referenced it manually to the project and modified the Global.asax file like so:
public class WebApiApplication : HttpApplication
{
protected void Application_Start()
{
ConfigureDiContainer();
GlobalConfiguration.Configure(WebApiConfig.Register);
}
private static void ConfigureDiContainer()
{
var servicesAssembly = Assembly.GetExecutingAssembly();
var container = BuildContainer(servicesAssembly);
var resolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
}
private static IContainer BuildContainer(Assembly servicesAssembly)
{
var x = new ActivityBl();
var builder = new ContainerBuilder();
builder.RegisterApiControllers(servicesAssembly);
var appAssemblies = AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => a.ToString().StartsWith("SC."))
.ToArray();
builder.RegisterAssemblyTypes(appAssemblies).AsImplementedInterfaces();
builder.RegisterAssemblyTypes(servicesAssembly).AsImplementedInterfaces();
return builder.Build();
}
}
And when I run the services this works as expected.
For the MVC 5 project I installed the Autofac.Integration.Mvc library from NuGet and modified the Global.asax code as well:
public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
The controllers in both projects have no default constructor, only the ones with the dependencies:
MVC Controller:
private readonly IActivitiesService activitiesService;
public HomeController(IActivitiesService activitiesService)
{
this.activitiesService = activitiesService;
}
Web Api Controller:
public class ActivitiesController : ApiController, IActivitiesService
{
private readonly IActivities activitiesBl;
public ActivitiesController(IActivities activitiesBl)
{
if(activitiesBl == null) throw new ArgumentNullException("activitiesBl", "ActivitiesBl dependency was not properly created.");
this.activitiesBl = activitiesBl;
}
}
When I run the application I get the following error:
None of the constructors found with
'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type
'SC.Web.Controllers.HomeController' can be invoked with the available
services and parameters: Cannot resolve parameter
'SC.Services.ServiceContracts.IActivitiesService activitiesService' of
constructor 'Void
.ctor(SC.Services.ServiceContracts.IActivitiesService)'.
In a way I guess it makes sense since the IoC on the web project has no definitions for the services and it seems that it is trying to resolve the whole dependency tree which leads me to the following questions:
From the names of the libraries it seems that each one is specifically tailored for each kind of project, is that so or can I use the Mvc one also for the Web Api?
Have things changed in such a way that the recommendation I got from the previous post is no longer valid and now I must have all the definitions in the Composition Root for each client?
What would be now the best way of configuring the dependencies hierarchy in this kind of multi-layered setup?
Thank you.
I have many common dependencies coming from several projects, including Web Api (using the Web Api Autofac integration), Quartz Scheduling, unit tests, data migration console apps etc.
For this, I have been able to initiate the ContainerBuilder in the manner expected by the project and then I just pass it into some code that exists in a separate project to specify the shared dependencies.
You might have the following 3 projects
MyApp.WebApi
var builder = new ContainerBuilder();
builder.RegisterApiControllers(servicesAssembly);
CommonContainerConfig.RegisterDependencies(builder);
MyApp.Mvc5
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
CommonContainerConfig.RegisterDependencies(builder);
MyApp.Common
public static class CommonContainerConfig
{
public static void RegisterDependencies(ContainerBuilder builder)
{
builder.RegisterType<ActivitiesService>().As<IActivitiesService>();
//etc
}
}
This works for my scenario, although I'm not 100% sure it's what you're after...