vote up 6 vote down
star
5

What's the best way to handle a visitor constructing their own URL and replacing what we expect to be an ID with anything they like?

For example:

http://stackoverflow.com/questions/236349

But the user could just as easily replace the URL with:

http://stackoverflow.com/questions/foo

I've thought of making every Controller Function parameter a String, and using Integer.TryParse() on them - if that passes then I have an ID and can continue, otherwise I can redirect the user to an Unknown / not-found or index View.

Stack Overflow handles it nicely, and I'd like to too - how do you do it, or what would you suggest?

offensive?
add comment

5 Answers:

vote up 4 vote down

Here's an example of a route like yours, with a constraint on the number:

routes.MapRoute(
	"Question",
	"questions/{questionID}",
	new { controller = "StackOverflow", action = "Question" },
	new { questionID = @"\d{1,}" }
);

Here we set the questionID to have at least one number. This will also block out any urls containing anything but an integer, and also prevents the need for a nullable int.

If the user enters the url "questions/foo", they will not hit the Question action, and fall through it, because it fails the parameter constraint. You can handle it further down in a catchall/default route if you want:

routes.MapRoute(
	"Catchall",
	"{*catchall}",
	new { controller = "Home", action = "Lost" }
);

This will push the user onto the Lost action in the home controller, where you may want to punish them for their sillyness. :-)

Please note that this should reside as the LAST route. Placing it further up the chain will mean that this will handle all others below it, given the lazy nature of routes in ASP.NET MVC.

link|offensive?
add comment
vote up 3 vote down

In ASP.NET MVC, you can define a filter implementing IActionFilter interface. You will be able to decorate your action with this attribute so that it will be executed on, before or after your action.

In your case, you will define it to be executed "before" your action. So that, you will be able to cancel it if there is an error in the passed parameters. The key benefit here that you only write the code which checking the passed paramaters once (i.e you define it in your filter) and use it wherever you want in your controller actions.

Read more about MVC filters here: http://haacked.com/archive/2008/08/14/aspnetmvc-filters.aspx

link|offensive?
add comment
vote up 3 vote down

Here is some useful infromation that might help. If you have a action method

public ActionResult Edit(int? id)
{}

then if someone types in

/Home/Edit/23

the parameter id will be 23. however if someone types in

/Home/Edit/Junk

then id will be null which is pretty cool. I thought it would throw a cast error or something. It means that if id is not a null value then it is a valid integer and can be passed to your services etc. for db interaction.

Hope this provides you with some info that I have found whilst testing.

link|offensive?
comments (1)
vote up 2 vote down

You can specify constraints as regular expressions or define custom constraints. Have a look at this blog post for more information:

http://weblogs.asp.net/stephenwalther/archive/2008/08/06/asp-net-mvc-tip-30-create-custom-route-constraints.aspx

You will still need to deal with the situation where id 43243 doesn't map to anything which could be dealt with as an IActionFilter or in your controller directly.

link|offensive?
add comment
vote up 0 vote down

The problem with that approach is that they still might pass an integer which doesn't map to a page. Just return a 404 if they do that, just as you would with "foo". It's not something to worry about unless you have clear security implications.

link|offensive?
comments (1)

Your Answer:

Get an OpenID
or

Not the answer you're looking for? Browse other questions tagged or ask your own question.