NYCChris
NYCChris

Reputation: 649

MVC 3 Route resolution question

I have the following 3 routes

This is how I register the routes in my global.asax.cs file

//Student Checkin
routes.MapRoute("StudentAvailableClasses_GetAllForStudent",
            "student/available/classes/{id}",
            new {controller = "StudentCheckin", action = "GetById"});
routes.MapRoute("StudentAvailableClasses_GetClassForStudent",
            "student/available/classes/{studentId}/{classTypeId}",
            new { controller = "StudentCheckin", action = "GetByStudentAndClassType" });
routes.MapRoute("StudentAvailableClasses_Query",
            "student/available/classes/query/{q}",
            new { controller = "StudentCheckin", action = "Query" });

When I execute this url

student/available/classes/query/smith+john

MVC tries to run this route:

student/available/classes/{studentId}/{classTypeId}

If I reverse the order in which I register the Query route with the GetClassForStudent route, MVC resolves to the query route.

What is going on here, and how can I register these routes with MVC so that they all resolve correctly?

UPDATE

Wow, once again thank you to everyone here on stackoverflow! Based on everyone's responses, and in particular the answer by Beno, I now understand my issue, and was able to make it work!

From what I understand, I was not giving MVC enough information about the routes. It was matching the word 'query' into the {studentId} parameter. From Beno's answer I learned about parameter constraints. So now I am able to tell MVC to expect a Guid type in the {studentId} (and {customerId}) parameter.

Here is the code now.

    //Student Checkin
    routes.MapRoute("StudentAvailableClasses_GetAllForStudent",
                    "student/available/classes/{id}",
                    new {controller = "StudentCheckin", action = "GetById"},
                    new {id = new GuidConstraint()});
    routes.MapRoute("StudentAvailableClasses_GetClassForStudent",
                    "student/available/classes/{studentId}/{classTypeId}",
                    new {controller = "StudentCheckin", action = "GetByStudentAndClassType"},
                    new {studentId = new GuidConstraint(), classTypeId = new GuidConstraint()});
    routes.MapRoute("StudentAvailableClasses_Query",
                    "student/available/classes/query/{q}",
                    new { controller = "StudentCheckin", action = "Query" });

The class GuidConstraint I found from this stackoverflow question.

Thank you!

Upvotes: 0

Views: 1512

Answers (3)

Beno
Beno

Reputation: 4753

What is going on here?

The URL, student/available/classes/query/smith+john is correctly picked up by the route student/available/classes/{studentId}/{classTypeId} since {studentID} can be anything, including 'query'. 'smith+john' is then picked up as the {classTypeId}

how can I register these routes with MVC so that they all resolve correctly?

You could add some validation to the {studentId} field. I don't know what your studentId is but if it's an 8 digit number:

routes.MapRoute("StudentAvailableClasses_GetClassForStudent",
       "student/available/classes/{studentId}/{classTypeId}",
       new { controller = "StudentCheckin", action = "GetByStudentAndClassType" }
       new { studentId = @"\d{8}" } );

OR

you could place the StudentAvailableClasses_Query route at the top so it gets matched before the other one

OR

a combination of both which is probably the best bet

Upvotes: 1

Chase Florell
Chase Florell

Reputation: 47397

I would highly recommed running your routes through the Routing Debugger. It will show you exactly where your hangups are.

Route Tester

Upvotes: 2

counsellorben
counsellorben

Reputation: 10924

Routes resolve in the order in which you register them. Always register more specific routes before more general routes.

To resolve your issue, move the "StudentAvailableClasses_Query" route to be the first one mapped.

counsellorben

Upvotes: 0

Related Questions