views:

237

answers:

2

I'm working on an ASP.NET MVC task list and I'd like to get fancy with the URL routing when filtering the list. I have an action method defined like this:

public ActionResult List(int categoryID, bool showCompleted, TaskFilter filter);

enum TaskFilter { MyTasks, MyDepartmentTasks, AllTasks }

I want my URLs to look like this:

/Tasks/Category4/MyTasks/ShowCompleted/
/Tasks/Category4/MyDepartment
/Tasks/Category4/

The Category# segment will always be present. I'd like the MyTasks|MyDepartment|AllTasks segment to be optional, defaulting to AllTasks if absent. I'd also like ShowCompleted to be optional, defaulting to false.

Is this sort of routing possible, or am I going to have to fall back and just use querystring parameters?

Followup/extra credit question: What if I also wanted a fourth parameter on the action method to filter by task due date that looked like Today|Day2Through10 (default Today if absent)?

+3  A: 

The following covers your first question with a slight change:

routes.MapRoute(
    "t1",
    "Tasks/Category{categoryID}",
    new
    {
        controller = "Task",
        action = "List",
        showCompleted = false,
        strFilter = TaskFilter.AllTasks.ToString()
    }
    );

routes.MapRoute(
    "t2",
    "Tasks/Category{categoryID}/{strFilter}/",
    new
    {
        controller = "Task",
        action = "List",
        showCompleted = false
    }
);

routes.MapRoute(
    "t3",
    "Tasks/Category{categoryID}/{strFilter}/ShowCompleted",
    new { controller = "Task", action = "List", showCompleted = true }
    );

You will need to change the List method to start like the following:

public ActionResult List(int categoryID, bool showCompleted, string strFilter)
{
    TaskFilter filter = (TaskFilter)Enum.Parse(typeof(TaskFilter), strFilter);

For your second query, you just need to use {Day2} and such to be passed to the ActionResult. You should be able to figure it out from what I've given you.

Yuriy Faktorovich
Thanks. Out of curiosity, what would I have to do to have a TaskFilter be passed to the action method as an Enum instead of a string? Which part of the routing infrastructure would I have to extend/override?
Brant Bobby
@Brant Bobby: That is an interesting question. It may be possible by implementing IController instead of Controller for your TaskController. Where you would implement the Execute method to first change the string to TaskFilter type and then use it to call your List method.
Yuriy Faktorovich
@Brant Bobby: Also I just noticed you could still inherit from Controller and just override the Execute method. There are a few other interesting methods in there that may be a possibility.
Yuriy Faktorovich
A: 

Look into the MvcContrib library. Here's an example of the fluent interface of adding routes with constraints: http://www.codinginstinct.com/2008/09/url-routing-available-in-mvccontrib.html

Agent_9191