Why might similar .NET Core services behave differently? - c#

I have two .net core 2.2 services, InitialisationHandler and WorkingTicketHandler, one holds initial information and the other is intended to hold a working ticket.
The InitialisationHandler always has its information ready when asked, but the WorkingTicketHandler always returns a null record.
I need to figure out how to have WorkingTicketHandler hold on to its data just like InitialisationHandler does.
Both are added to as transient in ConfigureServices, and created as identically as possible.
There is one key difference, the InitialisationHandler has its data created during startup by its constructor method and is only ever read from thereafter, whereas the WorkingTicketHandler is written to by a controller and re read in the same controller (Get vs Post).
using VTModels.Other;
namespace VT_Online22.Infrastructure.Services
{
/// <summary>
/// Interface for the WorkingTicket Service
/// </summary>
public interface IWorkingTicketHandler
{
WorkingTicket GetWorkingTicket();
void SaveWorkingTicket(WorkingTicket argWorkingTicket);
void ClearWorkingTicket();
}
/// <summary>
/// WorkingTicket service class definition
/// </summary>
public class WorkingTicketHandler : IWorkingTicketHandler
{
public WorkingTicketHandler()
{
this.WorkingTicket = new WorkingTicket();
}
public WorkingTicket GetWorkingTicket()
{
return this.WorkingTicket;
}
public void SaveWorkingTicket(WorkingTicket arg_WorkingTicket)
{
this.WorkingTicket = arg_WorkingTicket;
}
public void ClearWorkingTicket()
{
this.WorkingTicket = new WorkingTicket();
}
private WorkingTicket WorkingTicket;
private static readonly log4net.ILog logger = log4net.LogManager.GetLogger(typeof(WorkingTicketHandler));
}
}
using Microsoft.Extensions.Configuration;
using SharedModels.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
using VT_OnlineCore.Infrastructure.Other;
using VTModels.Models;
namespace VT_Online22.Infrastructure.Services
{
/// <summary>
/// Interface for the Initialization Service
/// </summary>
public interface IInitializationHandler
{
void Initialize();
CConfigMasterBase GetConfig();
IEnumerable<CScopeMasterBase> GetScopes(string clientId);
}
/// <summary>
/// Initialization service class definition
/// </summary>
public class InitializationHandler : IInitializationHandler
{
public InitializationHandler(IConfiguration configTech)
{
ConfigurationTech = configTech;
Initialize();
}
public void Initialize()
{
this.ldh = new LocalDataHandler(logger, this.ConfigurationTech);
this.config = new CConfigMasterBase();
LoadConfig();
}
public IEnumerable<CScopeMasterBase> GetScopes(string clientId)
{
IEnumerable<CScopeMasterBase> scopes = new List<CScopeMasterBase>();
scopes = this.ldh.GetScopes(clientId);
return scopes;
}
public CConfigMasterBase GetConfig()
{
return this.config;
}
private async Task LoadConfig()
{
this.config = this.ldh.GetConfig();
}
private LocalDataHandler ldh;
private CConfigMasterBase config;
private IEnumerable<CScopeMasterBase> scopes;
private static readonly log4net.ILog logger = log4net.LogManager.GetLogger(typeof(InitializationHandler));
public IConfiguration ConfigurationTech { get; private set; }
}
}
services.AddTransient<IInitializationHandler,InitializationHandler>();
services.AddTransient<IWorkingTicketHandler, WorkingTicketHandler>();

Related

Implementing "Repository Rotator" factory

