ServiceStack - Use Ninject instead of Funq - ninject

I am trying to use ServiceStack with Ninject rather than Funq. I have the following:
public interface IContainerAdapter
{
T Resolve<T>();
T TryResolve<T>();
}
public class NinjectIocAdapter : IContainerAdapter
{
private readonly IKernel kernel;
public NinjectIocAdapter(IKernel kernel)
{
this.kernel = kernel;
}
public T Resolve<T>()
{
return this.kernel.Get<T>();
}
public T TryResolve<T>()
{
return this.kernel.TryGet<T>();
}
}
Then inside my Configure method:
public override void Configure(Funq.Container container)
{
//Set JSON web services to return idiomatic JSON camelCase properties
ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;
IKernel kernel = new StandardKernel();
container.Adapter = new NinjectIocAdapter(kernel);
//Set MVC to use the same Funq IOC as ServiceStack
//ControllerBuilder.Current.SetControllerFactory(new FunqControllerFactory(container));
}
But I get the following error:
Cannot implicitly convert type 'NinjectIocAdapter' to 'ServiceStack.Configuration.IContainerAdapter'.
I'm also unsure whether I have to uncomment the line to set MVC to use Funq IoC? I have commented it out as I will be using Ninject. Is that correct?
I assume once this is all working. I can simply register any dependencies inside:
private static void RegisterServices(IKernel kernel)
{
}

The code exactly matches the documentation with one subtle difference.
You have to use ServiceStack.Configuration.IContainerAdapter instead of your own IContainerAdapter
.
Delete your implementation, add a reference to ServiceStack.Configuration and you should be fine.

Related

Define class dynamically with Service Locator - Asp.Net Core

