3

I'm at a loss for why this routing issue is occurring.

Route in Global.asax.cs file:

routes.MapRoute(
    "Archives", //Route name
    "{controller}/{action}/{month}", // URL with parameters
    new { controller = "Articles", action = "Archives" },
    new { month = @"^\d+" } // Parameter.defaults
);

Controller:

public ActionResult Archives(int month)
{
    ViewData["month"] = month;
    return View(article);
}

Which keeps throwing the error:

The parameters dictionary contains a null entry for parameter 'month' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Archives(Int32)' in 'AppleWeb.Controllers.ArticlesController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter. Parameter name: parameters

Which is bogus because the URL is: http://localhost:64529/Articles/Archives/12

EDIT- Full routing for all to see:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    //routes.IgnoreRoute("tellerSurvey.htm/{*pathInfo}");routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Appleweb", action = "Index", id = UrlParameter.Optional } // Parameter defaults
    );

    routes.MapRoute(
        "Contact", //Route name
        "{controller}/{action}/{page}", //URL with parameters
        new { controller = "Appleweb", action = "Contact", page = UrlParameter.Optional } // Paramter defaults
    );

    routes.MapRoute(
        "FormDetails", //Route name
        "{controller}/{action}/{formid}", // URL with parameters
        new { controller = "Resources", action = "FormDetails", formid = 0}
    );

    routes.MapRoute(
        "_calc",
        "{controller}/{action}/{calcid}", // URL with parameters
        new { controller = "Resources", action = "Calc", calcid = UrlParameter.Optional } // Parameter defaults
    );

    routes.MapRoute(
        "Article", //Route name
        "{controller}/{action}/{articleid}", // URL with parameters
        new { controller = "Articles", action = "Article", id = 0 } // Parameter.defaults
    );}

This is an MVC 3 project, so no routingconfig.cs.

3
  • 2
    Do you need this line new { month = @"^\d+" }? Commented Feb 3, 2014 at 16:14
  • 2
    can you please post your complete RouteConfig.cs? Commented Feb 3, 2014 at 16:14
  • 2
    Paste full list of your routings especially those that are declared before this one. Commented Feb 3, 2014 at 16:15

2 Answers 2

2

Here is the problem: The URL http://localhost:64529/Articles/Archives/12 matches the other routes. It will match the Default, Contact, etc routes.

Edit Simplest solution

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

    routes.MapRoute(
        "Archives",
        "{controller}/{action}/{month}",
        new { controller = "Articles", action = "Archives" },
        new { month = @"\d+"}
    );

    //short-circuit for all URLs where the month is not numeric
    //Warning: the 404 will not be handled in <customErrors>
    //Its handled in <httpErrors>
    routes.IgnoreRoute("Articles/Archives/{month}");

    //place all other routes here

Other possibilities

1) replace {controller} with the hard-coded controller name so that /Articles won't match the route. Sample:

    routes.MapRoute(
        "Contact",
        "Appleweb/{action}/{page}",
        new { controller = "Appleweb", action = "Contact", page = UrlParameter.Optional }
    );

Only match URLs that start with /Appleweb

2) use constraint

    routes.MapRoute(
        "Archives", //Route name
        "Appleweb/{action}/{page}",
        new { controller = "Appleweb", action = "Contact", page = UrlParameter.Optional },
        new { controller = "^(?!articles$).*$" } //don't match articles
    );

or

    routes.MapRoute(
        "Archives", //Route name
        "Appleweb/{action}/{page}",
        new { controller = "Appleweb", action = "Contact", page = UrlParameter.Optional },
        new { controller = "appleweb|resources" } //only allow appleweb and resources
    );

3) make the URL of archive unique like http://XXXX/Archives/12

   routes.MapRoute(
        "Archives",
        "Archives/{month}",
        new { controller = "Articles", action = "Archives" },
        new { month = @"\d+" }
   );
Sign up to request clarification or add additional context in comments.

6 Comments

My understanding of routing was you set the parameters (second line) {controller}, /{action}/{parameter} and you fill in the blanks with what you want articles, archives, month. But what you are writing is that the first line sets it up and should be hard coded as such. So following that logic, I created this: ' routes.MapRoute( "Archives", //Route name "Articles/Archives/{month}", // URL with parameters new { controller = "Articles", action = "Archives" }, new { month = @"^\d+" } // Parameter.defaults );'
The third parameter is the default values when none is specified. Example: For this route {controller}/{action}, the following URLs resolve to the same controller actions '/Appleweb/Index', '/Appleweb' (index is the default action), '/' (appleweb is the default controller and index is the default action)
So it is working with Articles/Archives/{month} in the URL. I guess don't gut what the Controller parameter is all about then, if you are hard coding.
The hard code in the first solution is so that only URLs that start with Appleweb matches. We normally don't hard-code.
I edited my answer. I think the first solution was confusing you.
|
2

Your route has not given a default value for the month and the action method has a non nullable parameter (int month).

Change your route map to:

 routes.MapRoute(
       "Archives",
       "{controller}/{action}/{month}",
       new { controller = "Articles", action = "Archives", 
                       month = UrlParameter.Optional }
   );

Or action method to accept nullable int for the month parameter:

public ActionResult Archives(int? month) //nullable int
{
    ViewData["month"] = month;
    return View(article);
}

5 Comments

you were faster than me
The thing is, it isn't (or shouldn't) be an optional parameter. I can't determine what months' articles to display. I also don't understand why it throws an error when there is clearly a parameter that matches the criteria. Not to mention, how does the UrlParameter.Optional mesh with my reg expression for a integer?
If it isn't an optional parameter, you could assign a default value (say, 1) and make Archives(int month) (i.e. non nullable)
Same as previous, how does that code look with the regular expression code @"^d+"?
Try month = "0*[0-9][0-9]*" in the same route value dictionary.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.