I have .Net Core Web API application. There is some Get method in controller and injected IRepositoryProviderFactory. Nothing special.
[ApiController]
public class DataController : ControllerBase
{
private readonly ILogger<DataController> _logger;
private readonly IRepositoryProviderFactory _repositoryProviderFactory;
#region ctor
/// <summary>
/// ctor
/// </summary>
public DataController(ILogger<DataController> logger, IRepositoryProviderFactory repositoryProviderFactory)
{
_logger = logger;
_repositoryProviderFactory = repositoryProviderFactory;
}
[HttpPost]
public async Task<IActionResult> GetData([FromBody] SearchModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
try
{
var data = await _repositoryProviderFactory.GetDataAsync(model);
return Ok(data);
}
catch (Exception ex)
{
return StatusCode((int)HttpStatusCode.InternalServerError);
}
}
}
There are repositories based on the same Interface to get data from different data sources.
public Repository1: IDataRepository {}
public Repository2: IDataRepository {}
public Repository3: IDataRepository {}
I'm using DI so all parts are registered in services as Scoped or Transients. Some repositories are using EntityFramework.
services.AddScoped<IDataRepository, Repository1>();
services.AddScoped<IDataRepository, Repository2>();
services.AddScoped<IDataRepository, Repository3>();
Ok, now I need to implement RepositoryProviderFactory to return repository. But there is one required functionality: it must return for every call different repository.
I have injected IEnumerable and I need to return Repository1, Repository2, Repository3 and again Repository1, … etc. So all repositores are used the same time.
/// <summary>
/// ctor
/// </summary>
public RepositoryProviderFactory(
ILogger<RepositoryProviderFactory> logger,
IEnumerable<IDataRepository> dataRepositories)
{
_logger = logger;
_dataRepositories = dataRepositories;
}
public IDataRepository GetRepository()
{
// TODO: Logic to cycle repositories
var instance = dataRepositories.Where();
return instance;
}
How to do this?
Factory can't be registered as Singleton, because repositories have another dependencies that have Scoped Lifetime (DbContext etc.)
How can I create some thread safe singleton object to be able persists last used repository and serve another one, for another call?
Well, I did it this way.
I made class GlobalAppData and registered is as Singleton.
services.AddSingleton<GlobalAppData>();
Then I made simple implementation (not finished yet).
public class GlobalAppData
{
private IDataRepository[] _availableRepositories;
private IDataRepository_lastUsedRepository;
/// <summary>
/// ctor
/// </summary>
public GlobalAppData()
{
_availableRepositories = new IDataRepository[0];
}
public void TryRegisterRepositories(IEnumerable<IDataRepository> repositories)
{
if (_availableRepositories.Length > 0)
{
return;
}
_availableRepositories = repositories.ToArray();
_lastUsedRepository = null;
}
public IDataRepository GetNextRepository()
{
if (_lastUsedRepository == null)
{
_lastUsedRepository = _availableRepositories[0];
return _lastUsedRepository;
}
var lastUsedIndex = _availableRepositories.IndexOf(_lastUsedRepository);
if (lastUsedIndex < _availableRepositories.Length - 1)
{
lastUsedIndex++;
}
else
{
lastUsedIndex = 0;
}
_lastUsedRepository = _availableRepositories[lastUsedIndex];
return _lastUsedRepository;
}
}
Then because of DI there will be stored original instances, not injected ones, I made just simple compare in factory.
var instanceData = _globalAppData.GetNextRepository();
var instance = _repositories.SingleOrDefault(r => r.GetType() == instanceData.GetType());
Not perfect, but it works as a start.

An entity object cannot be referenced by multiple instances of IEntityChangeTracker when saving to the database

I'm trying to save my objects to my local database. We are using Microsoft Entity Framework and Ninject. Currently when I try to save my object I get the 'An entity object cannot be referenced by multiple instances of IEntityChangeTracker.' error. We are able to get data from the database currently, it is saving data that is causing problems.
The error is given the moment the savetickets function is called, Visual studio displays the error in the repository at context.Tickets.add(ticket). I have tried passing a single object instead of a list and saving that, this has however caused the same error.
We apply the same principle of creating repositories in other controllers as well for getting data from the database before we get to this part of the code where I'm trying to save tickets.
We have added a Ninject binding
kernel.Bind<ITicketRepository>().To<TicketRepository>();
Our EFDBContext looks like this
public class EFDbContext : DbContext
{
public DbSet<Ticket> Tickets { get; set; }
// Other Entities
public EFDbContext() : base("EFDbContext"){
}
}
The interface for the ticketrepository looks like this
public interface ITicketRepository
{
// Other functions
void SaveTickets(List<Ticket> tickets);
}
The repository implementing this interface looks like this
public class TicketRepository : ITicketRepository
{
private EFDbContext context = new EFDbContext();
// Other functions
public void SaveTickets(List<Ticket> tickets)
{
foreach (var item in tickets)
{
context.Tickets.Add(item);
}
context.SaveChanges();
}
}
The moment all of this is called is in my printtickets function. This is the only time the ticketrepository is created and called for in the code.
public class ReservationController : Controller
{
// Other repositories
private ITicketRepository ticketRepository;
public ReservationController(IMovieOverviewRepository movieRepository, IShowRepository showRepository, ITicketRepository ticketRepository)
{
// Other repositories
this.ticketRepository = ticketRepository;
}
// Other code
[HttpGet]
public ActionResult PrintTickets()
{
List<Ticket> tickets = (List<Ticket>)TempData["TicketList"];
ticketRepository.SaveTickets(tickets);
// Irrelevant stuff
}
}
EDIT: Our full ninject configuration. NinjectWebCommon.cs
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();
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)
{
System.Web.Mvc.DependencyResolver.SetResolver(new Sprint123.WebUI.Infrastructure.NinjectDependencyResolver(kernel));
}
}
And NinjectDependencyResolver.cs
namespace Sprint123.WebUI.Infrastructure
{
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()
{
kernel.Bind<IShowRepository>().To<ShowRepository>();
kernel.Bind<ITicketRepository>().To<TicketRepository>();
kernel.Bind<IMovieOverviewRepository>().To<MovieOverviewRepository>();
}
}
}