I am working with Asp.Net Core application. I have two classes namely Online and Offline. I have created interface and defined the methods in these two classes. Based on the need I have to connect to anyone of these two classes.
Previously when I worked in Asp.Net MVC, I have used unity container and Service Locator to specify the class name in XML file for invoking the class dynamically (between online and offline).
Now I want to implement the same with Asp.Net core. But I am not sure how to specify the class name outside for method invocation. Kindly help.
Thanks
In .net core dependency injection is in built. You don't need unity or any other any more.
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0
You can achieve what you want by using a little tweak.
//// classes
public interface IFileUploadContentProcess
{
IEnumerable<StoreOrder> ProcessUploads(IFormFile file);
}
public class ProcessExcelFiles : IFileUploadContentProcess
{
public IEnumerable<StoreOrder> ProcessUploads(IFormFile file)
{
throw new NotImplementedException();
}
}
public class ProcessCsvFiles : IFileUploadContentProcess
{
public IEnumerable<StoreOrder> ProcessUploads(IFormFile file)
{
throw new NotImplementedException();
}
}
//// register it
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddTransient<IStoreOrderService, StoreOrderService>();
services.AddTransient<ProcessExcelFiles>();
services.AddTransient<ProcessCsvFiles>();
// Add resolvers for different sources here
services.AddTransient<Func<string, IFileUploadContentProcess>>(serviceProvider => key =>
{
return key switch
{
"xlsx" => serviceProvider.GetService<ProcessExcelFiles>(),
_ => serviceProvider.GetService<ProcessCsvFiles>(),
};
});
}
//use it
public class StoreOrderService : IStoreOrderService
{
private readonly Func<string, IFileUploadContentProcess> _fileUploadContentProcess;
public StoreOrderService(Func<string, IFileUploadContentProcess> fileUploadContentProcess)
{
_fileUploadContentProcess = fileUploadContentProcess;
}
public async Task<IEnumerable<StoreOrder>> UploadStoreOrdersAsync(IFormFile file)
{
//// passing csv to process csv type(default), if xlsx, pass xlsx
var records = _fileUploadContentProcess("csv").ProcessUploads(file);
return records;
}
}
After lot of brainstroming, I found the below solution
Create a class for ServiceLocator
public class ServiceLocator
{
private ServiceProvider _currentServiceProvider;
private static ServiceProvider _serviceProvider;
public ServiceLocator(ServiceProvider currentServiceProvider)
{
_currentServiceProvider = currentServiceProvider;
}
public static ServiceLocator Current
{
get
{
return new ServiceLocator(_serviceProvider);
}
}
public static void SetLocatorProvider(ServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public object GetInstance(Type serviceType)
{
return _currentServiceProvider.GetService(serviceType);
}
public TService GetInstance<TService>()
{
return _currentServiceProvider.GetService<TService>();
}
}
Step 2: Create interface and inherit in the classes and define the interface methods
Step 3: Define class name in appSettings.json and read the values in startup.cs
public void ConfigureServices(IServiceCollection services)
{
//reading from appSettings.json
string strClassName = Configuration["DependencyInjection:className"];
if (strClassName == "OnlineData")
services.AddTransient<<<InterfaceName>>, <<OnlineClassName>>>();
if (strClassName == "OfflineData")
services.AddTransient<<<InterfaceName>>, <<OfflineClassName>>>();
}
Step 4: Create object for the dynamic class inside controller/action method
InterfaceNamemyService = ServiceLocator.Current.GetInstance<>();

Ninject Property Injection in WebAPI custom ExceptionFilterAttribute Not Working

I am trying to use Ninject to inject an EventLogger instance into a custom ExceptionFilterAttribute. Whenever I run the code, the EventLogger instance is null. I have implemented an IFilterProvider to resolve dependencies in a similar manner for my custom AuthorizationFilterAttribute, and that works fine. Any ideas?
Not Working
public class ErrorHandlingAttribute : ExceptionFilterAttribute
{
[Inject]
public IEventLogger EventLogger { get; set; }
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
EventLogger.LogException(actionExecutedContext.Exception);
actionExecutedContext.Response = actionExecutedContext.Request.
CreateResponse(HttpStatusCode.BadRequest,
new ServiceErrorResponseDTO("An unhandled exception occurred while calling " +
actionExecutedContext.Request.RequestUri.ToString() +
". This event has been logged. If you continue to receive this error contact Weichert"));
}
}
Working
public class RequireAuthorizationAttribute : AuthorizationFilterAttribute
{
[Inject]
public IServiceRepository ServiceRepository { get; set; }
public override void OnAuthorization(HttpActionContext actionContext)
{
#region Header Authentication
var authHeader = actionContext.Request.Headers.Authorization;
if (authHeader != null)
{
Custom IFilterProvider
public class NinjectWebApiFilterProvider : IFilterProvider
{
private IKernel _kernel;
public NinjectWebApiFilterProvider(IKernel kernel)
{
_kernel = kernel;
}
public IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
var controllerFilters = actionDescriptor.ControllerDescriptor.GetFilters().Select(instance => new FilterInfo(instance, FilterScope.Controller));
var actionFilters = actionDescriptor.GetFilters().Select(instance => new FilterInfo(instance, FilterScope.Action));
var filters = controllerFilters.Concat(actionFilters);
foreach(var filter in filters)
{
_kernel.Inject(filter.Instance);
}
return filters;
}
}
NinjectWebCommon CreateKernel Method
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
// Ad Ninject support for Web API.
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
GlobalConfiguration.Configuration.Services.Add(typeof(IFilterProvider),
new NinjectWebApiFilterProvider(kernel));
RegisterServices(kernel);
return kernel;
}
NinjectWebCommon Bindings
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ServiceDbContext>().To<ServiceDbContext>();
kernel.Bind<IServiceRepository>().To<ServiceRepository>();
kernel.Bind<CareerDevelopmentDbContext>().To<CareerDevelopmentDbContext>();
kernel.Bind<ICareerDevelopmentRepository>().To<CareerDevelopmentRepository>();
kernel.Bind<ICareerDevelopmentService>().To<CareerDevelopmentService>();
kernel.Bind<IEventLogger>().To<ServiceEventLogger>();
kernel.Bind<IFilterProvider>().To<NinjectWebApiFilterProvider>().WithConstructorArgument("kernel", kernel);
}
I had the same problem and was configuring my error handler the same way by adding it to the filter collection in WebApiConfig.cs which meant it wasn't getting handled by the FilterProvider implementation I had added. So I did this instead:
public class LoggingExceptionFilterAttribute : ExceptionFilterAttribute, IExceptionFilter
{
// this is what I wanted injected
private IEmailService emailService;
public LoggingExceptionFilterAttribute(IEmailService service)
{
emailService = service;
}
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
// my implementation here
}
}
Then I registered this in NinjectWebCommon like so:
kernel.Bind<System.Web.Http.Filters.IExceptionFilter>().To<LoggingExceptionFilterAttribute>().InSingletonScope();
And then in WebApiConfig I realized that I could get a hold of the DependencyResolver so I did this:
config.Filters.Add((IFilter)config.DependencyResolver.GetService(typeof(IExceptionFilter)));
Now Ninject handles constructing my exception filter and I can even do constructor injection instead of needing [Inject] attributes and I don't have to add my ExceptionFilterAttribute to every API controller.
Ok, you have to make sure you are binding your custom IFilterProvider as well. As of writing the Ninject.Web.WebApi Nuget package is unstable and would do that automatically for you, if you were using it. Just in the same fashion Ninject.MVC3 does this for your regular controllers.
Just make sure you have this binding, and the replaced DependencyResolver will look for IFilterProvider implementation via your Ninject kernel as well:
kernel.Bind<IFilterProvider>().To<NinjectWebApiFilterProvider>();
Then your NinjectWebApiFilterProvider will kick in and inject dependencies into your filters as per your code.

