I have a working WCF application hosted in IIS (.svc), using Ninject (Ninject.Web.Common) for dependency injection. All is well and good, works great. However I am trying to implment interception on the service endpoints and am getting a ServiceActiviationException. I've included the ninject extensions for wcf, interception, and interception.dynamic proxy as well as castle.core, so I'm not really sure what I'm missing here. Any ideas?
UPDATE: I was able to get past the service validation exception but I am now getting the following error:
Can not instantiate proxy of class: MyNameSpace.CustomerService.
Could not find a parameterless constructor.
My NinjectWebCommon contents:
public class NinjectWebCommon
{
private static readonly Bootstrapper Bootstrapper = new Bootstrapper();
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
Bootstrapper.Initialize(CreateKernel);
}
public static void PostStart()
{
// Inject the WITS Application Security service into the ApplicationSecurityRoleProvider
//_kernel.Inject(Roles.Provider);
}
public static void Stop()
{
Bootstrapper.ShutDown();
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel(
new AutoMapperModule(),
new CustomerServiceModule(),
new AccountServiceModule());
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<LoggingInterceptor>().ToSelf().InRequestScope();
kernel.Bind<CustomerService>().ToSelf().Intercept().With<LoggingInterceptor>();
}
And a simple interceptor (Ive tried this also just implementing IInterceptor to no avail):
public class LoggingInterceptor : SimpleInterceptor
{
/// <summary>
/// Intercepts the specified invocation.
/// </summary>
/// <param name="invocation">The invocation to intercept.</param>
protected override void BeforeInvoke(IInvocation invocation)
{
Debug.WriteLine("Running " + invocation.ReturnValue);
base.BeforeInvoke(invocation);
}
public new void Intercept(IInvocation invocation)
{
try
{
base.Intercept(invocation);
}
catch (Exception e)
{
Debug.WriteLine("Exception: " + e.Message);
}
}
protected override void AfterInvoke(IInvocation invocation)
{
Debug.WriteLine("After Method");
base.AfterInvoke(invocation);
}
}
Related
I am working with MVC 4.0 & .net 4.0 and wish to use Ninject.
I have a static class, in which objects are created. I can NOT make the static calling class non-static!
I am trying to get an instance based on this binding
Bind<ClinicWebsite.ViewModels.ISelectionEngine>)
.To<ClinicWebsite.ViewModels.Genric_SelectionEngine>();
in the static class I call:
ClinicWebsite.ViewModels.Generic_SelectionEngine myService =
ClinicWebsite.App_Start.NinjectWebCommon.Kernel
.GetService(typeof(ClinicWebsite.ViewModels.ISelectionEngine))
as ClinicWebsite.ViewModels.Generic_SelectionEngine;
but when I examine "myservice" I get:
The name 'myservice' does not exist in the current context
What could I be doing wrong, or is there another way to explicitly create an instance with Ninject (again, cannot get rid of static calling class)
NinjectWebCommon
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
private static readonly StandardKernel kernel = new StandardKernel();
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
public static void Stop()
{
bootstrapper.ShutDown();
}
private static IKernel CreateKernel()
{
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
//DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
private static void RegisterServices(IKernel kernel)
{
Bind<ClinicWebsite.ViewModels.ISelectionEngine>().To<ClinicWebsite.ViewModels.Generic_SelectionEngine>();
}
public static IKernel Kernel
{
get
{
return kernel;
}
}
}
I found the answer.
because this is in a static class I need to make"myservice" a static member of the class and then assign to it.
I am getting the following error whenever I try to inject one of my service's dependency into the MVC controller:
Error activating IFeedService No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IFeedService into parameter svc of constructor of type FeedController
1) Request for FeedController
Suggestions:
1) Ensure that you have defined a binding for IFeedService.
2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
3) Ensure you have not accidentally created more than one kernel.
4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
5) If you are using automatic module loading, ensure the search path and filters are correct.
======================================================================
Here's how my code looks like:
ObjectFactory.cs
private static void RegisterServices(IKernel kernel)
{
// Contexts
kernel.Bind<IEntityObjectContext>().To<Entities>();
kernel.Bind<IAzureObjectContext>().To<AzureTableObjectContext>();
// Repositories
kernel.Bind<IEFRepository>().To<EFRepository>();
kernel.Bind<IAzureRepository>().To<AzureRepository>();
// Services
kernel.Bind<IFeedService>().To<FeedService>();
}
IEFRepository.cs
public interface IEFRepository : IDisposable
{
void SetContext(IEntityObjectContext context);
IQueryable<T> GetAll<T>() where T : class;
}
EFRepository.cs
public class EFRepository : IEFRepository
{
internal IEntityObjectContext context;
private Dictionary<Type, object> objectSets;
public EFRepository(IEntityObjectContext context)
{
this.context = context;
objectSets = new Dictionary<Type, object>();
}
public void SetContext(IEntityObjectContext context)
{
this.context = context;
}
}
IFeedService.cs
public interface IFeedService : IDisposable
{
IQueryable<FeedItem> GetPosts();
}
FeedService.cs
public class FeedService : IFeedService
{
private IEntityObjectContext _context;
private readonly IEFRepository _repo;
public FeedService(IEntityObjectContext context,
IEFRepository repo)
{
_context = context;
_repo = repo;
_repo.SetContext(_context);
}
public IQueryable<FeedItem> GetPosts()
{
using (_repo)
{
return _repo.GetAll<FeedItem>().Take(10);
}
}
}
FeedController.cs
public class FeedController : Controller
{
private readonly IFeedService _svc;
public FeedController(IFeedService svc)
{
_svc = svc;
}
}
As you can see, there are some nested dependency there in action. Not sure though, what needs to be added/removed for this bit to work.
Note: The error is thrown whenever I request the Feed/FetchFeed path. I also tried to comment out the FeedService's constructor portion to see if the nested dependencies are creating any problem, but again same error was thrown.
EDIT 1:
Rest of the code for the ObjectFactory.cs
class ObjectFactory
{
static ObjectFactory()
{
RegisterServices(kernel);
}
static IKernel kernel = new StandardKernel();
public static T GetInstance<T>()
{
return kernel.Get<T>();
}
private static void RegisterServices(IKernel kernel)
{
//...
}
}
EDIT 2:
I even tried to write a fairly basic service, but still the same error. Here's what I tried with:
public interface ITest
{
void CheckItOut();
}
public class Test : ITest
{
public void CheckItOut()
{
}
}
ObjectFactory.cs
kernel.Bind<ITest>().To<Test>();
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!
I followed the instructions in this article to use Ninject for MVC 4 Web API Controller Constructor injection:
http://www.peterprovost.org/blog/2012/06/19/adding-ninject-to-web-api/
the problem that i am facing is when i call the api method i get error saying "Type 'CarController' does not have a default constructor".
i have even set break points at NinjectWebCommon.CreateKernel to see if that is being called. And that does get called when application runs.
Am i missing any thing?
by the way, i installed Ninject.Web.Common and Ninject from nuget for doing this. Here is my code:
MVC WEB API Controller:
public class CarController : ApiController
{
private ICarService carService;
public CarController(ICarService carService)
{
this.carService = carService;
}
[AcceptVerbs("GET")]
public CarsResponse GetCars([FromUri] CarsRequest request)
{
return this.carService.GetCars(request);
}
}
in App_Start:
public class NinjectDependencyScope : IDependencyScope
{
IResolutionRoot resolver;
public NinjectDependencyScope(IResolutionRoot resolver)
{
this.resolver = resolver;
}
public object GetService(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
return resolver.TryGet(serviceType);
}
public System.Collections.Generic.IEnumerable<object> GetServices(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
return resolver.GetAll(serviceType);
}
public void Dispose()
{
IDisposable disposable = resolver as IDisposable;
if (disposable != null)
disposable.Dispose();
resolver = null;
}
}
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
my NinjectWebCommon looks like this:
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
public static void Stop()
{
bootstrapper.ShutDown();
}
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;
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ICarService>().To<CarService>();
}
}
I was having the same issue. I found the resolution by doing the following. I lost track of the webpage where I found the class NinjectMVCDependencyResolver.
/// <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 NinjectDependencyResolver(kernel);
// Install into the MVC dependency resolver
System.Web.Mvc.DependencyResolver.SetResolver(
new NinjectMVCDependencyResolver(kernel));
return kernel;
}
public class NinjectMVCDependencyResolver : NinjectDependencyScope
, System.Web.Mvc.IDependencyResolver
{
private IKernel kernel;
public NinjectMVCDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
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;
}
}