Error with dependency injections

I trying create generic repository for ms sql db. Earlier i worked with something like this but with mongo db. I can compile project. but when i trying sent request i see error: "An error occurred when trying to create a controller of type 'EmployeeController'. Make sure that the controller has a parameterless public constructor." can anybody help me?
namespace TestTask.Util
{public class NinjectDependencyResolver
{
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()
{
// repository
kernel.Bind<IEmployeeRepository>().To<EmployeeRepository>();
}
}
controller
namespace TestTask.Controllers
{
[RoutePrefix("api/v1")]
public class EmployeeController : ApiController
{
private readonly IEmployeeRepository _employeeRepository;
public EmployeeController(IEmployeeRepository employeeRepository) : base()
{
_employeeRepository = employeeRepository;
}
[HttpGet]
[Route("getItems")]
public IHttpActionResult GetItems(int take = 8, int skip = 0)
{
if(take<1|| skip < 0)
{
ModelState.AddModelError("Error", "Invalid take or skip params.");
return BadRequest(ModelState);
}
var result = _employeeRepository.Find(x => x.Id >= 0, x=>x.Id, take, skip);
return Ok(result);
}
[HttpGet]
[Route("pageCount")]
public IHttpActionResult PageCount(int itemsInPage)
{
var TotalCount = _employeeRepository.Count(x => x.Id >= 0);
var result = Math.Ceiling((double)TotalCount / (double)itemsInPage);
return Ok(result);
}
}
}
generic repository
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using System.Web;
namespace TestTask.Context
{
public abstract class GenericRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
private DefaultConnection context = new DefaultConnection();
public virtual List<TEntity> Find(Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, object>> order, int take =50, int skip=0) //where TEntity : class
{
return context.Set<TEntity>().Where(predicate).OrderBy(order).Skip(skip).Take(take).ToList();
}
public virtual int Count(Expression<Func<TEntity, bool>> predicate)
{
return context.Set<TEntity>().Where(predicate).Count();
}
}
}
I had to do this a while back and remember it not being as straight forward with Web API as it is with MVC.
I posted details and a demo project as part of a unit of work example here, and github project here.
Below are the pieces for configuring dependency injection with Ninject.
UnitOfWorkExample.WebApi/Controllers/ProductsController.cs
namespace UnitOfWorkExample.WebApi.Controllers
{
[RoutePrefix("products")]
public class ProductsController : ApiController
{
private IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService;
}
[Route]
public IHttpActionResult GetProducts()
{
// ensure there are products for the example
if (!_productService.GetAll().Any())
{
_productService.Create(new Product { Name = "Product 1" });
_productService.Create(new Product { Name = "Product 2" });
_productService.Create(new Product { Name = "Product 3" });
}
return Ok(_productService.GetAll());
}
}
}
UnitOfWorkExample.WebApi/App_Start/NinjectWebCommon.cs
namespace UnitOfWorkExample.WebApi.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using Ninject.Extensions.Conventions;
using System.Web.Http;
using UnitOfWorkExample.Domain.Helpers;
using UnitOfWorkExample.Data.Helpers;
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();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
// Install our Ninject-based IDependencyResolver into the Web API config
GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(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)
{
// unit of work per request
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
// default binding for everything except unit of work
kernel.Bind(x => x.FromAssembliesMatching("*").SelectAllClasses().Excluding<UnitOfWork>().BindDefaultInterface());
}
}
}
UnitOfWorkExample.WebApi/App_Start/NinjectDependencyResolver.cs
namespace UnitOfWorkExample.WebApi.App_Start
{
public class NinjectScope : IDependencyScope
{
protected IResolutionRoot resolutionRoot;
public NinjectScope(IResolutionRoot kernel)
{
resolutionRoot = kernel;
}
public object GetService(Type serviceType)
{
IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
return resolutionRoot.Resolve(request).SingleOrDefault();
}
public IEnumerable<object> GetServices(Type serviceType)
{
IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
return resolutionRoot.Resolve(request).ToList();
}
public void Dispose()
{
IDisposable disposable = (IDisposable)resolutionRoot;
if (disposable != null) disposable.Dispose();
resolutionRoot = null;
}
}
public class NinjectResolver : NinjectScope, IDependencyResolver
{
private IKernel _kernel;
public NinjectResolver(IKernel kernel)
: base(kernel)
{
_kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectScope(_kernel.BeginBlock());
}
}
}
ASP.NET does not inject anything into controllers by default. Instead, it looks for a matching controller and just uses new. So it needs a controller that has a default constructor with no parameters-- unless you do something special to add DI.
To add dependency injection to your controllers, you need to register a custom controller factory. The factory should use Ninject to instantiate the controller, which will automatically populate its constructor arguments with the appropriate dependencies. Here is a bare bones example (you will need to modify it to allow other controller types, as well as implement the rest of the interface):
public class CustomControllerFactory : IControllerFactory
{
public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
{
return _kernel.Get<EmployeeController>();
}
}
You can register it in startup with code like this:
protected void Application_Start()
{
IControllerFactory factory = new CustomControllerFactory();
ControllerBuilder.Current.SetControllerFactory(factory);
}
More info can be found here. The blogger shows you exactly the error that you are seeing and then fixes it.