SignalR, WebAPI and MVC sharing the same dependency resolver kernel

I have an ASP.NET MVC app with SignalR and WebAPI. The app uses Ninject for dependency injection, but apparently SignalR and WebAPI are getting different kernels, so it fails to share a singleton object that should be shared for all the application.
I can see clearly in the log how an instance is created when SignalR gets a connection request, and other when WebAPI gets a request.
I want to have the same Ninject kernel shared among these three elements, so I can have unique singletons.
This is what I have done so far:
The first thing I have done is creating a NinjectModule declaring the binding:
public class MyDependencyModule: NinjectModule
{
public override void Load()
{
var binding = Bind<MustBeSingleton>().ToSelf();
binding.OnActivation((ctx, o) =>
{
Debug.Print("Registering item " + o.GetHashCode());
HostingEnvironment.RegisterObject(o);
});
binding.OnDeactivation(o =>
{
Debug.Print("Unregistering game connection " + o.GetHashCode());
});
binding.InSingletonScope();
}
}
I have also created a wrapper for Ninject in order to plug it in WebAPI:
public class NinjectDependencyScope : IDependencyScope
{
private IResolutionRoot resolver;
internal NinjectDependencyScope(IResolutionRoot resolver)
{
this.resolver = resolver;
}
public void Dispose()
{
IDisposable 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);
}
}
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
Also, I have created another wrapper for SignalR:
public class SignalRNinjectDependencyResolver : DefaultDependencyResolver
{
private readonly IKernel _kernel;
public SignalRNinjectDependencyResolver(IKernel kernel)
{
_kernel = kernel;
}
public override object GetService(Type serviceType)
{
return _kernel.TryGet(serviceType) ?? base.GetService(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
return _kernel.GetAll(serviceType).Concat(base.GetServices(serviceType));
}
}
Then I have created a Ninject kernel that does all the config:
public class ApplicationDependencies:StandardKernel
{
public ApplicationDependencies()
:base(new MyDependencyModule())
{
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(this);
Microsoft.AspNet.SignalR.GlobalHost.DependencyResolver = new SignalRNinjectDependencyResolver(this);
}
}
The MVC application, uses NinjectHttpApplication as base class, so I indicate the kernel that must be used this way:
public class MvcApplication : Ninject.Web.Common.NinjectHttpApplication
{
protected override Ninject.IKernel CreateKernel()
{
return new ApplicationDependencies();
}
}
Also, in the SignalR configuration I specify the Resolver:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR<MyPersistentConnection>("/updates", new ConnectionConfiguration()
{
Resolver = GlobalHost.DependencyResolver
});
}
}
(I have tried also without specifying the resolver, and it does not work either).
Any idea?
Cheers.
I found the answer in another post: Singleton Scope binding not working as intended
Rather than binding as a singleton, "ToConstant" must be used:
var binding = Bind<MustBeSingleton>().ToConstant(new MustBeSingleton());
I have created a simple demo project with ASP.NET MVC, WebAPI and SignalR using the same dependency injection context.
https://drive.google.com/file/d/0B52OsuSSsroNX0I5aWFFb1VrRm8/edit?usp=sharing
The web app, contains a single page that shows the AppDomain and GetHashCode of an object that is supposed to be unique across the three frameworks, giving a result similar to:
Dependency Test
Framework IMySingletonService instance
MVC AppDomainId:2 / HashCode:5109846
WebAPI AppDomainId:2 / HashCode:5109846
SignalR AppDomainId:2 / HashCode:5109846
Other problem was, that Ninject was disposing my singleton because was IDisposable. I don't really understand why this happens, but that is another war.
Cheers.
In order keep this 3 things working.. you should check these references out:
Web API + Ninject
http://www.peterprovost.org/blog/2012/06/19/adding-ninject-to-web-api/
SignalR + Ninject https://github.com/SignalR/SignalR/wiki/Extensibility (last part:
When using ASP.NET MVC, configure SignalR first, then ASP.NET MVC)
For the second one, I refactored a little bit, since I need the kernel for SignalR Dependency Resolver
// Route SignalR.
GlobalHost.DependencyResolver = NinjectWebCommon.GetSignalrResolver();
RouteTable.Routes.MapHubs();
I defined GetSignalrResolver inside of NinjectWebCommon like this:
public static Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver GetSignalrResolver()
{
return new Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver(bootstrapper.Kernel);
}
Note: There are 2 different DependencyResolver: one for Web API (1) assigned to GlobalConfiguration.Configuration.DependencyResolver and the other for SignalR (2) assigned to GlobalHost.DependencyResolver
in order to use a dependency resolver for both WebApi and SignalR you need to implement a class that looks like this:
public class NinjectDependencyResolver : Microsoft.AspNet.SignalR.DefaultDependencyResolver,
System.Web.Http.Dependencies.IDependencyResolver
{
public readonly IKernel Kernel;
public NinjectDependencyResolver(string moduleFilePattern)
: base()
{
Kernel = new StandardKernel();
Kernel.Load(moduleFilePattern);
}
public override object GetService(Type serviceType)
{
var service = Kernel.TryGet(serviceType) ?? base.GetService(serviceType);
return service;
}
public override IEnumerable<object> GetServices(Type serviceType)
{
IEnumerable<object> services = Kernel.GetAll(serviceType).ToList();
if (services.IsEmpty())
{
services = base.GetServices(serviceType) ?? services;
}
return services;
}
public System.Web.Http.Dependencies.IDependencyScope BeginScope()
{
return this;
}
public void Dispose()
{ }
}
then in your startup class you should register NinjectDependencyResolver for both WebApi and SignalR, like this:
public void Configuration(IAppBuilder app)
{
var dependencyResolver = new NinjectDependencyResolver("*.dll");
var httpConfiguration = new HttpConfiguration();
httpConfiguration.DependencyResolver = dependencyResolver;
app.UseWebApi(httpConfiguration);
var hubConfig = new HubConfiguration { Resolver = dependencyResolver };
app.MapSignalR(hubConfig);
}

