1

I am wondering if there is any way of preventing an asp.net mvc controller from being executed, using an attribute if a particular criteria is not met when the controller was called?

What am basically trying to accomplish is to create something like an action filter but this time for a controller that is called before the controller is initialized and only if the filter succeeds before it is constructed, if not the attribute filter should be able to redirect the user to another controller.

6
  • can you do it in the constructor instead? Commented Mar 17, 2016 at 2:02
  • 1
    This smells a bit like an X-Y Problem. Why do you care if the controller is constructed unless you are doing way too much in the constructor? Commented Mar 17, 2016 at 2:04
  • What am trying to is before constructing the controller, check if the part of the application is configured/enabled then either go ahead or redirect the user depending on the result. In essence I do not want to bother initializing a controller if there is no need for it Commented Mar 17, 2016 at 2:07
  • You can define your custom atrribute filters in this case Commented Mar 17, 2016 at 3:41
  • If I understand your question correctly. You're saying that the Controllers is being constructed even if it is not needed or being Instantiated anywhere in your code? Wow, that is new to me. Commented Mar 17, 2016 at 5:03

1 Answer 1

2

If you want to change controllers dynamically, the place to do it is in a custom RouteBase subclass. Redirection is a bad idea because your server will issue a 301 or 302 to the client's browser telling it to lookup a new location on the server. That round-trip is wasteful and unnecessary.

public class SwitcherRoute : RouteBase
{
    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        RouteData result = null;

        // Trim the leading slash
        var path = httpContext.Request.Path.Substring(1);

        // Check that the request is what you are interested in
        if (path.Equals("home/about", StringComparison.OrdinalIgnoreCase))
        {
            result = new RouteData(this, new MvcRouteHandler());


            if (/* some (preferably cached) condition */)
            {
                result.Values["controller"] = "Home";
                result.Values["action"] = "About";
            } 
            else 
            {
                result.Values["controller"] = "Alternate";
                result.Values["action"] = "About";
            }
        }

        // IMPORTANT: Always return null if there is no match.
        // This tells .NET routing to check the next route that is registered.
        return result;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        VirtualPathData result = null;

        var controller = Convert.ToString(values["controller"]);
        var action = Convert.ToString(values["action"]);

        if (action.Equals("About", StringComparison.OrdinalIgnoreCase))
        {
            if (controller.Equals("Home", StringComparison.OrdinalIgnoreCase) || 
                controller.Equals("Alternate", StringComparison.OrdinalIgnoreCase))
            {
                return new VirtualPathData(this, "home/about");
            }
        }

        // IMPORTANT: Always return null if there is no match.
        // This tells .NET routing to check the next route that is registered.
        return result;
    }
}

Usage

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.Add(
    name: "AboutPage", 
    item: new SwitcherRoute());

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

Note that you can make your custom route more flexible by accepting constructor parameters or even inheriting from the built-in Route class.

Also note that routes run on every request, so you should cache any expensive lookup operations as in this example.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.