BasicAuthHttpModule custom property resolve at runtime

I have a problem with ASP .NET Web API. I have followed the tutorial http://www.asp.net/web-api/overview/security/basic-authentication and I have succesfully used it with sample code. However I would like to bind it with my AuthenticationService that I have made:
public class AuthenticationService : IAuthenticationService
{
private readonly GenericRepository<User> _userRepository;
public AuthenticationService(GluEntities entites)
{
_userRepository = new GenericRepository<User>(entites);
}
public bool Authenticate(string userName, string password)
{
var user = _userRepository.Get(x => x.UserName == userName).FirstOrDefault();
if (user == null || user.Password != password)
{
return false;
}
return true;
}
}
i tried to tie it up with my sample code as follows:
public class BasicAuthHttpModule : IHttpModule
{
private const string Realm = "GluService";
private readonly IAuthenticationService _authenticationService;
public BasicAuthHttpModule(IAuthenticationService authenticationService)
{
_authenticationService = authenticationService;
}
/... some irrelevant methods that are explained in the link
private bool CheckPassword(string username, string password)
{
return _authenticationService.Authenticate(username, password);
}
}
I am trying to resolve _authenticationService with ninject however the application throws Conustructor not found error at runtime. Any idea how can I resole _authenticationService at runtime so I can achieve maintainability and testability?
Http modules are unlikely to be resolved by an ioc container, however, if you refactor your code to use an authentication filter rather than http module, you should be able to set up the mvc internal service locator to resolve your filter.
Take a look at this tutorial by Rick Strahl
http://www.west-wind.com/weblog/posts/2013/Apr/18/A-WebAPI-Basic-Authentication-Authorization-Filter
and the IFilterProvider example
Property Injection into Web API's `System.Web.Http.Filters.ActionFilterAttribute`
Thanks to Wiktor I was able to glue together a code that actually works. Here is relevant code for future help. Other classes are in Wiktors' links.
public class NinjectFilterProvider : ActionDescriptorFilterProvider, IFilterProvider
{
private readonly IKernel _kernel;
public NinjectFilterProvider(IKernel kernel)
{
_kernel = kernel;
}
public IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
var filters = base.GetFilters(configuration, actionDescriptor);
foreach (var filter in filters)
{
_kernel.Inject(filter.Instance);
}
return filters;
}
}
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();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
//Support WebApi
GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
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<TCountingRepository>().To<CountingRepository>();
//kernel.Bind<CountingContext>().To<CountinContext>();
kernel.Bind<IAuthenticationService>().To<AlwaysAcceptAuthenticationService>();
kernel.Bind<IFilterProvider>().To<NinjectFilterProvider>();
}
}
Here is filter
public class GluAuthenticationFilter : BasicAuthenticationFilter
{
[Inject]
public IAuthenticationService AuthenticationService { get; set; }
public GluAuthenticationFilter()
{ }
public GluAuthenticationFilter(bool active)
: base(active)
{ }
protected override bool OnAuthorizeUser(string username, string password, HttpActionContext actionContext)
{
return AuthenticationService.Authenticate(username, password);
}
}

Singleton Scope binding not working as intended

