3

In ASP.NET MVC apps, when we scaffold the controllers in Visual Studio, we get the default actions:

  • Index
  • Create
  • Delete
  • Edit
  • Details

Of the above, a few have a nullable id (int? id) for parameters: Details, Edit (GET version), Delete, DeleteConfirmed. Then in at least some, there's the following code to ensure that ID isn't null:

if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } 

All these actions require an ID; it's not optional. You can't display the details of nothing or delete nothing, etc. Also, we're then generating a BadRequest status code if they're null.

So why aren't these parameters non-nullable integers to begin with?

4
  • 4
    Urls are strings, "id" is an int. What happens when a parameter in the route cannot be converted into an int? Should it be some generic error or should your controller get to dictate what to do with an invalid (i.e null) id? Commented Oct 4, 2017 at 20:41
  • Thanks, @maccettura. But if it's null, we should throw an exception to let the user know. Or should we detect it via the check that Visual Studio generates for us? Commented Oct 4, 2017 at 20:42
  • 2
    Should you always throw an exception? Is there some special processing that should happen? Should it be logged? The boilerplate code included with the MVC code is just a suggestion, its not a requirement. Commented Oct 4, 2017 at 20:44
  • 2
    Also, an invalid parameter (e.g. null in your example) should not throw an exception at all, because it is a Client issue, not a server one. BadRequest (400) is exactly the status code for this kind of issues (signaling a client that it has sent an invalid request). Commented Oct 4, 2017 at 20:50

1 Answer 1

3

I believe it's because the default value for int is 0. If you set it to int id as you suggest, the model-binder will give you a default value of 0, which means you can't differentiate between whether 0 was actually provided or if it was just defaulted.

EDIT: Been thinking about this a bit more. It's optional because it's defined at a higher level for the general routing template - some actions require it and others don't.

I was wrong about the defaulting of 0 for a simple parameter like this - see the comments.

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

3 Comments

Hmm. Hadn't thought of that at all. Yeah, 0 could be a valid record ID, whereas int? id truly offers blank/null.
Wrong - it its not provided an exception is thrown
Actually, the above isn't true: when I leave the id blank and try to navigate to a page, it simply blows up and says: The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Threading.Tasks.Task1 [System.Web.Mvc.ActionResult] Edit(Int32)' in 'MyController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter. Parameter name: parameters`. So it's not defaulting to 0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.