TJ Bandrowsky
TJ Bandrowsky

Reputation: 882

Why doesn't Controller Factory use a Controller returned by that factory?

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;
    }

Upvotes: 1

Views: 194

Answers (1)

CtrlDot
CtrlDot

Reputation: 2513

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;
    }

Upvotes: 1

Related Questions