Change ASP.NET MVC Routes dynamically

flq picture flq · Mar 29, 2010 · Viewed 9.9k times · Source

usually, when I look at a ASP.Net MVC application, the Route table gets configured at startup and is not touched ever after.

I have a couple of questions on that but they are closely related to each other:

  • Is it possible to change the route table at runtime?
  • How would/should I avoid threading issues?
  • Is there maybe a better way to provide a dynamic URL? I know that IDs etc. can appear in the URL but can't see how this could be applicable in what I want to achieve.
  • How can I avoid that, even though I have the default controller/action route defined, that default route doesn't work for a specific combination, e.g. the "Post" action on the "Comments" controller is not available through the default route?

Background: Comment Spammers usually grab the posting URL from the website and then don't bother to go through the website anymore to do their automated spamming. If I regularly modify my post URL to some random one, spammers would have to go back to the site and find the correct post URL to try spamming. If that URL changes constantly I'd think that that could make the spammers' work more tedious, which should usually mean that they give up on the affected URL.

Answer

Tomasz Jaskuλa picture Tomasz Jaskuλa · Mar 29, 2010

I would consider to implement my own IRouteHandler and put some custom logic in my custom ControllerActionInvoker. How it would work ? The route table wouldn't dynamically change but you could check in your custom ControllerActionInvoker for a random parameter in the route path and invoke or not the corresponding action.

My route :

routes.Add 
( 
    new Route 
        ( 
            "blog/comment/{*data}", 
            new RouteValueDictionary(new {controller = "blog", action = "comment", data = ""}), 
            new MyRouteHandler() 
        ) 
); 

My I route handler :

    class MyRouteHandler : IRouteHandler 
{ 

public IHttpHandler GetHttpHandler(RequestContext requestContext) 
    { 
        return new MyHttpHandler(requestContext); 
    } 
}`

My handler :

class MyHttpHandler : MvcHandler 
{ 
    public MyHttpHandler(RequestContext requestContext) : base(requestContext) 
    { 
    } 

    protected override void ProcessRequest(HttpContextBase httpContext) 
    { 
        IController controller = new BlogController(); 
        (controller as Controller).ActionInvoker = new MyActionInvoker(); 
        controller.Execute(RequestContext); 
    } }`

and my action ivoker where the custom logic for handling an action or not should be coded :

    class MyActionInvoker : ControllerActionInvoker 
{ 
    protected override ActionResult InvokeActionMethod(MethodInfo methodInfo, IDictionary<string, object> parameters) 
    { 

        var data = ControllerContext.RouteData.GetRequiredString("data"); 


 // put my custom logic to check whetever I'll handle the action or not. The data could be a parameter in the database for that purpose.

        return base.InvokeActionMethod(methodInfo, parameters); 
    } 
} 

I don't know it it's the best solution but for now it's the one that comes to my mind.