Search code examples
c#asp.net-mvcroutesactionresult

The parameters dictionary contains a null entry for parameter 'id' of non-nullable type


I'm trying to retrieve data from my db via the id parameter in my default route:

routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );

In this ActionResult I'm trying to render a custom user control, based on the route id parameter so that I retrieve the relevant data for the page that's requested

public ActionResult InitPageNav(int id)
{
      PageModel page = PageNavHelper.GetPageByID(id);
      return PartialView("UserControls/_PageNavPartial", page);
}

Edit*

public static MvcHtmlString CreateMenuItems(this HtmlHelper helper, string action, string text)
{
     var menuItem = new TagBuilder("li");
     var link = new TagBuilder("a");

     //Get current action from route data
     var currentAction = (string)helper.ViewContext.RouteData.Values["action"];
     link.Attributes.Add("href", string.Format("/Home/{0}", action));

     if (currentAction == action)
     {
         menuItem.AddCssClass("selected");
         link.Attributes.Remove("href");
         link.Attributes.Add("href", string.Format("/Home/{0}", currentAction.ToString()));
     }

     link.SetInnerText(text);
     menuItem.InnerHtml = link.ToString();

     return MvcHtmlString.Create(menuItem.ToString());
 }

But I keep getting the error:

The parameters dictionary contains a null entry for parameter 'id' of non-nullable type

Can anyone spot where I'm going wrong?


Solution

  • To call the action, an integer is needed in the URL, like so: /Home/InitPageNav/1

    Either that or you change the action method to allow for a nullable integer (but that doesn't make sense, unless you have a default page you can retrieve if no id was given?).

    If you don't want a page id in the url, you need something else to identify the page, like the title??

    routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{title}", // URL with parameters
                new { controller = "Home", action = "Index", title = UrlParameter.Optional } // Parameter defaults
            );
    

    and the action:

    public ActionResult InitPageNav(String title)
    {
          PageModel page = PageNavHelper.GetPageByTitle(title);
          return PartialView("UserControls/_PageNavPartial", page);
    }
    

    Just make sure to handle the case where the title parameter is empty/null. And generally you should use the helpers/extensions already present in the Mvc framework for building your urls.

    @Html.ActionLink("Link text", "action", "controller", new { title = "whatever" }, null)
    

    or in your more advanced helper,

    public static MvcHtmlString CreateMenuItems(this UrlHelper url, string action, string text)
    {
         var menuItem = new TagBuilder("li");
         var link = new TagBuilder("a");
    
         //Get current action from route data
         var currentAction = (string)helper.RequestContext.RouteData.Values["action"];
         link.Attributes.Add("href", url.Action(action, "home", new { title = "whatever" }));
    
         if (currentAction == action)
         {
             menuItem.AddCssClass("selected");
         }
    
         link.SetInnerText(text);
         menuItem.InnerHtml = link.ToString();
    
         return MvcHtmlString.Create(menuItem.ToString());
     }