views:

1895

answers:

3

hi all,

I have currently the following routes:

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.IgnoreRoute("{resource}.gif/{*pathInfo}");

        MvcRoute.MappUrl("{controller}/{action}/{ID}")
            .WithDefaults(new { controller = "home", action = "index", ID = 0 })
            .WithConstraints(new { controller = "..." })
            .AddWithName("default", routes)
            .RouteHandler = new MvcRouteHandler();

        MvcRoute.MappUrl("{title}/{ID}")
            .WithDefaults(new { controller = "special", action = "Index" })
            .AddWithName("view", routes)
            .RouteHandler = new MvcRouteHandler();

The SpecialController has a method : public ActionResult Index(int ID)

whenever i point my browser to : http://hostname/test/5 i get the following error:

The parameters dictionary contains a null entry for parameter 'ID' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Index(Int32)' in 'SpecialController'. To make a parameter optional its type should be either a reference type or a Nullable type. Parameter name: parameters Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Do you have any idea why is that? I used the mvccontrib route debugger and it seems that the route is accessible as expected

+2  A: 

It's exactly as the error message says. You've got a parameter called "ID" which has no default value, but your method is expecting a non-nullable int. Because there is no default value, it's trying to pass in a "null", but... it can't, because your int parameter is non-nullable.

The route debugger probably doesn't check types for nullable.

To fix it:

 MvcRoute.MappUrl("{title}/{ID}")
        .WithDefaults(new { controller = "special", action = "Index", ID = 0 })
        .AddWithName("view", routes)
        .RouteHandler = new MvcRouteHandler();
womp
i dont think thats the case cause even after i added the default ID (which i had tried before as well) it still throws the same exception.
Yannis
Can you post the code for your MappUrl extension method?
womp
thats not my code. thats part of the mvccontrib and i dont have the source available
Yannis
After playing with it for the past hour or so the view configuration is now as follows. However, the problem still remains...MvcRoute.MappUrl("{controller}/{ID}/{questionTitle}") .WithDefaults(new { controller = "special", action = "Index", ID = 0 }) .AddWithName("view", routes) .RouteHandler = new MvcRouteHandler(); -- default route omited
Yannis
+2  A: 

I think you should put your custom route before the default one.

http://weblogs.asp.net/scottgu/archive/2007/12/03/asp-net-mvc-framework-part-2-url-routing.aspx

CD
+1 I think you may be right here. Also check out Phil Haack's article re route debugging: http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx
Alan Christensen
unfortunatelly thats not the solution either. but you are right in that the default should go at the end to be treated as a last resort.
Yannis
I'm afraid this might be a defect in mvccontrib. I tried your scenario by mapping the route directly into the RouteCollection (not using mvccontrib) and it worked as expected.
CD
can you show me the routes you used? thx
Yannis
routes.MapRoute( "special", "{title}/{ID}", new { controller = "special", action = "Index" } );routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = "" } // Parameter defaults );
CD
still doesnt work...The controller has the index method as follows: public SpecialControllere() { // init stuff } public ActionResult Index(int ID) { // do stuff return View(form); }
Yannis
That's odd! I've done exactly the same, but it works for me...public class SpecialController : Controller { public ActionResult Index(int ID) { return View(); } }
CD
+1  A: 

Yannis, did you ever find a solution to this problem? I propose the solution was your route variable names did not match your action parameter names.

// Global.asax.cs
MvcRoute.MappUrl("{controller}/{action}/{ID}")
        .WithDefaults(new { controller = "home", action = "index", ID = 0 })
        .WithConstraints(new { controller = "..." })
        .AddWithName("default", routes)
        .RouteHandler = new MvcRouteHandler();

This would work:

// Controller.cs
public ActionResult Index(int ID){...}

Where this wouldn't:

// Controller.cs
public ActionResult Index(int otherID) {...}
Becky