Ninject InSingletonScope for asp.net mvc 4 - ninject

I am trying to use the InSingletonScope for one of my service interface. However it is still creating a new instance of the object per web request. basically it behaves like an InRequestScope in my asp.net mvc 4 application.
I thought InSingletonScope is for the life time of the IIS process?
I register the following implementation for the interface in one of my NinjectModule. if I resolve it right away, repo1 and repo2 are actually the same instance. However, in my controller every request result in a new instance.
-------------------- Module registration
public class RepositoryModule : NinjectModule
{
#region Overrides of NinjectModule
public override void Load()
{
Bind<IFakeRepository>().To<FakeRepository>().InSingletonScope();
// following code onle execute the constructor once
var repo1String = Kernel.Get<IFakeRepository>().GetString();
var repo2String = Kernel.Get<IFakeRepository>().GetString();
}
#endregion
}
-------------------- Repository interface and implementation
public interface IFakeRepository
{
string GetString();
}
public class FakeRepository : IFakeRepository
{
public FakeRepository()
{
// every web request execute this constructor
Debug.Write("FakeRepository constructor called");
}
#region Implementation of IFackRepository
public string GetString()
{
return "dummy string";
}
#endregion
}
------------------ web api controller
public class TestRepoController : ApiController
{
public IFakeRepository FakeRepository { get; set; }
public TestRepoController(IFakeRepository fakeRepository)
{
FakeRepository = fakeRepository;
}
public string Get()
{
return FakeRepository.GetString();
}
}
----------------- web api route registration
config.Routes.MapHttpRoute(
name: "TestTakeRoutePost",
routeTemplate: "Fake",
defaults: new { controller = "TestRepo" }
);
----------------- NinjectWebCommon
[assembly: WebActivator.PreApplicationStartMethod(typeof(PNI.MediaServer.Application.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(PNI.MediaServer.Application.App_Start.NinjectWebCommon), "Stop")]
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();
//load all Binds defined in the classes that inherit NinhectModule
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
// Set Web API Resolver
GlobalConfiguration.Configuration.DependencyResolver = new PniNinjectDependencyResolver(kernel);
return kernel;
}
}

Related

NHibernate Invalid Index Exception

I´m developing an ASP.NET MVC Application, in which I use NHibernate and Ninject.
The Problem is caused by the following Controller:
public class ShoppingCartController : Controller
{
private readonly Data.Infrastructure.IShoppingCartRepository _shoppingCartRepository;
private readonly Data.Infrastructure.IShopItemRepository _shopItemRepository;
public ShoppingCartController(Data.Infrastructure.IShoppingCartRepository shoppingCartController,
Data.Infrastructure.IShopItemRepository shopItemRepository)
{
_shoppingCartRepository = shoppingCartController;
_shopItemRepository = shopItemRepository;
}
public ActionResult AddToShoppingCart(FormCollection formCollection)
{
var cartItem = new Data.Models.ShoppingCartItem();
cartItem.ChangeDate = DateTime.Now;
cartItem.ShopItem = _shopItemRepository.GetShopItem(SessionData.Data.Info, Convert.ToInt32(formCollection["shopItemId"]));
//IF I DONT´T CALL THE METHOD ABOVE, AddToCart works
_shoppingCartRepository.AddToCart(SessionData.Data.Info, cartItem);
//BUT IF I CALL THE GetShopItem METHOD I GET THE EXCEPTION HERE!
return RedirectToAction("Index", "Shop");
}
}
I know most of the Time this Exception is caused by wrong Mapping, but I´m pretty sure that my Mapping is right because the AddToCart-Method works if I don´t call GetShopItem...
So here is the Code of the ShopItemRepository:
public class ShopItemRepository : ReadOnlyRepository<ShopItem>, IShopItemRepository
{
public ShopItemRepository(IUnitOfWork uow) : base(uow)
{
}
public ShopItem GetShopItem(SessionParams param, int id)
{
return CurrentSession.QueryOver<ShopItem>()
.Where(x => x.ProcessId == param.ProcessId &&
x.CatalogueId == param.CatalogueId &&
x.Id == id)
.SingleOrDefault();
}
public IList<ShopItem> GetShopItems(SessionParams param)
{
return CurrentSession.GetNamedQuery("GetShopItems")
.SetParameter("requestor_id", param.RequestorId)
.SetParameter("recipient_id", param.RecipientId)
.SetParameter("process_id", param.ProcessId)
.SetParameter("catalogue_id", param.CatalogueId)
.List<ShopItem>();
}
}
And finally the Code of my UnitOfWork (basically it is just a Wrapper for the Session because I don´t want to reference NHibernate in my MVC Project)
public class UnitOfWork : IUnitOfWork, IDisposable
{
private NHibernate.ISession _currentSession;
public NHibernate.ISession CurrentSession
{
get
{
if(_currentSession == null)
{
_currentSession = SessionFactoryWrapper.SessionFactory.OpenSession();
}
return _currentSession;
}
}
public void Dispose()
{
if(_currentSession != null)
{
_currentSession.Close();
_currentSession.Dispose();
_currentSession = null;
}
GC.SuppressFinalize(this);
}
}
Addendum:
My NinjectWebCommon Class
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<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
kernel.Bind<Data.Infrastructure.ICatalogueRepository>().To<Data.Repositories.CatalogueRepository>();
kernel.Bind<Data.Infrastructure.ICategoryRepository>().To<Data.Repositories.CategoryRepository>();
kernel.Bind<Data.Infrastructure.IContactRepository>().To<Data.Repositories.ContactRepository>();
kernel.Bind<Data.Infrastructure.IProcessRepository>().To<Data.Repositories.ProcessRepository>();
kernel.Bind<Data.Infrastructure.IShopItemRepository>().To<Data.Repositories.ShopItemRepository>();
kernel.Bind<Data.Infrastructure.IShoppingCartRepository>().To<Data.Repositories.ShoppingCartRepository>();
}
}
IUnitOfWork is set to RequestScope so in the Case of ShoppingCartController, the two Repositories share the same UOW right?
Maybe this could cause the Problem?
Are you sure that this isn´t caused by wrong mapping? I had the same Issue and could resolve it by checking my mappings again!

