Invalid mvc action arguments give an exception 500 argument instead of 404

When I have a controller action like this.

public ActionResult _Files(long parentid) { 

if you invoke an action from a browser without a parent element. It throws a System.ArgumentException and 500 responses

The parameter dictionary contains a null entry for the parameter "parentid" of the non-empty type "System.Int64" for the method 'System.Web.Mvc.ActionResult _Files

The action should NOT be called without PARENTID by design. Is there a way not to throw an exception (and return 500 responses back), and instead return 400 bad requests or 404 not found (any of which will make more sense to IMO). Looking for a solution that will do this in a general way through a web application?

+6
source share
3 answers

I suggest you take a look at the limitations of the route. Creating a route restriction requires that the integer be passed as the parent element, and if it is not specified, the route will not match, and the default value is 404.

Here is an example:

 routes.MapRoute( name: "MyController", url: "MyController/{parentid}", defaults: new { controller = "MyController", action = "Index" }, constraints: new { parentid = @"\d+" } ); 

For more information on route restrictions, see this article.

The only drawback of this approach is that the regular expression does not check if the input value is long or something big. However, if this is a concern, you can easily create a custom route restriction that will check if the input value can be parsed as long .

+4
source

Link: http://prideparrot.com/blog/archive/2012/5/exception_handling_in_asp_net_mvc

Create an error controller class and corresponding views:

 public class ErrorController : Controller { public ActionResult Index() { return View(); } public ActionResult NotFound() { return View(); } } 

at Global.asax.cs:

 protected void Application_Error(object sender, EventArgs e) { var httpContext = ((MvcApplication)sender).Context; var currentController = " "; var currentAction = " "; var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext)); if (currentRouteData != null) { if (currentRouteData.Values["controller"] != null && !String.IsNullOrEmpty(currentRouteData.Values["controller"].ToString())) { currentController = currentRouteData.Values["controller"].ToString(); } if (currentRouteData.Values["action"] != null && !String.IsNullOrEmpty(currentRouteData.Values["action"].ToString())) { currentAction = currentRouteData.Values["action"].ToString(); } } var ex = Server.GetLastError(); var controller = new ErrorController(); var routeData = new RouteData(); var action = "Index"; var statusCode = 500; if (ex is ArgumentException) { action = "NotFound"; statusCode = 404; } httpContext.ClearError(); httpContext.Response.Clear(); httpContext.Response.StatusCode = statusCode; httpContext.Response.TrySkipIisCustomErrors = true; routeData.Values["controller"] = "Error"; routeData.Values["action"] = action; controller.ViewData.Model = new HandleErrorInfo(ex, currentController, currentAction); ((IController)controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData)); } 
+3
source

what can you do:

  public ActionResult _Files(long ? parentid) { 

parentId is NULL.

Then in your action you need to process it like this:

  public ActionResult _Files(long ? parentid) { if(parentId.HasValue == false) {return some http status code;} // Then you can use parentId with its Value property. 
+2
source

All Articles