0

I have a default route with an optional id parameter that matches a lot of controller methods, which is desired.

routes.MapRoute(
  name: "Default",
  url: "{controller}/{action}/{id}",
  defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
);

Most controllers define the id param as an int rather than a nullable int. For example:

public ActionResult Detail(int id)
{
  var model = GetModel(id);
  return View(model);
}

The problem is that, in this large web app, occasionally some errant code will direct the user to a path without the id. For example, /ControllerName/Detail. The default route is invoked, but an exception is logged because of the missing parameter:

System.ArgumentException: The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Detail(Int32)'

There will be an effort to find out why such a request is happening in the first place, but I'd also like to avoid logging the exception, and show a 404 page instead of a 500 page. The questions I've seen provide solutions for an unknown controller or action, but not a param that the default route defines as optional, but the action method defines as required.

I've tried adding my "catchall" route before the default, with id given a value of 0:

routes.MapRoute(
  name: "CatchAll",
  url: "{controller}/{action}",
  defaults: new { controller = "Home", action = "Index", id = 0 },
);

This prevents the exception, but I want to show a 404 error page. Is there any way to do this in the route config, instead of changing every action method to expect an int? id and then redirecting to the 404 page if !id.HasValue?

Tap
  • 6,332
  • 3
  • 22
  • 25
  • 1
    Alternatively you can write an HTTP Request Filter (say, "CheckNonZeroId") and within the filter you can raise a 404 if id is zero or null. You can stick this filter on the actions or controllers you want to check for id. Checking for id at the route level can block pages like "/Help", "/Contact", "/Error" etc. from displaying. – TejSoft Jun 09 '21 at 02:03

1 Answers1

1

In my last project, I had a similar issue. This is what worked for me.

Try using int? while excepting parameters.

If it doesn't work, use string and then convert it to an integer.

[HttpGet]
public ActionResult MyFunction(string val)
{
   int n = Convert.ToInt32(val);
   ...logic
}

While implementing pagination with PagedList.MVC I used int? page and it didn't throw an exception.

ashish-98
  • 41
  • 1
  • 5