SimpleIoC - Type not found in cache: Windows.UI.Xaml.Controls.Frame

I am running into the below error the first time my ViewModel is being instantiated by the SimpleIoC. I believe I have setup the container as it should be, but for some reason, I am still getting the below error. Any ideas or assistance would be very much appreciated.
Microsoft.Practices.ServiceLocation.ActivationException was unhandled by user code
HResult=-2146233088
Message=Type not found in cache: Windows.UI.Xaml.Controls.Frame.
Source=GalaSoft.MvvmLight.Extras
StackTrace:
at GalaSoft.MvvmLight.Ioc.SimpleIoc.DoGetService(Type serviceType, String key) in c:\Users\Public\Downloads\CodePlex\MVVMLight\GalaSoft.MvvmLight\GalaSoft.MvvmLight.Extras (NET35)\Ioc\SimpleIoc.cs:line 532
at GalaSoft.MvvmLight.Ioc.SimpleIoc.GetService(Type serviceType) in c:\Users\Public\Downloads\CodePlex\MVVMLight\GalaSoft.MvvmLight\GalaSoft.MvvmLight.Extras (NET35)\Ioc\SimpleIoc.cs:line 768
at GalaSoft.MvvmLight.Ioc.SimpleIoc.MakeInstance[TClass]() in c:\Users\Public\Downloads\CodePlex\MVVMLight\GalaSoft.MvvmLight\GalaSoft.MvvmLight.Extras (NET35)\Ioc\SimpleIoc.cs:line 708
InnerException:
Here are pieces of my code related to this:
ViewModelLocator.cs (Located in my Win8 project)
public class ViewModelLocator
{
/// <summary>
/// Initializes a new instance of the ViewModelLocator class.
/// </summary>
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
// Create design time view services and models
//SimpleIoc.Default.Register<IDataService, DesignDataService>();
}
else
{
// Create run time view services and models
//SimpleIoc.Default.Register<IDataService, DataService>();
SimpleIoc.Default.Register<INavigationService, NavigationService>();
SimpleIoc.Default.Register<IParseService, ParseService>();
SimpleIoc.Default.Register<IServiceHandler, ServiceHandler>();
}
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<ActionViewModel>();
}
public MainViewModel MainVM
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
public ActionViewModel ActionVM
{
get
{
return ServiceLocator.Current.GetInstance<ActionViewModel>();
}
}
public static void Cleanup()
{
// TODO Clear the ViewModels
}
}
MainViewModel.cs Constructor
public class MainViewModel : ViewModelBase
{
#region Variables
private readonly INavigationService _navigationService;
private readonly IParseService _parseService;
#endregion
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel(INavigationService navigationService, IParseService parseService)
{
if (IsInDesignMode)
{
// Code runs in Blend --> create design time data.
}
else
{
_navigationService = navigationService;
_parseService = parseService;
BuildCommonData();
}
}
I know this is long overdue, but here is the offending code in the implementation of my NavigationService class.
NavigationService class (Before)
public class NavigationService : INavigationService
{
/// <summary>
/// Gets the root frame.
/// </summary>
private Frame RootFrame;
public NavigationService(Frame rootFrame)
{
RootFrame = rootFrame;
}
public event NavigatingCancelEventHandler Navigating;
public void Navigate<T>(object parameter = null)
{
var type = typeof(T);
RootFrame.Navigate(type, parameter);
}
public void Navigate(string type, object parameter = null)
{
RootFrame.Navigate(Type.GetType(type), parameter);
}
public void GoBack()
{
if (RootFrame.CanGoBack)
{
RootFrame.GoBack();
}
}
public void GoForward()
{
if (RootFrame.CanGoForward)
{
RootFrame.GoForward();
}
}
}
I simply took out the constructor, and made the RootFrame private variable a property. Like so:
public class NavigationService : INavigationService
{
/// <summary>
/// Gets the root frame.
/// </summary>
private static Frame RootFrame
{
get { return Window.Current.Content as Frame; }
}
public event NavigatingCancelEventHandler Navigating;
public void Navigate<T>(object parameter = null)
{
var type = typeof(T);
RootFrame.Navigate(type, parameter);
}
public void Navigate(string type, object parameter = null)
{
RootFrame.Navigate(Type.GetType(type), parameter);
}
public void GoBack()
{
if (RootFrame.CanGoBack)
{
RootFrame.GoBack();
}
}
public void GoForward()
{
if (RootFrame.CanGoForward)
{
RootFrame.GoForward();
}
}
}
Simple, I know, but hope it's of some use.
I was getting the same error today in my Xamarin project. The actual error given was "System.Reflection.TargetInvocationException: 'Exception has been thrown by the target of an invocation.'" and then when I look up the InnerException I could see the actual error, which is Type not found in cache.
It was a silly mistake that I was using DataService instead of IDataService for the Constructor Dependency Injection.
public SearchViewModel(DataService dataService, IErrorLoggingService errorLoggingService, IDialogService dialogService, IResourceService resourceService, INavigationService navigationService) {
SearchCommand = new AsyncRelayCommand <SearchFilter>(SearchAsync);
DataService = dataService;
ErrorLoggingService = errorLoggingService;
DialogService = dialogService;
ResourceService = resourceService;
NavigationService = navigationService;
CancelCommand = new RelayCommand(Cancel);
}
And just for your information, this is how I registered my service.
SimpleIoc.Default.Register<IDataService, DataService>();
So the issue was fixed after changing to IDataService. Hope it helps.

Subclassing AuthorizeAttribute with WebApi not working returns 401?

I'm subclassing the AuthorizeAttribute so I can implement token authentication whereby the token is passed in the request header. I'm also using Ninject for IoC. The overriden OnAuthorization method gets called and validates the token but I still receive a 401.
Any ideas on why this is happening?
TokenAuthorisationAttribute.cs
public class TokenAuthorisationAttribute : AuthorizeAttribute
{
private readonly IRepository _repository;
public TokenAuthorisationAttribute(IRepository repository)
{
_repository = repository;
}
public override void OnAuthorization(
HttpActionContext actionContext)
{
if (!ValidateToken(actionContext.ControllerContext.Request))
HandleUnauthorizedRequest(actionContext);
base.OnAuthorization(actionContext);
}
private bool ValidateToken(HttpRequestMessage request)
{
const string authenticationToken = "Authentication-Token";
var token = request.Headers.GetValues(authenticationToken).FirstOrDefault();
if (token == null)
return false;
var device = _repository.FindSingleOrDefault<Device>(x => x.Id.Equals(token));
if (device == null || !token.Equals(device.Id))
return false;
return true;
}
}
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);
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 connectionString = ConfigurationManager.ConnectionStrings["MONGOHQ_URL"].ConnectionString;
var databaseName = ConfigurationManager.AppSettings["Database"];
kernel.Bind<IRepository>().To<MongoRepository>()
.WithConstructorArgument("connectionString", connectionString)
.WithConstructorArgument("databaseName", databaseName);
kernel.BindHttpFilter<TokenAuthorisationAttribute>(FilterScope.Global);
}
I managed to resolve this issue by overriding the IsAuthorized method instead of OnAuthorization. Not 100% sure if this is the right approach? Any opinions ??
public class TokenAuthorisationAttribute : AuthorizeAttribute
{
private readonly IRepository _repository;
public TokenAuthorisationAttribute(IRepository repository)
{
_repository = repository;
}
protected override bool IsAuthorized(HttpActionContext actionContext)
{
if (actionContext.Request.Headers.Authorization == null)
return false;
var authToken = actionContext.Request.Headers.Authorization.Parameter;
var decodedToken = Encoding.UTF8.GetString(Convert.FromBase64String(authToken));
var deviceToken = new DeviceToken(decodedToken);
var device = _repository.FindSingleOrDefault<Device>(x => x.Id.Equals(deviceToken.GetDeviceId()));
if (device != null)
{
HttpContext.Current.User = new GenericPrincipal(new ApiIdentity(device), new string[] {});
return true;
}
return base.IsAuthorized(actionContext);
}
}
The ASP.NET WebAPI is an open source project. So you can read the correspondingly codes here:
AuthorizationFilterAttribute http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/03357424caf5#src%2fSystem.Web.Http%2fFilters%2fAuthorizationFilterAttribute.cs
AuthorizeAttribute
http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/03357424caf5#src%2fSystem.Web.Http%2fAuthorizeAttribute.cs
There are two facts an AuthorizationFilterAttribute takes in to consider when it is making decision:
Is OnAuthorization throw exception; or
Is the actionContext's Response field is filled;
Either one is fulfilled, the remaining action filters and action are shortcut.
Based on your code, I'm curious if the function HandleUnauthorizedRequest does either of the operation above.
The reason why overriding IsAuthorized works, is because it works at AuthorizeAttribute level. The OnAuthorization call to the IsAuthorized overload and set value to actionContext's Request property.
Thanks,
Troy