NinjectModule and IProvider not resolving types

Here is the set up that is not working
Using Ninject V3.0
public class LoggerModule : NinjectModule{
public override void Load()
{
Bind<ILogger>.ToProvider(MyLoggerProvider);
}
}
public class MyLoggerProvider: IProvider<ILogger>
{
public object Create(IContext context){
return new OneOfMyLoggers();
}
}
In my application wherever I inject instance of ILogger (using constructor or property injection, just does matter) I never get instance of ILogger resolved.
But If do not use module and/or povider, and bind when kernel is created, everything works like a charm. The following works
public class MyDiResolver()
{
public MyDiResolver()
{
MyKernel = new StandardKernel();
MyKernel.Bind<ILogger>().To<OneOfMyLoggers>();
}
}
The same arrangement of modules and providers works fine in Ninject2.x version. Is there something different about Ninject V3.0 that I am missing?
Thanks
Try passing the module into the StandardKernel so it knows to use it:
using (IKernel kernel = new StandardKernel(new LoggerModule()))
{
ILogger logger = kernel.Get<OneOfMyLoggers>();
}

Avoiding Service Locator with AutoFac 2

I'm building an application which uses AutoFac 2 for DI. I've been reading that using a static IoCHelper (Service Locator) should be avoided.
IoCHelper.cs
public static class IoCHelper
{
private static AutofacDependencyResolver _resolver;
public static void InitializeWith(AutofacDependencyResolver resolver)
{
_resolver = resolver;
}
public static T Resolve<T>()
{
return _resolver.Resolve<T>();
}
}
From answers to a previous question, I found a way to help reduce the need for using my IoCHelper in my UnitOfWork through the use of Auto-generated Factories. Continuing down this path, I'm curious if I can completely eliminate my IoCHelper.
Here is the scenario:
I have a static Settings class that serves as a wrapper around my configuration implementation. Since the Settings class is a dependency to a majority of my other classes, the wrapper keeps me from having to inject the settings class all over my application.
Settings.cs
public static class Settings
{
public static IAppSettings AppSettings
{
get
{
return IoCHelper.Resolve<IAppSettings>();
}
}
}
public interface IAppSettings
{
string Setting1 { get; }
string Setting2 { get; }
}
public class AppSettings : IAppSettings
{
public string Setting1
{
get
{
return GetSettings().AppSettings["setting1"];
}
}
public string Setting2
{
get
{
return GetSettings().AppSettings["setting2"];
}
}
protected static IConfigurationSettings GetSettings()
{
return IoCHelper.Resolve<IConfigurationSettings>();
}
}
Is there a way to handle this without using a service locator and without having to resort to injecting AppSettings into each and every class? Listed below are the 3 areas in which I keep leaning on ServiceLocator instead of constructor injection:
AppSettings
Logging
Caching
I would rather inject IAppSettings into every class that needs it just to keep them clean from the hidden dependency on Settings. Question is, do you really need to sprinkle that dependency into each and every class?
If you really want to go with a static Settings class I would at least try to make it test-friendly/fakeable. Consider this:
public static class Settings
{
public static Func<IAppSettings> AppSettings { get; set; }
}
And where you build your container:
var builder = new ContainerBuilder();
...
var container = builder.Build();
Settings.AppSettings = () => container.Resolve<IAppSettings>();
This would allow to swap out with fakes during test:
Settings.AppSettings = () => new Mock<IAppSettings>().Object;
Now the AppSettings class (which I assume there is only one of) you could do with regular constructor injection. I assume also that you really want to do a resolve on each call to your settings properties, thus injecting a factory delegate that retrieves an instance when needed. If this is not needed you should of course inject the IConfigurationSettings service directly.
public class AppSettings : IAppSettings
{
private readonly Func<IConfigurationSettings> _configurationSettings;
public AppSettings(Func<IConfigurationSettings> configurationSettings)
{
_configurationSettings = configurationSettings;
}
public string Setting1
{
get
{
return _configurationSettings().AppSettings["setting1"];
}
}
public string Setting2
{
get
{
return _configurationSettings().AppSettings["setting2"];
}
}
}