tags:

views:

47

answers:

1

I have a virtual function that is called handlePathChange() in my Controller class.
It checks the current URL and should dispatch the right view for it.
Here's the code I have so far:

void Controller::handlePathChange()
{
    if ( app->internalPathMatches(basePath) )
    {
        string path = app->internalPathNextPart(basePath);

        if ( path.empty() ) // If it's empty it is known that the index of the controller should show up
            index();
        // else if ( path == ?? ) each controller has it's own routes
        //   call_some_unknown_function();
    }
}

How can I generalize this?
I was thinking about two options:

  1. Call a pure virtual function called dispatch() that will match the right path to the right function in the derived class. This solution violates DRY as basically you will write the same code over and over again.
  2. Create a hash maps of std::function but then if a part of the url is a parameter then the view won't be found. So that option isn't good enough.

Any ideas?

+1  A: 

I realize your post uses a c++ example, but if you don't mind reading some c#, this article by Scott Guthrie is a great overview of how the ASP.NET MVC framework implements its routing:

http://weblogs.asp.net/scottgu/archive/2007/12/03/asp-net-mvc-framework-part-2-url-routing.aspx

I think you will find that article very helpful. In an overly simplified sort-of-way, it is similar to your option #2, yet it always checks for a parameter. If the parameter is not provided, it uses the same routing rule, but provides a "default" value and sends the request to the correct view. That strategy avoids the problem you mention where you can't find the appropriate view if the parameter is specified.

Hope this helps.

Chris Melinn
There is a problem here since C++ lacks reflection. I can't call index() out of the string "index". Moreover I can't have an heterogeneous container that contains function objects that don't have the same length of parameters?
the_drow
Ah, I see. Not sure how to handle the dynamic invocation other than what you suggest in #1 and #2. However, with the parameters, couldn't you assume the same number of parameters and then just provide defaults? For example, - parse the URL - identify the intended action as first/middle part of URL - assign additional parameters if supplied - otherwise, send defaults for parameter values? Seems like using that approach your option #2 might work?
Chris Melinn
I've started writing it. As of now I am using a hash map of parameters (key : string, value : string), what I mean is if they don't match a controller or an action then it is added to the parameters. Now I am implementing the defaults. How would you implement setView like in ASP.Net MVC?
the_drow
As I understand it (admittedly roughly), in ASP.NET MVC, the controller returns the View (technically a ViewResult, which derives from ActionResult). Then, the pipeline invokes ExecuteResult on the returned object, which essentially renders the page output. So, depending on the rest of your architecture, you might be able to do the same? Are you able to define a common interface for all of your views with some sort of render method on the interface? If you're building a web framework, it might not be so bad. If you have a windows app, then it may be more difficult to render().
Chris Melinn
I'm programming an MVC wrapper for a C++ Web Framework.Currently I'm returning the view just like you said but I came across another problem.In the view there are widgets right?Each of their events bind to certain functions like onClick -> handleButtonClick(), instead I want them to reroute to another action or maybe even a different controller.How is it done in ASP.Net MVC?I'm accepting your answer as the correct one because you got me to the right direction. Thank you very much.
the_drow
In ASP.NET MVC, such events are generally just new GET/POST requests that go back to the web server and therefore uses the standard event routing. For example, a button click is generally a new http form post with a specified action. Similarly, there is also a Controller.RedirectToAction method (see http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.redirecttoaction.aspx) that returns a 302 response to a browser, causing another GET request. So, easier said than done, the trick is to rewire your events to do another server POST/GET request. Hope this helps.
Chris Melinn