Ninject ActivationException

I'm getting the infamous "Error activating XYZ. No matching bindings are available blah blah blah" from Ninject 3.0.1.10 in an ASP.NET MVC project.
The following is how I've setup my binding (very simple):
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;
}
private static void RegisterServices(IKernel kernel)
{
string connectionString = WebConfigurationManager.ConnectionStrings["STAGING"].ConnectionString;
kernel.Bind<IUserAccountRepository>()
.To<SqlUserAccountRepository>()
.WithConstructorArgument("connectionString", connectionString);
kernel.Bind<IRecipeRepository>()
.To<SqlRecipeRepository>()
.WithConstructorArgument("connectionString", connectionString);
kernel.Bind<HomeViewModel>().ToSelf();
}
}
When the controller Index action is invoked it attempts to create a HomeViewModel object as such:
public ActionResult Index()
{
IKernel kernel = new StandardKernel();
HomeViewModel model = kernel.Get<HomeViewModel>();
...
Which triggers the exception:
Error activating IRecipeRepository No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IRecipeRepository into parameter recipeRepository of constructor of type HomeViewModel
1) Request for HomeViewModel
But if I attempt to get an instance of HomeViewModel directly after calling kernel.Bind in RegisterServices then it works fine.
Here's what the HomeViewModel looks like (some details removed for sake of brevity):
public class HomeViewModel
{
public HomeViewModel(IRecipeRepository recipeRepository,
IUserAccountRepository userAccountRepository)
{
this.recipeRepository = recipeRepository;
this.userAccountRepository = userAccountRepository;
}
//
// Some details removed for sake of brevity
//
private readonly IRecipeRepository recipeRepository;
private readonly IUserAccountRepository userAccountRepository;
}
Any idea what I'm missing? Why is the controller "special" in this case?

