The parameters dictionary contains a null entry fo

2019-04-12 02:13发布

问题:

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?

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


回答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.