2

I have an controller (Product) with several actions, some have a required parameter (Edit, Details, History) and some have a nullable parameter (Create, Search). The default route with the optional parameter will route to all of the actions, but an error will be thrown if the user enters a url pointing to a controller/action with a required parameter i.e., Product/History. What is the best place to handle this? Should I:

  1. define routes for the actions with the required with parameter as having a required URL parameter?

     routes.MapRoute(  
               name: "ProductParamRequired",  
               url: "Product/History/{id}",  
               defaults: new { controller = "Product", action = "History"}  
           );  
    
  2. change the action to have an optional parameter and return bad request.

    public ActionResult History(int? id)
        {
            if (id == null)
            {
                throw new HttpException(400, "BadRequest");
            }
    
  3. let the application throw a 500 internal server error and show that (customized error page, of course) to the user?

Thank you and happy Friday!

1 Answer 1

1

If it's required, absolutely make it required as part of the route. If a request doesn't even have the data you're expecting, don't entertain the idea of processing it. It's much more costly to fix bad data that you've let into your application as opposed to validating it at the edge of your application. Always validate input as early as possible.

2 isn't a good idea, because you'll end up duplicating this pattern for every action and every required parameter that you have.

3 isn't a good idea, because you're not even trying to validate the data. That's always asking for trouble.

1 is fine, because it presumably falls back to your default route of product/history.

As an aside, making use of attribute routing can prevent you from having an enormous RouteConfig to maintain when you explicitly define your routes.

Sign up to request clarification or add additional context in comments.

9 Comments

It seems that if I go with option 1, then when the url ~/product/history is entered, the default MVC route is reached which is {controller}/{action}/{id} with id being optional, then it ends up at the product/history action method and returns a 500 error because the int parameter was required. So, it seems there was no point in defining the route with the id as required?
@user3281004 Not quite. This works because you have a fallback route, but that isn't always the case. For example, imagine a route such as /product/edit/{id}. If id was not required, falling back to /product/edit wouldn't make much sense, as how would we know what product was intending to be edited. Require your parameters when they needed to fulfil a contract.
@user3281004 So you'd have two actions: public ActionResult History() and public ActionResult History(int id). Notice how the id in the second action is not nullable.
thank you for your time. Is it ok to let the invalid url to fall through to the default route, go to the controller and action and return the 500 because the id was required? Or, do I need to implement constraints on the default route somehow so that if a user enters product/history (or any other controller/action that has a required parameter) without a required parameter a 404 error is returned?
@user3281004 You're welcome. :) It's fine to let it go through to whichever routes happen to match it, as you have no way of telling whether the request was genuinely trying to get to one route or another. If no route matches, 404 is entirely appropriate.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.