I have created a basic Web API project with a single controller and trying to use the Unity MVC Bootstrapper package from NuGet. Unfortunately when I try and visit the URL http://localhost/api/runtypes it throws the error
{"Message":"An error has occurred.","ExceptionMessage":"Type
'SE.FlexApplication.WebApi.Controllers.RunTypeController' 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 controller class
public class RunTypeController : ApiController
{
private readonly IStaticTypesRepository _staticTypesRepository;
private readonly IDataModelConverter _dataModelConverter;
private readonly IBusinessModelConverter _businessModelConverter;
public RunTypeController(IStaticTypesRepository staticTypesRepository, IDataModelConverter dataModelConverter, IBusinessModelConverter businessModelConverter)
{
_staticTypesRepository = staticTypesRepository;
_dataModelConverter = dataModelConverter;
_businessModelConverter = businessModelConverter;
}
public RunType[] Get()
{
return _staticTypesRepository.GetRunTypes().Select(r => _dataModelConverter.Convert(r)).ToArray();
}
public HttpResponseMessage Post(RunType type)
{
_staticTypesRepository.AddRunType(_businessModelConverter.Convert(type));
_staticTypesRepository.Save();
var response = Request.CreateResponse(System.Net.HttpStatusCode.Created, type);
return response;
}
}
And the Unity activator
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(SE.FlexApplication.WebApi.App_Start.UnityWebActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(SE.FlexApplication.WebApi.App_Start.UnityWebActivator), "Shutdown")]
namespace SE.FlexApplication.WebApi.App_Start
{
/// <summary>Provides the bootstrapping for integrating Unity with ASP.NET MVC.</summary>
public static class UnityWebActivator
{
/// <summary>Integrates Unity when the application starts.</summary>
public static void Start()
{
var container = UnityConfig.GetConfiguredContainer();
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
/// <summary>Disposes the Unity container when the application is shut down.</summary>
public static void Shutdown()
{
var container = UnityConfig.GetConfiguredContainer();
container.Dispose();
}
}
}
Unity Config class
public class UnityConfig
{
#region Unity Container
private static readonly Lazy<IUnityContainer> Container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
/// <summary>
/// Gets the configured Unity container.
/// </summary>
public static IUnityContainer GetConfiguredContainer()
{
return Container.Value;
}
#endregion
/// <summary>Registers the type mappings with the Unity container.</summary>
/// <param name="container">The unity container to configure.</param>
/// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to
/// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
public static void RegisterTypes(IUnityContainer container)
{
try
{
//container.RegisterInstance<IUnitOfWork>(new ProdUnitOfWork());
container.RegisterType<IEventRepository, EventRepository>();
container.RegisterType<IModelRepository, ModelRepository>();
container.RegisterType<ISecurityRepository, SecurityRepository>();
container.RegisterType<IStaticTypesRepository, StaticTypesRepository>();
container.RegisterType<IDataModelConverter, DataToModelConverter>();
container.RegisterType<IBusinessModelConverter, ModelToDataConverter>();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
It seems like the Controller isn't picking up that it should be using the Unity Dependency resolver for constructor injection. I've followed all the steps on the tutorials online. Have I missed something basic?
Related
I'm developing a web app that uses Ninject Data injection in my ASP.NET MVC5 project. I set up an NinjectDependencyResolver that inherits from IDependencyResolver like this:
public class NinjectDependencyResolver : IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver(IKernel kernelParam)
{
kernel = kernelParam;
AddBindings();
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
private void AddBindings()
{
// here I have all my bindings set up
kernel.Bind<ProConnect.Domain.Abstract.IMyRepository>().To<MyRepository>();
}
}
and here is the NinjectWebCommon class that is fired on application launch and that registers the services:
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(MyApp.WebUI.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(MyApp.WebUI.App_Start.NinjectWebCommon), "Stop")]
namespace ProConnect.WebUI.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using Ninject.Web.Common.WebHost;
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)
{
// creating the bridge between the NinjectDependencyResolver class and the MVC support for dependency injection.
System.Web.Mvc.DependencyResolver.SetResolver(new
MyApp.WebUI.Infrastructure.NinjectDependencyResolver(kernel));
// maybe I have to add some code here to create the bridge between
// NinjectDependencyResolver class and my standard classes that
// have nothing to do with MVC????
}
}
}
I use this to inject Repository object coming from the domain into my MVC controllers and this all works perfectly well.
The problem I have is that I would like to inject some other Repository Objects into a Settings Class that will retrieve some settings data from the database. Since my settings class is not a MVC controller but just a plain old class, it doesn't figure out how to inject the data.
Could some one help me on this one? I tried to set up again data injection like this but it didn't work:
public class Settings
{
private Domain.Abstract.ISettingRepository settingRepository;
private StandardKernel kernel;
public Settings()
{
this.kernel = new StandardKernel();
// I don't know if this loads a new kernel or the one that is used in the rest of the MVC application
kernel.Load(Assembly.GetExecutingAssembly());
// I tryed re-specifying the bindings but this didn't help
kernel.Bind<Domain.Abstract.ISettingRepository>().To<Domain.Concrete.SettingRepository>();
this.settingRepository = kernel.Get<Domain.Abstract.ISettingRepository>();
}
public void DoSomethigWithSettings(){
this.settingRepository.Settings()......
}
}
Ok I figured out the answer thanks to https://stackoverflow.com/a/19585471/11011693
I simply had get the object I wanted to inject in a non MVC class from the current MVC DependencyResolver that is set up on Application Start
public class Settings
{
private Domain.Abstract.ISettingRepository settingRepository;
public Settings()
{
// simply get the object you want to inject in a non MVC class
// from the current MVC DependencyResolver that is set up on Application Start
this.settingRepository = (Domain.Abstract.IAppSettingService)System.Web.Mvc.DependencyResolver.Current.GetService(typeof(Domain.Abstract.IAppSettingService));
}
public void DoSomethigWithSettings(){
this.settingRepository.Settings()......
}
}
I did not managed to find any similar example, so I decided to ask the question.
I am using Autofac to register my service layer interfaces and I am wondering, can I inject one into App.xaml.cs?
I am having my own log service, that I want to run in case of fatal error in the application.
As far as I know similar way you can inject dependency to the window, can I do it the same in App.xaml.cs?
public partial class App : Application
{
private readonly ILogService _log;
public App()
{
}
public App(ILogService log) : this()
{
_log = log;
}
async Task App_DispatcherUnhandledExceptionAsync(object sender, DispatcherUnhandledExceptionEventArgs e)
{
_log.Error("App.xaml.cs exception: " + e.Exception.Message);
await _log.SaveAllLinesAsync();
e.Handled = true;
}
}
Autofac IoC:
public class BootStrapper
{
/// <summary>
/// IoC container
/// </summary>
/// <returns></returns>
public static IContainer BootStrap()
{
var builder = new ContainerBuilder();
builder.RegisterType<EventAggregator>()
.As<IEventAggregator>().SingleInstance();
builder.RegisterType<LogService>()
.As<ILogService>().SingleInstance();
builder.RegisterType<DeleteView>().AsSelf();
builder.RegisterType<DeleteViewModel>().AsSelf().SingleInstance();
builder.RegisterType<PhraseView>().AsSelf();
builder.RegisterType<PhraseViewModel>().AsSelf().SingleInstance().WithParameter(new NamedParameter("searchPhrase", ""));
builder.RegisterType<PopulateDictionaries>().AsSelf().SingleInstance();
return builder.Build();
}
}
IoC initializing in ViewModelLocator:
public class ViewModelLocator
{
IContainer _container;
public ViewModelLocator()
{
_container = BootStrapper.BootStrap();
}
//view models below
}
If you want to inject the App class with a dependency, you should define a custom Main method where you instantiate the App class:
public class Program
{
[STAThread]
public static void Main(string[] args)
{
ILogService logService = ...;
App app = new App(logService);
app.InitializeComponent();
app.Run();
}
}
If you do this, remember to change the Build Action of App.xaml from ApplicationDefinition to Page.
I have a web api application in which I'd like to use Owin, Oauth and Ninject , So I have this configuration
Dependency injector
public class NinjectDependencyResolver : IDependencyResolver
{
private static IKernel kernel;
public NinjectDependencyResolver()
{
kernel = new StandardKernel();
// AddBindings();
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
private static void AddBindings()
{
kernel.Bind<INotifier>().To<Notifier>();
kernel.Bind<IEventRepository>().To<EventRepository>();
kernel.Bind<ICrud<Config>>().To<CrudConfig>();
kernel.Bind<ICrud<Evenement>>().To<CrudEvent>();
kernel.Bind<IAccount>().To<Account>();
}
public static Lazy<IKernel> CreateKernel = new Lazy<IKernel>(() =>
{
//var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
AddBindings();
return kernel;
});
}
StartUp class
public partial class Startup
{
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
public static string PublicClientId { get; private set; }
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public static void ConfigureAuth(IAppBuilder app)
{
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Configure the application for OAuth based flow
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
// In production mode set AllowInsecureHttp = false
AllowInsecureHttp = true
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
//app.UseNinjectMiddleware(CreateKernel);
}
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseNinjectMiddleware(() => NinjectDependencyResolver.CreateKernel.Value);
app.UseNinjectWebApi(config);
ConfigureAuth(app);
}
}
Global.cs
protected void Application_Start()
{
DependencyResolver.SetResolver(new NinjectDependencyResolver());
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
I have this class also
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)
{
}
}
and I have this api controller :
public class AccountController : BaseController
{
#region ctors
public AccountController()
{
}
[Inject]
public AccountController(INotifier _notifierParam, IAccount _IAccount)
{
Notifier = _notifierParam;
Account = _IAccount;
}
#endregion
}
which derived from BaseController which is a class with no contructor.
the problem is when I make a call to service of the account controller I get this exception :
"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":" à
System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage
request, HttpControllerDescriptor controllerDescriptor, Type
controllerType)\r\n à
System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage
request)\r\n à
System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()",
"InnerException":{
"Message":"An error has occurred.",
"ExceptionMessage":"Error activating INotifier\r\nNo matching bindings are available, and the type is not
self-bindable.\r\nActivation path:\r\n 4) Injection of dependency
INotifier into parameter _notifierParam of constructor of type
AccountController\r\n 3) Injection of dependency AccountController
into parameter resolutionRoot of constructor of type NamedScope\r\n
2) Injection of dependency NamedScope into parameter resolutionRoot of
constructor of type OwinNinjectDependencyResolver\r\n 1) Request for
IDependencyResolver\r\n\r\nSuggestions:\r\n 1) Ensure that you have
defined a binding for INotifier.\r\n 2) If the binding was defined in
a module, ensure that the module has been loaded into the kernel.\r\n
3) Ensure you have not accidentally created more than one kernel.\r\n
4) If you are using constructor arguments, ensure that the parameter
name matches the constructors parameter name.\r\n 5) If you are using
automatic module loading, ensure the search path and filters are
correct.\r\n",
"ExceptionType":"Ninject.ActivationException",
"StackTrace":" à Ninject.KernelBase.Resolve(IRequest request)\r\n à Ninject.Planning.Targets.Target1.GetValue(Type
service, IContext parent)\r\n à
Ninject.Planning.Targets.Target1.ResolveWithin(IContext parent)\r\n
à Ninject.Activation.Providers.StandardProvider.GetValue(IContext
context, ITarget target)\r\n à
Ninject.Activation.Providers.StandardProvider.<>c__DisplayClass4.b__2(ITarget
target)\r\n à
System.Linq.Enumerable.WhereSelectArrayIterator2.MoveNext()\r\n à
System.Linq.Buffer1..ctor(IEnumerable1 source)\r\n à
System.Linq.Enumerable.ToArray[TSource](IEnumerable1 source)\r\n à
Ninject.Activation.Providers.StandardProvider.Create(IContext
context)\r\n à Ninject.Activation.Context.ResolveInternal(Object
scope)\r\n à Ninject.Activation.Context.Resolve()\r\n à
Ninject.KernelBase.<>c__DisplayClass15.b__f(IBinding
binding)\r\n à
System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()\r\n
à System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable1
source)\r\n à
Ninject.Web.WebApi.NinjectDependencyScope.GetService(Type
serviceType)\r\n à
System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage
request, Type controllerType, Func`1& activator)\r\n à
System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage
request, HttpControllerDescriptor controllerDescriptor, Type
controllerType)"} }
So I need to know :
What is the reason of this error?
How can I fix it?
You are mixing Dependency Injection approaches. Your are using OWIN for setting the ninject middleware for Web API but then you are managing Web API outside of OWIN (using the IIS pipeline):
protected void Application_Start()
{
//..
GlobalConfiguration.Configure(WebApiConfig.Register);
//..
}
The second mistake is that you are creating multiple Kernels, and your exception message is warning you to avoid this:
Ensure you have not accidentally created more than one kernel
Start by refactoring your code. Manage Web API using only OWIN:
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseNinjectMiddleware(() => NinjectDependencyResolver.CreateKernel.Value);
ConfigureAuth(app);
app.UseNinjectWebApi(config);
}
and remove this line from Global.asax.cs:
GlobalConfiguration.Configure(WebApiConfig.Register);
Then ensure you are creating only one Kernel for the entire application lifetime. You should have only one static instance of the Kernel, and reference it from any other object that needs it.
I have a custom AuthorizationFilter Attribute on my Web Api project like this
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class GenericAuthenticationFilter : AuthorizationFilterAttribute
{
/// <summary>
/// Public default Constructor
/// </summary>
public GenericAuthenticationFilter()
{
}
private readonly bool _isActive = true;
/// <summary>
/// parameter isActive explicitly enables/disables this filter.
/// </summary>
/// <param name="isActive"></param>
public GenericAuthenticationFilter(bool isActive)
{
_isActive = isActive;
}
/// <summary>
/// Checks basic authentication request
/// </summary>
/// <param name="filterContext"></param>
public override void OnAuthorization(HttpActionContext filterContext)
{
if (!_isActive) return;
var identity = FetchAuthHeader(filterContext);
if (identity == null)
{
ChallengeAuthRequest(filterContext);
return;
}
var genericPrincipal = new GenericPrincipal(identity, null);
Thread.CurrentPrincipal = genericPrincipal;
if (!OnAuthorizeUser(identity.Name, identity.Password, filterContext))
{
ChallengeAuthRequest(filterContext);
return;
}
base.OnAuthorization(filterContext);
}
My StartUpClass is like this
public class Startup
{
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
// Get your HttpConfiguration. In OWIN, you'll create one
// rather than using GlobalConfiguration.
var config = new HttpConfiguration();
WebApiConfig.Register(config);
IoC.Instance.RegisterApiControllers(Assembly.GetExecutingAssembly());
config.DependencyResolver =
new AutofacWebApiDependencyResolver(IoC.Instance.GetComponentsContainer());
// Register your Web Api controllers.
IoC.Instance.RegisterApiControllers(Assembly.GetExecutingAssembly());
IoC.Instance.RegisterWebApiModelBinders(Assembly.GetExecutingAssembly());
IoC.Instance.RegisterWebApiModelBinderProvider();
IoC.Instance.RegisterWebApiFilterProvider(config);
// Register the Autofac middleware FIRST, then the Autofac Web API middleware,
// and finally the standard Web API middleware.
app.UseAutofacMiddleware(IoC.Instance.GetComponentsContainer());
app.UseAutofacWebApi(config);
app.UseWebApi(config);
}
}
and my IoC class where all dependencies are resolved is like this
public class IoC : ContainerBuilder
{
/// <summary>
///
/// </summary>
private readonly static IoC _instance = new IoC();
/// <summary>
///
/// </summary>
private static object _lock;
/// <summary>
///
/// </summary>
private IContainer _componentsContainer;
/// <summary>
///
/// </summary>
public static IoC Instance
{
get
{
return _instance;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public IContainer GetComponentsContainer()
{
if (_componentsContainer == null)
{
lock (_lock)
{
if (_componentsContainer == null)
_componentsContainer = this.Build();
}
}
return _componentsContainer;
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T Resolve<T>() where T : class
{
return GetComponentsContainer().Resolve<T>();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public ILifetimeScope BeginLifetimeScope()
{
return GetComponentsContainer().BeginLifetimeScope();
}
/// <summary>
///
/// </summary>
private IoC()
{
_lock = new object();
ConfigureDependencies();
}
/// <summary>
///
/// </summary>
private void ConfigureDependencies()
{
//Configure all your depedendencies here!!
//Database connection
var connectionString = ConfigurationManager.ConnectionStrings["DBConnectionStringName"].ConnectionString;
this.Register(c => new SqlConnection(connectionString)).As<IDbConnection>().InstancePerRequest();// InstancePerLifetimeScope();
//Database Connection OrmLite
OrmLiteConfig.DialectProvider = SqlServerDialect.Provider;
//Register Repositories
this.RegisterType<Repository>().As<IRepository>().InstancePerRequest();// InstancePerLifetimeScope();
// Register Services
this.RegisterType<UserService>().As<IUserService>().InstancePerRequest();// InstancePerLifetimeScope();
this.RegisterType<TokenService>().As<ITokenService>().InstancePerRequest();
this.RegisterType<DKMenuService>().As<IDKMenuService>().InstancePerRequest();// InstancePerLifetimeScope();
this.RegisterType<DKGRIDTblService>().As<IDKGRIDTblService>().InstancePerRequest();// InstancePerLifetimeScope();
this.RegisterType<FKService>().As<IFKService>().InstancePerRequest();// InstancePerLifetimeScope();
this.RegisterType<LOVService>().As<ILOVService>().InstancePerRequest();// InstancePerLifetimeScope();
this.RegisterType<JobService>().As<IJobService>().InstancePerRequest();// InstancePerLifetimeScope();
this.RegisterType<MADEService>().As<IMADEService>().InstancePerRequest();// InstancePerLifetimeScope();
}
}
And I decorate my Controllers with this filter like this
[GenericAuthenticationFilter]
public AuthenticateController(ITokenService tokenService)
{
_tokenService = tokenService;
}
My Problem is that the OnAuthorazation method of the GenericAuthenticationFilter is never fired.
If on the IoC Class class I change InstancePerRequest to InstancePerLifetimeScope everything works ok, but I want my dependencies to work per Request
Any Ideas?
I'm not sure if this is part or all of your issue, but... you can only build a ContainerBuilder once. In Startup.Configuration() I see on lines 11-12:
config.DependencyResolver =
new AutofacWebApiDependencyResolver(IoC.Instance.GetComponentsContainer());
And IoC.Instance.GetComponentsContainer() calls Build() to create the container.
But just two lines later I see you're adding more components to the container, and after that I see a second call:
app.UseAutofacMiddleware(IoC.Instance.GetComponentsContainer());
Based on your code, that's going to be the same container that was built before you added the new registrations. The container won't include the API controllers, the model binders, or the filter provider.
I'm actually not sure why you're not having more problems than you're having now.
Try moving the setting of the containers (the calls to IoC.Instance.GetComponentsContainer()) until all the way at the end, after you've finished registering all of your dependencies.
The only configuration that worked was the following
public class Startup
{
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
// Get your HttpConfiguration. In OWIN, you'll create one
// rather than using GlobalConfiguration.
var config = new HttpConfiguration();
WebApiConfig.Register(config);
// Register your Web Api controllers.
IoC.Instance.RegisterApiControllers(Assembly.GetExecutingAssembly());
IoC.Instance.RegisterWebApiModelBinders(Assembly.GetExecutingAssembly());
IoC.Instance.RegisterWebApiModelBinderProvider();
config.DependencyResolver =
new AutofacWebApiDependencyResolver(IoC.Instance.GetComponentsContainer());
// Register your Web Api controllers.
//IoC.Instance.RegisterApiControllers(Assembly.GetExecutingAssembly());
//IoC.Instance.RegisterWebApiModelBinders(Assembly.GetExecutingAssembly());
//IoC.Instance.RegisterWebApiModelBinderProvider();
// Register the Autofac middleware FIRST, then the Autofac Web API middleware,
// and finally the standard Web API middleware.
app.UseAutofacMiddleware(IoC.Instance.GetComponentsContainer());
app.UseAutofacWebApi(config);
app.UseWebApi(config);
}
}
I am still not sure whether it is right.
Examples of usage. I have a filter like the following
public class ApiAuthenticationFilter : GenericAuthenticationFilter
{
/// <summary>
/// Default Authentication Constructor
/// </summary>
public ApiAuthenticationFilter()
{
}
}
A method in this filter is using a service which is resolved like this
protected override bool OnAuthorizeUser(string username, string password, HttpActionContext actionContext)
{
var provider = actionContext.Request.GetDependencyScope().GetService(typeof(IUserService)) as IUserService;
}
My controllers on the other hand do not have parameterless constructors and the dependencies are resolved automatically
public class DKMenuController : ApiController
{
#region Private variable.
private readonly ITokenService _tokenService;
private readonly IDKMenuService _dkMenuService;
private readonly IUserService _userservice;
private const string Token = "Token";
#endregion
#region Public Constructor
/// <summary>
/// Public constructor to initialize DKMenu service instance
/// </summary>
public DKMenuController(ITokenService tokenService, IUserService userservice, IDKMenuService dkMenuService)
{
_tokenService = tokenService;
_dkMenuService = dkMenuService;
_userservice = userservice;
}
}
I don't know whether it is correct but it works
In MVC 5 we get this account controller that looks like this.
public class AccountController : Controller
{
public AccountController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new DatePickerDbContext())))
{
}
public AccountController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
}
I installed Ninject to handle my dependency injection. I have two repositories, that I want to use in my AccountController
and the code now looks like this
public class AccountController : Controller
{
private readonly ILicenserepository _licenserepository;
private readonly IUserRepository _userRepository;
public AccountController(ILicenserepository licenserepository, IUserRepository userRepository)
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new DatePickerDbContext())))
{
_licenserepository = licenserepository;
_userRepository = userRepository;
}
public AccountController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
}
in ninject.web.common this is what i've done
private static void RegisterServices(IKernel kernel)
{
kernel.Bind(typeof (ILicenserepository)).To(typeof (Licenserepository));
kernel.Bind(typeof (IUserRepository)).To(typeof (UserRepository));
}
but when I run the application i get the error on browser that says no parametereless constructor found. And if i create parameter less constructor my repositories doesn't get instantiated. So wherever i called the method from repository the value is null.
How can I solve this problem? Or make MVC or Ninject know which constructor to call?
You need a DependencyResolver registered in Global.asax.cs
Registration would look something like this:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
RegisterDependencyResolver();
}
private void RegisterDependencyResolver()
{
var kernel = new StandardKernel();
// you may need to configure your container here?
RegisterServices(kernel);
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
}
And the DependencyResolver
public class NinjectDependencyResolver : IDependencyResolver
{
private readonly IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
{
this.kernel = kernel;
}
public object GetService(Type serviceType)
{
return this.kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return this.kernel.GetAll(serviceType);
}
catch (Exception)
{
return new List<object>();
}
}
}
This is an update:
If your are using MVC5 and WebAPI 2 then all you need to do is use NuGet Manager and add NinjectMVC5 and NinjectWebApi2 into your project. Then the error goes away. (Using Visual Studio 2013)
Cheers
I just got this working without issue using .NET MVC 5 and Ninject 3.3.4.
Steps Taken:
Install Ninject 3.3.4
Install Ninject.Web.Common 3.3.1
Install Ninject.Web.Common.WebHost 3.3.1
Install Ninject.MVC5 3.3.0 (for use with an MVC Controller)
(Optional) Api Controller Steps
Install Ninject.Web.WebApi 3.3.0 (for use with an api ApiController)
Install Ninject.Web.WebApi.WebHost (for use with an ApiController)
The important distinction here is whether your project uses Api Controllers or Mvc Controllers. If you are unfamiliar with the difference please check out the below post:
Difference between ApiController and Controller in ASP.NET MVC.
Note: I did not have to do any extra configuration to my Ninject.Web.Common.cs file. Below is my configuration omitting my bindings
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(YourProject.Web.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(YourProject.Web.App_Start.NinjectWebCommon), "Stop")]
namespace YourProject.Web.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using Ninject.Web.Common.WebHost;
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)
{
// Common
// Repositories
// Services
// Factories
// Misc
}
}
}