Словарь параметров содержит нулевую запись для параметра «id» ненулевого типа.

Я пытаюсь получить данные из моей базы данных с помощью параметра id в моем маршруте по умолчанию:

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

В этом ActionResult я пытаюсь отобразить пользовательский элемент управления на основе параметра идентификатора маршрута, чтобы получить соответствующие данные для запрошенной страницы.

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

Редактировать*

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

Но я продолжаю получать ошибку:

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

Может ли кто-нибудь заметить, где я ошибаюсь?


person dtsg    schedule 27.07.2012    source источник
comment
Как вы создаете ссылку в своем представлении? Как выглядит образец сгенерированного URL?   -  person nemesv    schedule 27.07.2012
comment
Так как же выглядит URL-адрес? /контроллер/инитпагенав/1 ?   -  person Steen Tøttrup    schedule 27.07.2012
comment
Я использую вспомогательный метод для создания своих ссылок, я отредактирую сообщение   -  person dtsg    schedule 27.07.2012
comment
Хорошо, хорошо, это работает, если я поставлю идентификатор страницы в конце своих ссылок, но я не хочу, чтобы идентификатор отображался для каждого URL-адреса. Есть ли способ удалить его через маршрут?   -  person dtsg    schedule 27.07.2012


Ответы (2)


Чтобы вызвать действие, в URL-адресе необходимо целое число, например: /Home/InitPageNav/1.

Либо так, либо вы меняете метод действия, чтобы разрешить целое число, допускающее значение NULL (но это не имеет смысла, если у вас нет страницы по умолчанию, которую вы можете получить, если идентификатор не был указан?).

Если вам не нужен идентификатор страницы в URL-адресе, вам нужно что-то еще для идентификации страницы, например заголовок ??

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

и действие:

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

Просто убедитесь, что вы обработали случай, когда параметр title пуст/нулевой. И, как правило, вы должны использовать помощники/расширения, уже присутствующие в структуре Mvc, для создания ваших URL-адресов.

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

или в вашем более продвинутом помощнике,

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());
 }
person Steen Tøttrup    schedule 27.07.2012
comment
Первоначально я делал что-то похожее на это, но получал страницу по имени файла, но не думал, что это отличная идея, поскольку имя файла можно легко изменить, что приведет к его поломке, с другой стороны, PK в db другое дело. - person dtsg; 27.07.2012
comment
Но если ключ — это идентификатор, то вам понадобится идентификатор в URL-адресе или придумайте что-нибудь еще! Вам нужно указать действию, какую страницу использовать, так или иначе. - person Steen Tøttrup; 27.07.2012
comment
Таким образом, действие на контроллере нуждается в каком-то аргументе, указывающем, какую страницу получить и использовать. - person Steen Tøttrup; 27.07.2012
comment
Думаю, я мог бы получить на основе Request.Url или что-то в этом роде? По крайней мере, если имя файла будет изменено, URL-адрес изменится вместе с ним, а затем просто добавьте поле URL-адреса в базу данных? - person dtsg; 27.07.2012
comment
Да, это будет параметр id, который я передаю - person dtsg; 27.07.2012
comment
Понятно! Но вы также должны понимать, что действие откуда-то нуждается в этом аргументе, так что это либо часть URL-адреса, например: /controller/action/id, либо старый способ: /controller/action?id=1 - person Steen Tøttrup; 27.07.2012
comment
Да, теперь я понимаю, немного поковырялся в PageController, который был сгенерирован автоматически, когда я связал его с контекстом БД, и он использует параметр id для своих URL-адресов для создания/редактирования/удаления страниц и т. д. думаю, я мог бы посмотреть в удаление идентификатора через маршрутизацию, но на данный момент приведенное выше решение кажется лучшей идеей. Спасибо за вашу помощь +1 - person dtsg; 27.07.2012
comment
Мне было интересно, могу ли я сохранить идентификатор на каждой странице просмотра ViewBag или создать для него ViewData["id"]? Затем установите идентификатор, переданный результату действия = одному из них? - person dtsg; 27.07.2012

Если исключение/ошибка выдается платформой ASP .NET MVC Framework, причина этого исключения заключается в том, что параметр id не передается в HTTP-запросе.

Попробуйте переопределить сигнатуру метода действия следующим образом:

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

РЕДАКТИРОВАТЬ: Если вы считаете, что более полезно изменить тип параметра id на «строку», вам просто нужно изменить подпись метода действия.

person hiddenbyte    schedule 27.07.2012
comment
Я уже пробовал это, но id всегда null. Однако я могу исправить это, поместив идентификатор в конце всех моих ссылок, что, по моему мнению, является плохим решением. - person dtsg; 27.07.2012
comment
@Duane, вы можете показать сгенерированный URL-адрес, это поможет решить эту проблему? - person hiddenbyte; 27.07.2012
comment
<li><a href="/Home/masterplan">Masterplan</a></li> Один из примеров. Как я уже сказал, это сработало бы, если бы я использовал <li><a href="/Home/masterplan/[ID HERE]">Masterplan</a></li>, но я бы предпочел URL-адреса без идентификатора в них. - person dtsg; 27.07.2012