There are plenty of examples for having it worked on an MVC application. How is it done on Web Forms?
Here are the steps to use Ninject with WebForms.
Step1 - Downloads
There are two downloads required - Ninject-2.0.0.0-release-net-3.5 and the WebForm extensions Ninject.Web_1.0.0.0_With.log4net (there is an NLog alternative).
The following files need to be referenced in the web application: Ninject.dll, Ninject.Web.dll, Ninject.Extensions.Logging.dll and Ninject.Extensions.Logging.Log4net.dll.
Step 2 - Global.asax
The Global class needs to derive from Ninject.Web.NinjectHttpApplication
and implement CreateKernel()
, which creates the container:
using Ninject; using Ninject.Web;
namespace Company.Web {
public class Global : NinjectHttpApplication
protected override IKernel CreateKernel()
{
IKernel kernel = new StandardKernel(new YourWebModule());
return kernel;
}
The StandardKernel
constructor takes a Module
.
Step 3 - Module
The Module, in this case YourWebModule
, defines all the bindings the web application will need:
using Ninject;
using Ninject.Web;
namespace Company.Web
{
public class YourWebModule : Ninject.Modules.NinjectModule
{
public override void Load()
{
Bind<ICustomerRepository>().To<CustomerRepository>();
}
In this example, wherever the ICustomerRepository
interface is referenced the concrete CustomerRepository
will be used.
Step 4 - Pages
Once that's done each page needs to inherit from Ninject.Web.PageBase
:
using Ninject;
using Ninject.Web;
namespace Company.Web
{
public partial class Default : PageBase
{
[Inject]
public ICustomerRepository CustomerRepo { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
Customer customer = CustomerRepo.GetCustomerFor(int customerID);
}
The InjectAttribute -[Inject]
- tells Ninject to inject ICustomerRepository
into the CustomerRepo Property.
If you already have a base page you just need to get your base page to derive from the Ninject.Web.PageBase.
Step 5 - Master Pages
Inevitably, you'll have master pages, and to allow a MasterPage to access injected objects you'll need to derive your master page from Ninject.Web.MasterPageBase
:
using Ninject;
using Ninject.Web;
namespace Company.Web
{
public partial class Site : MasterPageBase
{
#region Properties
[Inject]
public IInventoryRepository InventoryRepo { get; set; }
Step 6 - Static Web Service Methods
The next problem was not being able to inject into static methods. We had a few Ajax PageMethods, which are obviously static, so I had to move the methods into a standard web service. Again, the web service needs to derive from a Ninject class - Ninject.Web.WebServiceBase
:
using Ninject;
using Ninject.Web;
namespace Company.Web.Services
{
[WebService(Namespace = "//tempuri.org/">http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class YourWebService : WebServiceBase
{
#region Properties
[Inject]
public ICountbackRepository CountbackRepo { get; set; }
#endregion
[WebMethod]
public Productivity GetProductivity(int userID)
{
CountbackService _countbackService =
new CountbackService(CountbackRepo, ListRepo, LoggerRepo);
In your JavaScript you'll need to reference the standard service - Company.Web.Services.YourWebService.GetProductivity(user, onSuccess)
, rather than PageMethods.GetProductivity(user, onSuccess)
.
The only other problem I found was injecting objects into User Controls. While it's possible to create your own base UserControl with Ninject capabilities, I found it quicker to add a Property to the user control for the required object and setting the Property in the container page. I think supporting UserControls out of the box is on the Ninject "to-do" list.
Adding Ninject is quite simple and it is an eloquent IoC solution. Many people like it because there is no Xml configuration. It has other useful "tricks" such as turning objects into Singletons with just the Ninject syntax - Bind<ILogger>().To<WebLogger>().InSingletonScope()
. There is no need to change WebLogger into an actual Singleton implmentation, I like this.
It's gotten easier with the release of Ninject v3.0 (as of 4/12/2012). Injection is implemented via HttpModule so there is no need to have your pages inherit from a custom Page / MasterPage. Here are the steps (and code) for a quick spike.
- Create a new ASP.NET WebForms project
- Use NuGet to add the Ninject.Web lib (which will also bring down the Ninject.Web.Common and Ninject libs)
- Register your custom bindings in App_Start / NinjectWebCommon.cs / RegisterServices method
- Use attribute injection on your pages
NinjectWebCommon / RegisterServices
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IAmAModel>().To<Model1>();
}
Default
public partial class _Default : System.Web.UI.Page
{
[Inject]
public IAmAModel Model { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
System.Diagnostics.Trace.WriteLine(Model.ExecuteOperation());
}
}
Site.Master
public partial class SiteMaster : System.Web.UI.MasterPage
{
[Inject]
public IAmAModel Model { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
System.Diagnostics.Trace.WriteLine("From master: "
+ Model.ExecuteOperation());
}
}
Models
public interface IAmAModel
{
string ExecuteOperation();
}
public class Model1 : IAmAModel
{
public string ExecuteOperation()
{
return "I am a model 1";
}
}
public class Model2 : IAmAModel
{
public string ExecuteOperation()
{
return "I am a model 2";
}
}
Results from output window
I am a model 1
From master: I am a model 1
NinjectWeb.cs
in App_Start
. Your code to initialise Ninject has to go in this file. If it's in a separate file (e.g. NinjectWebCommon.cs
it won't work). This can happen if you install Ninject.Web later than the other Ninject packages using NuGet. –
Edgaredgard The answer here currently does not work due to a open bug. Here is a modified version of @Jason's steps using a customer httpmodule to inject into pages and controls without needing to inherit from ninject classes.
- Create a new ASP.NET WebForms project
- Use NuGet to add the Ninject.Web lib
- Register your custom bindings in App_Start / NinjectWebCommon.cs / RegisterServices method
- Add InjectPageModule and register in NinjectWebCommon
- Use attribute injection on your pages
InjectPageModule.cs
public class InjectPageModule : DisposableObject, IHttpModule
{
public InjectPageModule(Func<IKernel> lazyKernel)
{
this.lazyKernel = lazyKernel;
}
public void Init(HttpApplication context)
{
this.lazyKernel().Inject(context);
context.PreRequestHandlerExecute += OnPreRequestHandlerExecute;
}
private void OnPreRequestHandlerExecute(object sender, EventArgs e)
{
var currentPage = HttpContext.Current.Handler as Page;
if (currentPage != null)
{
currentPage.InitComplete += OnPageInitComplete;
}
}
private void OnPageInitComplete(object sender, EventArgs e)
{
var currentPage = (Page)sender;
this.lazyKernel().Inject(currentPage);
this.lazyKernel().Inject(currentPage.Master);
foreach (Control c in GetControlTree(currentPage))
{
this.lazyKernel().Inject(c);
}
}
private IEnumerable<Control> GetControlTree(Control root)
{
foreach (Control child in root.Controls)
{
yield return child;
foreach (Control c in GetControlTree(child))
{
yield return c;
}
}
}
private readonly Func<IKernel> lazyKernel;
}
NinjectWebCommon / RegisterServices
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IHttpModule>().To<InjectPageModule>();
kernel.Bind<IAmAModel>().To<Model1>();
}
Default
public partial class _Default : System.Web.UI.Page
{
[Inject]
public IAmAModel Model { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
System.Diagnostics.Trace.WriteLine(Model.ExecuteOperation());
}
}
Site.Master
public partial class SiteMaster : System.Web.UI.MasterPage
{
[Inject]
public IAmAModel Model { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
System.Diagnostics.Trace.WriteLine("From master: "
+ Model.ExecuteOperation());
}
}
Models
public interface IAmAModel
{
string ExecuteOperation();
}
public class Model1 : IAmAModel
{
public string ExecuteOperation()
{
return "I am a model 1";
}
}
public class Model2 : IAmAModel
{
public string ExecuteOperation()
{
return "I am a model 2";
}
}
Results from output window
I am a model 1
From master: I am a model 1
if (currentPage.Master!=null) { this.lazyKernel().Inject(currentPage.Master); }
–
Caliban I think here are the steps to implement Ninject.Web on ASP.NET Web Forms.
- Implement NinjectHttpApplication at Global.asax. For the Kernel, pass it in by implementing NinjectModule.
- On each web forms page load event at code behind, implement Ninject.Web.PageBase. Add instance class with [Inject] filter on top of it.
For more detailed example, below are some useful links I found:
Check the book "Pro ASP.NET MVC 2 Framework, 2nd Edition" by Steve Sanderson (Apress). The author uses Ninject to connect with a database. I think you can use the examples and adapt them to your needs.
public IGoalsService_CRUD _context { get; set; }
The _context object is being set to null somehow. Following are the rest of the settings
public partial class CreateGoal : Page
{
[Inject]
public IGoalsService_CRUD _context { get; set; }
}
For Global File
protected override IKernel CreateKernel()
{
IKernel kernel = new StandardKernel(new Bindings());
return kernel;
}
public class Bindings : NinjectModule
{
public override void Load()
{
Bind<goalsetterEntities>().To<goalsetterEntities>();
Bind<IGoalsService_CRUD>().To<GoalsService_CRUD>();
}
}
© 2022 - 2024 — McMap. All rights reserved.