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>();
Related
I am trying to inject the API dependency and MVC dependency. But when I try to inject the MVC Dependency I get the error:
The configuration is invalid. The following diagnostic warnings were
reported:
-[Lifestyle Mismatch] FeedbackDbRepository (Web Request) depends on ChatBotDbContext (Transient).
-[Disposable Transient Component] ChatBotDbContext is registered as transient, but implements IDisposable. See the Error property for
detailed information about the warnings. Please see
https://simpleinjector.org/diagnostics how to fix problems and how to
suppress individual warnings.
Which happens in the RegisterMvcDependencies() in here:
public static void RegisterWebApiDependencies()
{
//TODO: setup dependency injection for Web Api
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
container.Register<IAnswerGenerator, PxlAnswerGenerator>(Lifestyle.Singleton);
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
}
public static void RegisterMvcDependencies()
{
//TODO: setup dependency injection for MVC
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
container.Register<IFeedbackRepository, FeedbackDbRepository>(Lifestyle.Scoped);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
This is my application_start():
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
DependencyConfig.RegisterWebApiDependencies();
DependencyConfig.RegisterMvcDependencies();
}
It does work when I comment out RegisterMvcDependencies() how can I solve this?
EDIT ChatBotDbContext is registered here:
public class FeedbackDbRepository : IFeedbackRepository//TODO: implement IFeedbackRepository
{
private readonly ChatBotDbContext _context;
public FeedbackDbRepository(ChatBotDbContext context)
{
_context = context;
}
//Tip1: use async await
//Tip2: use SaveChangesAsync() instead of SaveChanges()
public async Task AddAsync(Feedback newFeedback)
{
_context.Feedbacks.Add(newFeedback);
await _context.SaveChangesAsync();
}
}
ChatBoxDBContext:
public class ChatBotDbContext : DbContext //TODO: inherit from some other class
{
public ChatBotDbContext()
: base("DefaultConnection")
{
}
public DbSet<Feedback> Feedbacks { get; set; }
public DbSet<User> Users { get; set; }
public static ChatBotDbContext Create()
{
return new ChatBotDbContext();
}
public static void SetInitializer()
{
//TODO: make sure Entity Framework creates the database if it does not exists and migrates an existing database to the latest version
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ChatBotDbContext, Migrations.Configuration>());
}
}
Change it to be a scoped service. From the docs:
Warning: Transient instances are not tracked by the container. This means that Simple Injector will not dispose transient instances. Simple Injector will detect disposable instances that are registered as transient when calling container.Verify(). Please view Diagnostic Warning - Disposable Transient Components for more information.
You can read more on the error here: https://simpleinjector.readthedocs.io/en/latest/disposabletransientcomponent.html
I have a MVC 5 project (framework 4.6.1), where I would like to load a POCO from appsettings.json.
My MVC app does not have a Startup.cs, starting point seems to be Global.asax.
I tried adding Owin to have a Startup.cs, but contrary to most articles I have found, Configuration seems to be a void method called during startup and not an IConfiguration as in net core.
This article pretty much attempts to do what I want, but also assumes that Configuration is an IConfiguration interface.
Ok here is what I ended up doing:
I wanted to load an object of class ScrumBan from my appsettings.json.
I declared this class
public class ChartConfiguration: IChartConfiguration
{
public Scrumban Scrumban { get; }
public ChartConfiguration()
{
var configuration = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
Scrumban = new Scrumban();
configuration.GetSection("Scrumban").Bind(Scrumban);
}
}
The interface only exposes the ScrumBan object:
public interface IChartConfiguration
{
Scrumban Scrumban { get; }
}
Then i included Unity for Dependency Injection handling and registered my interface:
public static class IocExtensions
{
public static void BindInRequestScope<T1, T2>(this IUnityContainer container) where T2 : T1
{
container.RegisterType<T1, T2>(new HierarchicalLifetimeManager());
}
}
public class UnityMvc5
{
public static void Start()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// Configuration object, one per request, ensure it is disposed
container.BindInRequestScope<IChartConfiguration, ChartConfiguration>();
return container;
}
}
Finally in Application_Start in Global.asax.cs I added the UnityMvc5.Start():
protected void Application_Start()
{
BundleConfig.RegisterBundles(BundleTable.Bundles);
AreaRegistration.RegisterAllAreas();
UnityMvc5.Start();
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
With Unity in place, I can now change my Controller constructors to include my IChartConfiguration interface and store it for future reference, exactly as is common practice with ASP.NET Core.
I am not quite sure about the instantiation model BindInRequestScope, I could have chosen the singleton, but as far as I can tell, the ChartConfiguration constructor is not called per request anyway. Similarly I am not sure of the value of reloadOnChange, but is not crucial to my app.
Hope this helps someone in a situation like mine.
I have the following constructor (only one for the controller):
[Authorize]
public class AccountController : Controller
{
public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager,
IAccountService accountSrv)
{
UserManager = userManager;
SignInManager = signInManager;
AccountService = accountSrv;
}
private IAccountService AccountService { get; }
private ApplicationSignInManager SignInManager { get; }
private ApplicationUserManager UserManager { get; }
And I'd like MVC to call it with proper parameters, so I tried this:
Global.asax.cs
public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
DALMapper.Mapping();
LabMapper.Mapping();
var container = new UnityContainer();
container
.RegisterType<IDALContext, DALContext>()
.RegisterType<IConsultantService, ConsultantService>()
.RegisterType<IProjectService, ProjectService>()
.RegisterType<IAccountService, AccountService>()
.RegisterType<AccountController, AccountController>()
.RegisterType<ApplicationUserManager, ApplicationUserManager>()
.RegisterType<ApplicationSignInManager, ApplicationSignInManager>()
.RegisterInstance<IAccountService>(new AccountService(new DALContext()), new ContainerControlledLifetimeManager())
;
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
(UnityDependencyResolver being:)
public class UnityDependencyResolver : IDependencyResolver
{
private readonly IUnityContainer _container;
public UnityDependencyResolver(IUnityContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _container.ResolveAll(serviceType);
}
catch
{
return new List<object>();
}
}
}
Where I register every types needed (the result feel weird though when in/from types are the same (I'm that new to Unity)).
But it doesn't work. (As far as I know, since MV3, the default controller factory will use the service locator, so one doesn't need to implement it's own factory).
What's wrong?
Current result:
Server Error in '/' Application.
No parameterless constructor defined for this object.
If I understand your problem correctly, there's a problem resolving the dependencies for ApplicationUserManager and ApplicationSignInManager.
This is the code that solved the problem for me:
//for accountcontroller
container.RegisterType<DbContext, ApplicationDBContext>(new HierarchicalLifetimeManager());
container.RegisterType<UserManager<ApplicationUser>>(new HierarchicalLifetimeManager());
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(new HierarchicalLifetimeManager());
container.RegisterType<IAuthenticationManager>(new InjectionFactory(o => HttpContext.Current.GetOwinContext().Authentication));
After digging it up more (downloaded the Unity source code, built it, added a reference to the dll, added the pdb to the symbols locations (debug))*, I could see the error was coming from another constructor which requirs parameters.
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store)
: base(store)
{
}
(I've yet to solve this, but that should be easy).
*is there an easier way to step into a third party library's code? Let me know in the comment.
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.
My ASP.Net MVC 4 Web API controller doesn't work with Unity.WebApi. In the same project simple controllers works with Unity.Mvc3 properly. But when I run Web API controller derived from ApiController I'm getting a message:
{"$id":"1","Message":"An error has occurred.","ExceptionMessage":"Type
'ElectricTests.Controllers.Api.DocumentsController' does not have a
default
constructor","ExceptionType":"System.ArgumentException","StackTrace":"
at System.Linq.Expressions.Expression.New(Type type)\r\n at
System.Web.Http.Internal.TypeActivator.Create[TBase](Type
instanceType)\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)"}
My ApiController:
public class DocumentsController : ApiController
{
private readonly IDocumentsRepository _repository;
public DocumentsController(IDocumentsRepository repository) {
_repository = repository;
}
public IEnumerable<FormattedDocument> GetFormattedDocuments()
{
return _repository.GetAllFormattedDocuments();
}
...
Bootstrapper.cs:
public static class Bootstrapper {
public static void Initialise() {
IUnityContainer container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
private static IUnityContainer BuildUnityContainer() {
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterType<IDocumentsRepository, DocumentsRepository>();
container.RegisterType<IQuestionsRepository, QuestionsRepository>();
container.RegisterType<ITestRepository, TestsRepository>();
return container;
}
}
Where is my mistake?
The handling of Controller and ApiController is different as they have completely different base classes:
I use Unity.MVC4 library for controller DI (http://www.nuget.org/packages/Unity.MVC4/)
Install-Package Unity.MVC4
and Unity.WebAPI for DI (http://www.nuget.org/packages/Unity.WebAPI/)
Install-Package Unity.WebAPI
Your bootstrapper should be a combination of both:
DependencyResolver.SetResolver(new Unity.Mvc4.UnityDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
Note I also had to do to add some registration to get the Help page to work
container.RegisterInstance(typeof (HttpConfiguration), GlobalConfiguration.Configuration);
As the owner of Unity.MVC4 I am looking at getting WebApi implemented within our library.
When you install Unity for ASP.NET Web API, it does everything except add the following line to your Global.asax
Bootstrapper.Initialise();
So you need to add that to your Application_Start method:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
Bootstrapper.Initialise();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}