I watched the first 2 beginner tutorials for Ninject on dimecasts.net. Now, I want to use Ninject 2.2 in ASP.NET MVC 3. I want a view with a mocked out Model. I get object reference not set to an instance of an object when calling my service;
public class HomeController : Controller
{
private readonly IMilestoneService _service;
public HomeController()
{
}
HomeController(IMilestoneService service)
{
_service = service;
}
public ActionResult Index()
{
ViewBag.Message = "Change Request System";
return View();
}
public ActionResult About()
{
return View();
}
#region Partial views
public ActionResult Milestone()
{
var result = _service.GetMileStones();//OBJECT REF ERROR
return View(result);
}
#endregion
}
//####GLOBAL.ASAX
//By using the NinjectHttpApplication, it automatically takes care of controllers, starting up mvc, etc.
//Ninject.Web.Mvc
public class MvcApplication : NinjectHttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
//StartNinject();
}
#region Inversion of Control
protected override IKernel CreateKernel()
{
return Container;
}
static IKernel _container;
public static IKernel Container
{
get
{
if (_container == null)
{
_container = new StandardKernel(new SiteModule());
}
return _container;
}
}
internal class SiteModule : NinjectModule
{
public override void Load()
{
//Set up ninject bindings here.
Bind<IMilestoneService>().To<MileStoneService>();
}
}
#endregion
}
I'm using Razor, he's the milestone partial view
@foreach (var item in Model)
{
<div>item.Name</div>
}
Finally, the Home view Index
@{
ViewBag.Title = "Home Page";
}
<h2>@ViewBag.Message</h2>
<p>
@Html.Action("Milestone");
</p>
Edit 11/20/2013
Note that Ninject has since released version 2.0. The changes are nicely outlined on their site. Of Note StandardModule
is now NinjectModule
and namespace Ninject.Core
no longer exists. I was able to replace it with just Ninject
.
There is an issue with your controller class, the constructor with the dependency is private. Your controller should look like:
public class HomeController : Controller
{
private readonly IMilestoneService _service;
public HomeController(IMilestoneService service)
{
_service = service;
}
}
Don't even include a public parameterless constructor, it isn't even valid, your class needs that dependency to function.
In fact, I also insert a null check against that dependency in the constructor just to be sure my class is valid on construction:
public class HomeController : Controller
{
private readonly IMilestoneService _service;
public HomeController(IMilestoneService service)
{
_service = service;
Enforce.NotNull(() => _service); // lambda to auto-magically get variable name for exception
}
}
There also may be an issue with your MvcApplication class.
Instead of protected void Application_Start()
, there is a different function you can override, protected override void OnApplicationStarted()
This is where your calls to setup routing should go:
public class MvcApplication : NinjectHttpApplication
{
public override void Init()
{
base.Init();
Mappers.Initialize();
}
protected override Ninject.IKernel CreateKernel()
{
return Ioc.Initialize();
}
protected override void OnApplicationStarted()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
public static void RegisterRoutes(RouteCollection routes)
{
Routing.RegisterRoutes(routes);
//RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
}
}
Of course, if you are already calling Application_Start
that's fine too, but I didn't see it in the OP.