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

27,086

Solution 1

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());
 }

Solution 2

If the exception/error is thrown by the ASP .NET MVC Framework, then the reason of this exception is that 'id' parameter is not being passed on the HTTP request.

Try to redefine the action method signature to the following:

    public ActionResult InitPageNav(int? id) //id is now a nullable int type
    {
          if(!id.HasValue) //id parameter is set ?
          {
                //return some default partial view or something 
          }

          PageModel page = PageNavHelper.GetPageByID(id);
          return PartialView("UserControls/_PageNavPartial", page);
    }

EDIT: If you think that is more useful to change the id parameter type to 'string', then you just have to change the action method signature.

Share:
27,086
dtsg
Author by

dtsg

Updated on June 21, 2020

Comments

  • dtsg
    dtsg almost 4 years

    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?

  • dtsg
    dtsg almost 12 years
    I've already tried this but id is always null. However i can fix this by putting the ID at the end of all of my links which IMO is a poor solution
  • dtsg
    dtsg almost 12 years
    I was originally doing something similar to this but getting the page by the filename but didn't think it was a great idea since the filename could easily be changed which would cause it to break, the PK in the db on the other hand is a different matter.
  • Steen Tøttrup
    Steen Tøttrup almost 12 years
    But if the key is the ID, then you'll need the ID in the URL, or think of something else! You need to tell the action which page to use, one way or the other.
  • hiddenbyte
    hiddenbyte almost 12 years
    @Duane can you show the generated URL, it would help solve this problem ?
  • dtsg
    dtsg almost 12 years
    <li><a href="/Home/masterplan">Masterplan</a></li> Would be one example. Like i said, it would work if i used <li><a href="/Home/masterplan/[ID HERE]">Masterplan</a></li> but i would prefer urls without the ID in them
  • Steen Tøttrup
    Steen Tøttrup almost 12 years
    So the action on the controller needs some argument telling it which page to get and use.
  • dtsg
    dtsg almost 12 years
    I guess i could fetch based on the Request.Url or something? At least if the filename is changed the url will change with it and then just add a url field to the db?
  • dtsg
    dtsg almost 12 years
    Yes, that would be the id parameter im passing in
  • Steen Tøttrup
    Steen Tøttrup almost 12 years
    Got it! But you also need to understand that the action needs that argument from somewhere, so it's either part of the url like so: /controller/action/id or like the old way of doing things: /controller/action?id=1
  • dtsg
    dtsg almost 12 years
    Yeah i understand now, had a little poke around in the PageController that was generated automagically when I linked it to the db context and it uses the id parameter for it's urls for the create/edit/delete pages etc... guess i could look into removing the id via routing but for now the above solution seems like the best idea. Thanks for your help +1
  • dtsg
    dtsg almost 12 years
    I was wondering, could i store the id in each view pages ViewBag or create a ViewData["id"] for it? Then set the id passed to the action result = to one of those?