Auto-mock container: Rhino Mocks and NInject

Does anyone have an implementation lying around of an auto-mock container using Rhino Mocks and NInject?
OK I built one myself using the Moq integration as a starting point. It is very simple. You need these 3 classes:
public class AutoMockingKernel : StandardKernel
{
private readonly IMockProvider _mockProvider;
public void Reset()
{
Components.Get<ICache>().Clear();
}
protected override bool HandleMissingBinding(Type service)
{
var isSelfBindable = TypeIsSelfBindable(service);
var binding = new Binding(service)
{
ProviderCallback = isSelfBindable
? StandardProvider.GetCreationCallback(service)
: _mockProvider.GetCreationCallback(),
IsImplicit = true
};
if (!isSelfBindable)
binding.ScopeCallback = ctx => null;
AddBinding(binding);
return true;
}
public AutoMockingKernel(IMockProvider mockProvider, INinjectSettings settings, params INinjectModule[] modules)
: base(settings, modules)
{
_mockProvider = mockProvider;
}
public AutoMockingKernel(IMockProvider mockProvider, params INinjectModule[] modules)
: base(modules)
{
_mockProvider = mockProvider;
}
}
internal class RhinoMockProvider : IProvider
{
public Type Type { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="RhinoMockProvider"/> class.
/// </summary>
public RhinoMockProvider(Type type)
{
Type = type;
}
public object Create(IContext context)
{
return MockRepository.GenerateMock(Type, Type.EmptyTypes);
}
}
public class RhinoAutoMockProvider : IMockProvider
{
public Func<IContext, IProvider> GetCreationCallback()
{
return ctx => new RhinoMockProvider(ctx.Request.Service);
}
}
You can then create an auto-mocking kernel in your unit test like this:
[Test]
public void Test()
{
var kernel = new AutoMockingKernel(new RhinoAutoMockProvider());
... etc
}
There is a RhinoMocks integration extension available.