I am using the ninject mvc3 plugin with my web api application. I have a binding that looks like:
kernel.Bind<IFoo>().To<Foo>().InSingletonScope();
It is my interpretation that the kernal will create exactly one instance of Foo and reuse it appropriately. By putting a breakpoint in Foo's constructor, I can clearly see that it is getting called once per request, and I cannot explain why.
My only guess is that somehow a new kernel is getting created per request, but that doesn't appear to be the case, as the CreateKernel method which sets the global dependency resolver is only getting run once in the application lifetime.
I am using some code taken from this post to make ninject play nice with mvc 4. Because of framework changes, I had to make an additional wrapper that I assign to GlobalConfiguration.Configuration.DependencyResolver:
public class NinjectResolver : NinjectScope, IDependencyResolver
{
private readonly IKernel _kernel;
public NinjectResolver(IKernel kernel)
: base(kernel)
{
_kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectScope(_kernel.BeginBlock());
}
}
What am I doing wrong?
I never could get it to work properly, and I am not sure why. My guess is it has something to do with MVC4 integration being a bit immature at the moment.
As an alternative I am using:
kernel.Bind<IFoo>().ToConstant(new Foo());
This seems to work, but I am not too happy with it.
Like previously mentioned it does look like a bug.
One option is to simply implement a singleton extension method yourself:
public static class NinjectSingletonExtension
{
public static CustomSingletonKernelModel<T> SingletonBind<T>(this IKernel i_KernelInstance)
{
return new CustomSingletonKernelModel<T>(i_KernelInstance);
}
}
public class CustomSingletonKernelModel<T>
{
private const string k_ConstantInjectionName = "Implementation";
private readonly IKernel _kernel;
private static object padlock = new Object();
private T _concreteInstance;
public CustomSingletonKernelModel(IKernel i_KernelInstance)
{
this._kernel = i_KernelInstance;
}
public IBindingInNamedWithOrOnSyntax<T> To<TImplement>(TImplement i_Constant = null) where TImplement : class, T
{
_kernel.Bind<T>().To<TImplement>().Named(k_ConstantInjectionName);
var toReturn =
_kernel.Bind<T>().ToMethod(x =>
{
if (i_Constant != null)
{
return i_Constant;
}
if (_concreteInstance == null)
{
lock (padlock)
{
if (_concreteInstance == null)
{
_concreteInstance = _kernel.Get<T>(k_ConstantInjectionName);
}
}
}
return _concreteInstance;
}).When(x => true);
return toReturn;
}
}
And then simply use:
i_Kernel.SingletonBind<T>().To<TImplement>();
Rather then
i_Kernel.Bind<T>().To<TImplement>().InSingletonScope();
Certainly arriving late to this thread but it just happened to me with a Windows Service hosting OWIN for Web API controllers and resolving dependencies with Ninject, InSingletonScope() wasn't working until I did the following:
var kernel = new StandardKernel();
...
kernel.Bind<Foo>().ToSelf().InSingletonScope();
kernel.Bind<IFoo>().ToMethod(context => context.Kernel.Get<Foo>());
...
// Controllers ask for the dependency as usual...
public class SomeController : ApiController
{
readonly IFoo _foo;
public SomeController(IFoo foo)
{
_foo = foo;
}
...
Hope this helps
Note: I used nuget to install ninject & ninject.web.mvc (which I'm sure you did as well).
I'm not able to see the rest of your code, but here's what I had in my "NinjectDependencyScope" class. (I think yours is just called NinjectScope, might be some other naming inconsistencies with your code)
public class NinjectDependencyScope : IDependencyScope
{
private IResolutionRoot _resolver;
internal NinjectDependencyScope(IResolutionRoot resolver)
{
Contract.Assert(resolver != null);
_resolver = resolver;
}
#region IDependencyScope Members
public void Dispose()
{
var disposable = _resolver as IDisposable;
if (disposable != null)
disposable.Dispose();
_resolver = null;
}
public object GetService(Type serviceType)
{
if (_resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return _resolver.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (_resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return _resolver.GetAll(serviceType);
}
#endregion
}
And here is my NinjectWebCommon class (located in App_Start folder):
using System;
using System.Web;
using System.Web.Http;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Modules;
using Ninject.Web.Common;
[assembly: WebActivator.PreApplicationStartMethod(typeof(ABCD.Project.Web.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(ABCD.Project.Web.App_Start.NinjectWebCommon), "Stop")]
namespace ABCD.Project.Web.App_Start
{
public static class NinjectWebCommon
{
private static readonly Bootstrapper Bootstrap = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
Bootstrap.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
Bootstrap.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
// Set Web API Resolver
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(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)
{
//var modules = new INinjectModule[] { new NinjectBindingModule(), };
//kernel.Load(modules);
Here's where you would load your modules or define your bindings manually...
}
}
}

Categories