How to inject dependencies in an HttpModule with ninject? - c#

We are running a webforms project at my company and I have an HttpModule that I need to resolve dependencies for.
We use the Ninject.Web library to resolve dependencies for master pages, pages, user controls, web services, and HttpHandlers. All these have base classes you can inherit from in the Ninject.Web Namespace:
MasterPageBase
PageBase
WebServiceBase
HttpHandlerBase
And a custom one we added since for some odd reason it wasn't there: UserControlBase
However I am unable to find a HttpModuleBase. There is a NinjectHttpModule, but that is not a base class, it is a real module that tries to eliminate the need to inherit from base classes in pages and user controls, but it has some bugs and we are not using it.
What is the best way to resolve my dependencies in my HttpModule?
When I google this I come up with this question on the first page -_-

Phil Haack blogged about a way to do this that makes it possible to use constructor injection and thereby avoid making your HttpModule depend directly on Ninject. In a standard NinjectHttpApplication, do the following:
Step 1
Use Nuget to find and add the HttpModuleMagic package to your web project.
Step 2
Write your HttpModule to use constructor injection:
public class MyHttpModule : IHttpModule
{
public MyHttpModule(ISomeService someService) {...}
}
Step 3
Remove the http module from your web.config:
<httpModules>
<!-- Modules will be defined via DI bindings -->
</httpModules>
Step 4
Set up bindings:
Bind<IHttpModule>().To<MyHttpModule>();
// Repeat the pattern above for any other modules.

I'm kind of amazed that nobody has answered this all day! Looks like I stumped you guys :)
Well, I solved the issue. I wrote my own custom implementation of IHttpModule and compiled it into the Ninject.Web assembly myself. Here is the source of the base class I added:
namespace Ninject.Web
{
public class HttpModuleBase : IHttpModule
{
/// <summary>
/// This method is unused by the base class.
/// </summary>
public virtual void Dispose()
{
}
/// <summary>
/// Ininitialize the module and request injection.
/// </summary>
/// <param name="context"></param>
public virtual void Init(HttpApplication context)
{
RequestActivation();
}
/// <summary>
/// Asks the kernel to inject this instance.
/// </summary>
protected virtual void RequestActivation()
{
KernelContainer.Inject(this);
}
}
}
I simply modeled it after the other base classes in the Ninject.Web assembly. It appears to be working wonderfully. Just make your HttpModule inherit from Ninject.Web.HttpModuleBase and then you are free to use property injection within your module, like this:
public class AppOfflineHttpModule : HttpModuleBase
{
[Inject]
public IUtilitiesController utilitiesController { get; set; }
...
}

Related

Resolving .net standard 2.0 with unity (DI) in .NET 4.7.2

We are currently working with a large solution that contains a WCF project (.NET Framework 4.7.2) along with multiple .NET Standard 2.0 libraries.
We're trying to register these libraries with Unity (DI). Loading the libraries in the container works fine. However resolving these classes in a constructor fails.
Unity.Exceptions.ResolutionFailedException: 'Resolution of the dependency
failed, type = 'PROJECTNAME.Service.ITypeDependentonDbContext', name = '(none)'.
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type,
PROJECTNAME.DAL.Repositories.Interfaces.IDbContext, is an interface
and cannot be constructed. Are you missing a type mapping?
More specifically, each library has a ModuleInit class where we register types on the ModuleRegistrar (for MEF2) like so:
public void Initialize(IModuleRegistrar registrar)
{
registrar.RegisterType<IDbContext, DbContext>();
// etc
}
Then, in our .NET Framework project, we register types to the Unity Container:
protected override void ConfigureContainer(IUnityContainer container)
{
container
.RegisterType<ISomeService, SomeService>()
.RegisterType<ITypeDependentonDbContext, TypeDependentonDbContext>();
//etc
ModuleLoader.LoadContainer(container, ".\\bin", "*.*.dll");
}
Finally, in a class in the .NET Framework project, we have
public class SomeService : ISomeService
{
private readonly ITypeDependentonDbContext _typeDependentonDbContext;
/// <summary>
/// constructor
/// </summary>
/// <param name="typeDependentonDbContext"></param>
public SomeService(ITypeDependentonDbContext typeDependentonDbContext)
{
_typeDependentonDbContext = typeDependentonDbContext ?? throw new ArgumentNullException(nameof(typeDependentonDbContext));
}
}
The weird thing is that the exception is not thrown if we register ALL types that we depend on directly in the container. This is in contrast to an existing .NET framework solution where we register each type in the moduleInit class of that project, exactly as presented here. However this doesn't seem to work with .NET standard 2.0 projects.
Additionally, while debugging it seems that the classes seem to be registered just fine in the container - each interface is mapped to the correct implementation class. Things only seem to go wrong when we actually wish to resolve the dependecy in a constructor.
Does anyone have any ideas as to why this may occur?

