ASP.NET MVC, Ninject.Web.Mvc and 404’s
I went about trying to handle 404 errors on my ASP.NET MVC application by following code I found here.
protected void Application_Error( object sender, EventArgs e ) { var exception = Server.GetLastError(); Response.Clear(); var httpException = exception as HttpException; var routeData = new RouteData(); routeData.Values.Add( "controller", "Error" ); if( httpException == null ) { routeData.Values.Add( "action", "Index" ); } else //It's an Http Exception, Let's handle it. { switch( httpException.GetHttpCode() ) { case 404: // Page not found. routeData.Values.Add( "action", "HttpError404" ); break; case 500: // Server error. routeData.Values.Add( "action", "HttpError500" ); break; // Here you can handle Views to other error codes. // I choose a General error template default: routeData.Values.Add( "action", "General" ); break; } } // Pass exception details to the target error View. routeData.Values.Add( "error", exception ); // Clear the error on server. Server.ClearError(); // Call target Controller and pass the routeData. IController errorController = new ErrorController(); errorController.Execute( new RequestContext( new HttpContextWrapper( Context ), routeData ) ); }
Although, this didn’t work for me because I’m using Ninject.Web.Mvc. Instead, I get this error:
The IControllerFactory ‘Ninject.Web.Mvc.NinjectControllerFactory’ did not return a controller for a controller named ‘blah’.
The NinjectControllerFactory.CreateController( RequestContext requestContext, string controllerName ) method is returning null when it can’t find a controller, when it should be throwing a 404 HttpException.
There apparently is a patch waiting to be merged into trunk for this, but until then, you can use this change to the controller factory. The factory now inherits from DefaultControllerFactory, CreateController and ReleaseController are now overrides, and a test for a null controller will call base.CreateController.
using System; using System.Globalization; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace Ninject.Web.Mvc { /// <summary> /// A controller factory that creates <see cref="IController"/>s via Ninject. /// </summary> public class NinjectControllerFactory : DefaultControllerFactory { /// <summary> /// Gets the kernel that will be used to create controllers. /// </summary> public IKernel Kernel { get; private set; } /// <summary> /// Initializes a new instance of the <see cref="NinjectControllerFactory"/> class. /// </summary> /// <param name="kernel">The kernel that should be used to create controllers.</param> public NinjectControllerFactory(IKernel kernel) { Kernel = kernel; } /// <summary> /// Creates the controller with the specified name. /// </summary> /// <param name="requestContext">The request context.</param> /// <param name="controllerName">Name of the controller.</param> /// <returns>The created controller.</returns> public override IController CreateController(RequestContext requestContext, string controllerName) { var controller = Kernel.TryGet<IController>(controllerName.ToLowerInvariant()); if(controller == null) return base.CreateController(requestContext, controllerName); var standardController = controller as Controller; if(standardController != null) standardController.ActionInvoker = new NinjectActionInvoker(Kernel); return controller; } /// <summary> /// Releases the specified controller. /// </summary> /// <param name="controller">The controller to release.</param> public override void ReleaseController(IController controller) { } } }
[...] to VoteASP.NET MVC, Ninject.Web.Mvc and 404’s (8/6/2009)Thursday, August 06, 2009 from joshcloseI went about trying to handle 404 errors on my ASP.NET MVC [...]