В контроллере MVC5 как создать IDictionary или routeValueDictionary для htmlAttributes или routeValues ​​HtmlHelper? - PullRequest
0 голосов
/ 19 февраля 2020

MVC5

Конечная цель - создать ссылки представления в контроллере, поскольку они меняются в зависимости от лога программы c.

Следующая ссылка компилируется и запускается:

Dim myLink = HtmlHelper.GenerateLink(Request.RequestContext, RouteTable.Routes, "edit", "Default", "Edit", "Role", Nothing, Nothing)

Строка выше генерирует: <a href=""/Role/Edit"">edit</a>. Затем это отображается в представлении с использованием html.raw и приводит к ссылке: http://localhost:53908/Role/Edit

Ссылка, показанная выше, перемещается правильно, но не будет работать с методом действия, потому что мне нужно передать параметр ID поэтому я попытался изменить последний параметр в помощнике следующим образом:

Dim myLink = HtmlHelper.GenerateLink(Request.RequestContext, RouteTable.Routes, "edit", "Default", "Edit", "Role", Nothing, New With {.ID = "somedata"})

Но строка выше возвращает предупреждение о синтаксисе, и код не может быть запущен:

Runtime errors might occur when converting '<anonymous type: ID As String>' to 'IDictionary(Of String, Object)'

Итак затем я попытался создать IDictionary, как показано ниже, для передачи в помощник:

Dim temp As IDictionary(Of String, String)
temp.Add("ID", "somedata")
Dim myLink = HtmlHelper.GenerateLink(Request.RequestContext, RouteTable.Routes, "edit", "Default", "Edit", "Role", Nothing, temp)

Код выше удовлетворяет HtmlHelper, но строка temp.Add не работает, потому что:

temp is used before it has been assigned a value.

Во время выполнения возникает исключение нулевой ссылки. Я не особо знаком с IDictionary и не мог понять, что делать дальше.

Итак, у меня есть ряд вопросов:

  1. Есть ли способ создать IDictionary, запрашиваемый помощником "на лету", с вызовом помощника?
  2. Должен ли я использовать метод HtmlHelper.GenerateLink по-другому?
  3. Как создать IDictionary?

, добавленный после исходного сообщения:

Первоначальный вопрос касался создания на месте IDictionary для использования HtmlHelpers в контроллере, чтобы создание ссылок могло быть выполнено в коде, а не в представлении. Общая цель состоит в том, чтобы позволить коду контроллера выполнять необходимые логические операции c и вычислять ссылки вместо того, чтобы делать это в представлении.

Первоначальный вопрос касался htmlAttributes случайно, потому что в данном конкретном случае реальная потребность должен был создать routeValues. Но ответ, приведенный ниже, фактически служит для информирования о том, как сделать то и другое.

Ключом к успеху было использование правильных ключевых слов. В случае создания либо New RouteValueDictionary или New IDictionary необходимо использовать Новый словарь (Of String, Object), что означает ключевое слово Object, а ключевое слово From необходимо для настройки на месте определения записи. В MVC5 синтаксис New Dictionary (Of String, String) рассматривается как анонимный тип и не может быть преобразован в IDictionary, на месте или иным образом.

Окончательный код, используемый в Controller для установить эквивалентный ActionLink в представлении, основанном на ответе ниже:

Dim editLink = HtmlHelper.GenerateLink(Request.RequestContext,
    RouteTable.Routes,
    "Edit",      'the link text
    "Default",   'a route name, can found in RouteConfig.vb
    "Edit",      'the target ActionResult method
    "Role",      'the target Controller
    New RouteValueDictionary(New Dictionary(Of String, Object) From {"ID", role.Id}, {"selectedDomain", selectedDomain}}),
    Nothing)

В приведенном выше случае второе значение маршрута было добавлено в routeValueDictionary в соответствии с требованиями метода ActionResult.

Если htmlAttributes также требуются, они могут быть добавлены вместо заключительного Nothing показа выше, как указано в ответе ниже.

1 Ответ

1 голос
/ 19 февраля 2020

Параметр типа IDictionary(Of String, Object). Это просто интерфейс, поэтому вам нужно создать объект типа, который реализует этот интерфейс. Очевидный выбор - Dictionary(Of String, Object), например

Dim temp As IDictionary(Of String, Object) = New Dictionary(Of String, Object)
temp.Add("ID", "somedata")
Dim myLink = HtmlHelper.GenerateLink(Request.RequestContext, RouteTable.Routes, "edit", "Default", "Edit", "Role", Nothing, temp)

Я не могу вспомнить, когда анонимные типы начали поддерживаться в таком сценарии ios, но, похоже, это было позже, чем MVC 5. Если вы Если вы хотите использовать анонимные типы, вам придется написать собственный метод, который принимает анонимный тип, использует Reflection для извлечения данных из него, создает словарь и затем вызывает существующий метод. Вы можете сделать это следующим образом:

Public Module HtmlHelperExtender

    Public Function GenerateLink(requestContext As RequestContext,
                                 routeCollection As RouteCollection,
                                 linkText As String,
                                 routeName As String,
                                 actionName As String,
                                 controllerName As String,
                                 routeValues As RouteValueDictionary,
                                 htmlAttributes As Object) As String
        'Create a dictionary from the properties of the anonymously typed object.
        Dim attributesType = htmlAttributes.GetType()
        Dim properties = attributesType.GetProperties()
        Dim htmlAttributesDictionary = properties.ToDictionary(Function(p) p.Name, Function(p) p.GetValue(htmlAttributes))

        Return HtmlHelper.GenerateLink(requestContext,
                                       routeCollection,
                                       linkText,
                                       routeName,
                                       actionName,
                                       controllerName,
                                       routeValues,
                                       htmlAttributesDictionary)
    End Function

End Module

Затем вы можете вызвать этот метод так же, как вы изначально пытались:

Dim myLink = HtmlHelperExtender.GenerateLink(Request.RequestContext,
                                             RouteTable.Routes,
                                             "edit",
                                             "Default",
                                             "Edit",
                                             "Role",
                                             Nothing,
                                             New With {.ID = "somedata"})

Другой вариант, который мне только что пришёл в голову, - это придерживаться словарь, но создайте и заполните его на месте, что возможно с помощью ключевого слова From:

Dim myLink = HtmlHelper.GenerateLink(Request.RequestContext,
                                     RouteTable.Routes,
                                     "edit",
                                     "Default",
                                     "Edit",
                                     "Role",
                                     Nothing,
                                     New Dictionary(Of String, Object) From {{"ID", "somedata"}})
...