Will there be any memory issues if Unity and Ninject Dependency injection used together in the same solution?

I have a solution with several class library projects and a WCF web service project already in it. The dependency Injection is handled in Unity 2.1 where in web config file of the WCF project I have registered my new class library project as below.
<container name="unityDI">
<register type="INewProcess" mapTo="NewProcess"/>
<register type="ISomeService" mapTo="SomeService">
<constructor>
<param name="newProcess" type="INewProcess" />
<param name="Service1" type="IService1" />
<param name="repository1" type="IRepository1" />
</constructor>
</register>
In the class library project I added to this solution NewProcess class is where the client will consume the library.
That is the class where I do initiate the dependency handling process to handle the dependencies within the class library. this library implements the strategy pattern for handling validations based on different workflows and few other helper classes which used implement different utilities for this validation.
Below is the code I have in NewProcess class
public class NewProcess : INewProcess
{
private readonly IKernel _kernel = new StandardKernel(new NewProcessValidationsLibraryNinjectModule());
/// <inheritdoc />
public Tuple<string, IDictionary<string, string>> DetermineCandidate(string val1, string val2, string val3)
{
var newValidationObjectFactory = _kernel.Get<INewValidationObjectFactory>();
return newValidationObjectFactory.DetermineValidationStrategy(val1, val2, val3);
}
/// <inheritdoc />
public NewStatusObject GetSomeReceivedStatus(NewStatusObject newStatusObject)
{
var statusReceiveStatusChecker = _kernel.Get<IStatusReceiveStatusChecker>();
return statusReceiveStatusChecker.GetNewReceiveStatus(newStatusObject);
}
}
And in the NewProcessValidationsLibraryNinjectModule i have the below code
public class NewProcessValidationsLibraryNinjectModule : NinjectModule
{
public override void Load()
{
Kernel.Bind(x => x.FromThisAssembly().SelectAllClasses().BindAllInterfaces());
}
}
Can someone please let me know will there be any memory leak related issues while using both Unity and Ninject at the same time as above? Or is this the correct way of using both Unity and Ninject within the same solution? Will the new up of StandardKernel end up in memory issues?
I had a lengthy look at the comments I received and did some testing at run time and found that the way I have implemented the DI in my library it was loading and unloading the Ninject Kernel on request basis which is not the way you want your DI container to work.
It should load all the dependencies when you load it first time.
To resolve this issue I opt to use Unity across my solution. Apparently this move made the library calls faster and I do not have to worry about using 2 different DI containers in the same solution and complexities it can bring to your solution.

Dependency injection in custom workflow activity

I have a standard application that has a workflow. The customer can customize the workflow in the designer. Now we are making some custom activities for a specific customer. The custom activity is communicating against the business layer by a interface. How do I give the interface an implementation of that interface?
It is very important that the standard application doesn't know about the interface and implementation of that interface because it is custom code for that specific customer. The activity is found by standard workflow so that works already.
I see a lot of information about extensions but I don't really know how it works.
Custom activity
public sealed class GetDealerDetails : CodeActivity
{
/////// <summary>
/////// The dealer controller with all the businesslogic.
/////// </summary>
////private readonly IDealerController _dealerController;
[Inject]
public IDealerController DealerController { private get; set; }
////public GetDealerDetails()
////{
////}
////[Inject]
////public GetDealerDetails(IDealerController dealerController)
////{
//// _dealerController = dealerController;
////}
protected override void Execute(CodeActivityContext context)
{
Dealer dealer = DealerController.GetDealerDetails(5);
}
}
I use Ninject in my standard application. I tried to use constructor injection and property injection but it doesn't work. The DealerController stays null.
Edit
The rest of the code can be found here: Inject custom code in standard application
Import is that you have to use the workflow application wrapper I provide with ninject. Only with that I can build up the activities. The trick is the following: you cannot use constructor injection with custom workflow activities. Activities are very special in WF. Usually when you have coded workflow you build them up we the new operator in a lambda expression which is then lazy executed. So my ninject extension can only work its magic when the activities are already built up. Therefore you need to pass in the root activities of your activity tree in the workflow application of ninject. This does then internally resolve the whole activity tree und injects all properties which are decorated with the inject attribute.
But your actual problem was a bug in the library which I have fixed now. The BookmarkInfo decorator assumed that the scope info is always set and this wasn't the case.
Extensions are what the framework provides for injection in workflows. When you execute the workflow you add all dependencies that you will use in your activities.
[Dependency]
public IMyService MyService{ get; set; }
WorkflowApplication instance = new WorkflowApplication(myWorkflow, inParameters);
instance.Extensions.Add(MyService);
instance.Run();
And then you can get the extension in your activity in order to use it.
protected override void Execute(NativeActivityContext context){
var myservice = context.GetExtension<IMyService>();
myservice.MyMethod();
}
I hope it helps.

