1

I implemented a custom controller factory in ASP.NET MVC, and I registered it in global.ascx. The idea is to handle the case of 404 and also exceptions in the controller constructors. I know the factory has been assigned to ASP.NET MVC, because on requests, I can step into it. I can see that I'm returning the controller that I think. But why, oh why on earth, is not my controller used? But I'd think I'd get the usual action not found exception, not controller..conceptually I'm wondering if this is even the right spot to do this in.

 protected override IController GetControllerInstance
    (RequestContext context, 
    Type controllerType)
    {
        IController controller = null;

        try
        {
            controller = base.GetControllerInstance(context, controllerType);
        }
        catch (CurrentSessionException)
        {
            controller = new LoginController();
        }
        catch (System.Web.HttpException)
        {
            controller = new ErrorController();
        }
        catch (System.Exception)
        {
            controller = new ErrorController();
        }

        return controller;
    }
MikeSmithDev
  • 15,731
  • 4
  • 58
  • 89
TJ Bandrowsky
  • 842
  • 8
  • 12
  • Can we see the class for the method you provided and how you registered your Controller Factory? I'd also mention if you haven't to take a look at the answers in [How can I properly handle 404 in ASP.NET MVC?](http://stackoverflow.com/questions/619895/how-can-i-properly-handle-404-in-asp-net-mvc). – Erik Philips Feb 10 '14 at 21:14
  • Oh I read the example in the link you provided. It looks like the simple explanation is that it doesn't work through the Visual Studio Debugger but works like a champ when deployed to IIS 7.5. – TJ Bandrowsky Feb 10 '14 at 21:22
  • I haven't had any problems using [IIS Express](http://blogs.msdn.com/b/webdev/archive/2011/03/14/enabling-iis-express-support-in-vs-2010-sp1.aspx). – Erik Philips Feb 10 '14 at 21:31
  • Am using Visual Studio Development Server in VS 2010... – TJ Bandrowsky Feb 10 '14 at 21:35
  • I am using IIS Express with VS 2010 (**not** the Visual Studio ASP.Net Development Server aka Cassini, if you aren't using IIS Express I would Highly recommend reading my previous link). – Erik Philips Feb 10 '14 at 21:37
  • New job... didn't even think to check it. But I did read the link you sent, religiously today it's excellent... but was drilled in on everything but Cassini as an issue. – TJ Bandrowsky Feb 10 '14 at 21:44
  • Would this not be better handled via a CustomErrorFilter? – CtrlDot Feb 10 '14 at 22:18

1 Answers1

1

Try manually clearing the errors in your catch statement.

requestContext.HttpContext.ClearError();

Ideally this is best handled as a Filter. MVC comes with a HandleErrorAttribute which you can subclass. You would override the OnException method and then simple handle the logic as you wish.

This is what MVC 3 does by default.

        public virtual void OnException(ExceptionContext filterContext) {
        if (filterContext == null) {
            throw new ArgumentNullException("filterContext");
        }
        if (filterContext.IsChildAction) {
            return;
        }

        // If custom errors are disabled, we need to let the normal ASP.NET exception handler
        // execute so that the user can see useful debugging information.
        if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled) {
            return;
        }

        Exception exception = filterContext.Exception;

        // If this is not an HTTP 500 (for example, if somebody throws an HTTP 404 from an action method),
        // ignore it.
        if (new HttpException(null, exception).GetHttpCode() != 500) {
            return;
        }

        if (!ExceptionType.IsInstanceOfType(exception)) {
            return;
        }

        string controllerName = (string)filterContext.RouteData.Values["controller"];
        string actionName = (string)filterContext.RouteData.Values["action"];
        HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
        filterContext.Result = new ViewResult {
            ViewName = View,
            MasterName = Master,
            ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
            TempData = filterContext.Controller.TempData
        };
        filterContext.ExceptionHandled = true;
        filterContext.HttpContext.Response.Clear();
        filterContext.HttpContext.Response.StatusCode = 500;

        // Certain versions of IIS will sometimes use their own error page when
        // they detect a server error. Setting this property indicates that we
        // want it to try to render ASP.NET MVC's error page instead.
        filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
    }
CtrlDot
  • 2,463
  • 14
  • 11