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...
}
}
}
Related
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>();
}
}
}
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.
iam using ninject.web in my aspx page in this way
my problem is with Nhibernate session management.
this is my ninject module:
public override void Load()
{
Bind<IUnitOfWork>().To<UnitOfWork>();
Bind<IAttivitaRepository>().To<AttivitaRepository>();
}
the page_load and quite every button in a single page create and dispose a unit of work at this way:
using (iuow)
{
iuow.DoSomething();
iuow.SaveAll();
}
in pageLoad works, but every other attempt in the page to use iuow with a new Using block, return that session is closed
this is my UoW impl:
public UnitOfWork()
{
_nhHelper = new SessionFactory();
InizializzaSessione();
_transaction = _session.BeginTransaction();
}
private void InizializzaSessione()
{
if (_session == null)
{
_session = _nhHelper.OpenSession();
}
Area = new AreaRepository(this._session);
Attivita = new AttivitaRepository(this._session);
Societa = new SocietaRepository(this._session);
Persona = new PersonaRepository(this._session);
}
/// <summary>
/// Salva le modifiche sulla base dati
/// </summary>
public void SaveAll()
{
if (_transaction != null)
{
_transaction.Commit();
_transaction = null;
}
}
it seems to me that iuow is resolved (whith a call to New) only at page load, so every new attempt to create Uow return last used one with session disposed.
before attimpting to use ninject what i do is simply:
using (Iuow = new UnitOfWork())
{
....
}
and all works fine
p.s.
i have to remove InRequestScope from binding since it prevent even the page load to work
replace
using (iuow)
{
...
}
by
using (IResolutionRoot.Get<IUnitOfWork>())
{
...
}
Whereas you can inject IResolutionRoot into your classes. No extra bindings necessary (it's a Ninject type).
Caveat: this is service locator.
Alternatively you can hide the IResolutionRoot.Get<IUnitOfWork>() behind an IUnitOfWorkFactory which you can either implement manually or use Ninject.Extensions.Factory to do it for you.
Example
using Ninject;
using Ninject.Syntax;
namespace NinjectTest.SO38013150
{
public interface IUnitOfWork { }
internal class UnitOfWork : IUnitOfWork { }
public interface IUnitOfWorkFactory
{
IUnitOfWork Create();
}
internal class UnitOfWorkFactory : IUnitOfWorkFactory
{
private readonly IResolutionRoot resolutionRoot;
public UnitOfWorkFactory(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public IUnitOfWork Create()
{
return this.resolutionRoot.Get<IUnitOfWork>();
}
}
}
with a test showing that it works (this uses xunit for testing and FluentAssertions for assertions.. they are nuget packages):
using FluentAssertions;
using Ninject;
using Xunit;
namespace NinjectTest.SO38013150
{
public class Test
{
[Fact]
public void Foo()
{
var kernel = new StandardKernel();
kernel.Bind<IUnitOfWork>().To<UnitOfWork>();
kernel.Bind<IUnitOfWorkFactory>().To<UnitOfWorkFactory>();
var factory = kernel.Get<IUnitOfWorkFactory>();
var unitOfWork1 = factory.Create();
var unitOfWork2 = factory.Create();
unitOfWork1.Should().NotBeSameAs(unitOfWork2);
}
}
}
The code is also available as part of my examples collection, here
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);
}
}
Several of our internal apps are MVC3 and all use Ninject.MVC.
We're running into an issue that affects all the tools at one point. First we get the error:
Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'.
Followed by:
Execution of the command requires an open and available connection. The connection's current state is broken.
This can happen at any time when the tool is used. We've updated our ninjects to the latest versions and it helped a LOT, errors have been much more seldom but still happen when the tools are heavily used. I've been simply setting up Ninject.MVC3 via the nuget package manager and registering the proper services to the NinjectWebCommon.cs.
Here's our our controllers, NinjectWebCommon and global.asax are setup, is there something we're doing wrong here?
One we we know for sure will fix this is to simply get rid of Ninject altogether and instantiate our repositories on each controller. But that's not a good solution I'm guessing.
Global.asax (removed some routes):
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Index", // Route name
"", // URL with parameters
new { controller = "Home", action = "Index" } // Parameter defaults
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}
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)
{
kernel.Bind<IToolRepository>().To<ToolRepository>();
}
}
HomeController:
public class HomeController : Controller
{
private IBattleStationRepository _repository;
private LoginEntities _loginEntities;
private SpecialLib _speclib;
private AccessManager _accessManager;
public HomeController(IBattleStationRepository repository)
{
_repository = repository;
_speclib = new SpecialLib();
_loginEntities = new LoginEntities();
_accessManager = new AccessManager();
}
public virtual ActionResult Index()
{
var byPassHomePage = false;
var urlReferrer = HttpContext.Request.UrlReferrer;
var user = _accessManager.GetUserByUserName(User.Identity.Name);
if (urlReferrer == null)
{
byPassHomePage = true;
}
if (user.TeamId != null && byPassHomePage == true)
{
return RedirectToAction("Release", "Release", new { shortTeamName = user.Team.ShortName });
}
return View();
}
}