Ninject.Web and user controls

I am using the Ninject.Web library with our web forms application. It's working great except now I need to inject a dependency into a user control. What is the best way to accomplish this? Ninject.Web does not contain a base class like it does for web services, pages, and master pages.
You can make a base class for user controls yourself:
public class NinjectedUserControl : System.Web.UI.UserControl
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
RequestActivation();
}
/// <summary>
/// Asks the kernel to inject this instance.
/// </summary>
protected virtual void RequestActivation()
{
KernelContainer.Inject(this);
}
}
I have Ninject.Web's source code in my solution and I have added this class to Ninject.Web (so it can access KernelContainer, which is internal).

WCF Service problem using Ninject (Moving from Windsor) (InvalidOperationException)

Any Ninject experts in the house? :)
I've recently been trying to convert my WCF Service Application and Windows Forms Client Application from Castle Windsor dependency injection to Ninject.
All has gone fine on the Win Forms side, but I am encountering issues on the WCF side of things. I have learned so far I believe I need to WCF extensions available for Ninject in order to use DI with WCF which I have done and referenced but still experiencing an issue I believe when my service is attempted to be resolved:
System.InvalidOperationException: The type 'WcfMemberService', provided as the Service attribute value in the ServiceHost directive, or provided in the configuration element system.serviceModel/serviceHostingEnvironment/serviceActivations could not be found.
The code I have which is what I thought to be correct to access just for instance my WcfMemberService is as follows:
ServiceModule.cs:
public class ServiceModule : NinjectModule
{
private IKernel _parentContainer;
public ServiceModule(IKernel container)
{
this._parentContainer = container;
}
public override void Load()
{
Bind<IDataContextProvider>().To<DataContextProvider>()
.WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString);
Bind(typeof(IRepository<>)).To(typeof(Repository<>));
Bind<IServiceLocator>().ToConstant(new NinjectServiceLocator(_parentContainer));
Bind<IUserService>().To<UserService>();
// ** WCF Services **
Bind<Business.Common.Wcf.Services.Contracts.IMemberServiceContract>().To<Business.Common.Wcf.Services.MemberService>().InSingletonScope().Named("WcfMemberService");
}
}
The assumption I made is when converting over from my working Castle Windsor configuration is that Named() should be the same entry which is featured in the declaration of your WCF .svc file. So I have done that as follows:
<%# ServiceHost Language="C#" Service="WcfMemberService" Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory" %>
Pretty simple, I have taken this approach from the TimeService example solution featured on the Ninject Wcf Extensions GitHub page here by the way.
Can anyone see what I have done wrong here and why "WcfMemberService" would not be resolving? It is bound to be "WcfMemberService" in the Kernel and referenced in the #ServiceHost declaration. I can't see what else could be wrong. This is exactly the same as how I declare it in Castle Windsor, except for roughly different syntax, but both use Named() and both ref that name in the Service part of the .svc file.
*Update* I have discovered if I do not use the Named() approach, and simply set my service in # ServiceHost declaration as Business.Common.Wcf.Services.MemberService, Business.Common.Wcf.Services it works. But I am still stumped as to why I can't use Named services. Thanks.
By the way, my Ninject module is loaded via Global.asax.cs in this fashion:
public class Global : NinjectWcfApplication
{
#region Overrides of NinjectWcfApplication
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
protected override IKernel CreateKernel()
{
// config to reside in executing directory
log4net.Config.XmlConfigurator.Configure(new FileInfo("log4net.config"));
var _container = new StandardKernel();
_container.Load(new ServiceModule(_container));
//_container.Load(new Log4netModule());
ServiceLocator.SetLocatorProvider(() => _container.Get<IServiceLocator>());
return _container;
}
#endregion
}
The .Named(string) syntax is used in conditional binding. For example, if you have
Bind<IService1>().To<MyService>().Named("MyServiceImpl");
Bind<IService1>().To<DefaultService();
Then DefaultService will be injected as the default unless you have something like the following:
class MyForm([Named("MyServiceImpl")] IService1 service){...}
or
kernel.Get<IService1>(metadata => metadata.Name == "MyServiceImpl");
or
kernel.Get<IService1>("MyServiceImpl");
If you do not have a default binding for the type, and you only have the conditional named binding, then you will get an activation exception when you try to create an instance.
-Ian

Categories