HTML.ActionLink метод

249

Допустим, у меня есть класс

public class ItemController:Controller
{
    public ActionResult Login(int id)
    {
        return View("Hi", id);
    }
}

На странице, которая не находится в папке Item, где ItemControllerнаходится, я хочу создать ссылку на Loginметод. Так какой Html.ActionLinkметод я должен использовать и какие параметры я должен передать?

В частности, я ищу замену метода

Html.ActionLink(article.Title,
    new { controller = "Articles", action = "Details",
          id = article.ArticleID })

это было удалено в недавнем воплощении ASP.NET MVC.

Гравитон
источник
17
Документация, для тех, кто ищет ее: msdn.microsoft.com/en-us/library/…
BlueRaja - Дэнни Пфлугхофт
@ Дэнни Спасибо, искал это в Google, когда я оказался здесь.
Рей Миясака

Ответы:

491

Я думаю, что вы хотите это:

ASP.NET MVC1

Html.ActionLink(article.Title, 
                "Login",  // <-- Controller Name.
                "Item",   // <-- ActionMethod
                new { id = article.ArticleID }, // <-- Route arguments.
                null  // <-- htmlArguments .. which are none. You need this value
                      //     otherwise you call the WRONG method ...
                      //     (refer to comments, below).
                )

При этом используется следующий метод подписи ActionLink:

public static string ActionLink(this HtmlHelper htmlHelper, 
                                string linkText,
                                string controllerName,
                                string actionName,
                                object values, 
                                object htmlAttributes)

ASP.NET MVC2

два аргумента были переключены вокруг

Html.ActionLink(article.Title, 
                "Item",   // <-- ActionMethod
                "Login",  // <-- Controller Name.
                new { id = article.ArticleID }, // <-- Route arguments.
                null  // <-- htmlArguments .. which are none. You need this value
                      //     otherwise you call the WRONG method ...
                      //     (refer to comments, below).
                )

При этом используется следующий метод подписи ActionLink:

public static string ActionLink(this HtmlHelper htmlHelper, 
                                string linkText,
                                string actionName,
                                string controllerName,
                                object values, 
                                object htmlAttributes)

ASP.NET MVC3 +

аргументы находятся в том же порядке, что и MVC2, однако значение id больше не требуется:

Html.ActionLink(article.Title, 
                "Item",   // <-- ActionMethod
                "Login",  // <-- Controller Name.
                new { article.ArticleID }, // <-- Route arguments.
                null  // <-- htmlArguments .. which are none. You need this value
                      //     otherwise you call the WRONG method ...
                      //     (refer to comments, below).
                )

Это позволяет избежать жесткого кодирования любой логики маршрутизации в ссылку.

 <a href="/Item/Login/5">Title</a> 

Это даст вам следующий вывод html, если:

  1. article.Title = "Title"
  2. article.ArticleID = 5
  3. у вас еще есть следующий маршрут

, ,

routes.MapRoute(
    "Default",     // Route name
    "{controller}/{action}/{id}",                           // URL with parameters
    new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
);
Джозеф Кингри
источник
7
Но разве это не выдает URL-адрес типа / Item / Login? Id = 5?
Adhip Gupta
21
Что странного, если вы пропустите последний параметр, он добавляется для меня? Длина = 8 к текущему действию
Крис S
32
@Chris S - я знаю, что это старый пост, но причина? Length = 8 в том, что вам нужно иметь , nullпараметр ПОСЛЕ вашего new { ... }... потому что, если вы проверяете перегрузки этого метода, он думает, что ваши параметры являются htmlArguments ... не аргументы маршрута. Чтобы использовать правильный метод, вам нужно использовать метод, который имеет routeArguments, htmlArguments.. так что просто передайте значение null для этого последнего htmlArgument. Первый фрагмент кода в этом ответе имеет это. Я обновил этот пост, чтобы вы могли легко это увидеть (т.е. он не прокручивается).
Pure.Krome
7
Кто-нибудь пробовал это с MVC 3? Кажется, что строки ControllerName и ActionMethod в приведенном выше примере перевернуты. Кто-нибудь еще видел это?
Стив Дуитсман
8
В MVC3 свойство id не найдено ... вместо этого следует использовать следующее:@Html.ActionLink("Text","Action","Controller", new { item.ID }, null)
Гэвин Коутс
30

Я хотел добавить к ответу Джозефа Кингри . Он предоставил решение, но сначала я тоже не смог заставить его работать и получил результат, как Adhip Gupta. И тогда я понял, что маршрут должен существовать в первую очередь и параметры должны точно соответствовать маршруту. Так что у меня был идентификатор, а затем текстовый параметр для моего маршрута, который тоже нужно было включить.

Html.ActionLink(article.Title, "Login", "Item", new { id = article.ArticleID, title = article.Title }, null)
Джефф Видмер
источник
4
Это как раз то, что мне было нужно - я забыл добавить последний нулевой аргумент. Спасибо.
Ян Оксли
1
Спасибо за показ сопоставления и из имени параметра маршрута (например, new {id = ..., bar = ...}.
Уильям Роуз,
17

Возможно, вы захотите взглянуть на метод. RouteLink()Он позволяет вам указать все (кроме текста ссылки и названия маршрута) через словарь.

Haacked
источник
4
Было бы здорово увидеть пример того, как это решает проблему; страница MSDN имеет много перегрузок, и знание того, что искать, может сбивать с толку
Саймон Мартин
14

Я думаю, что Джозеф переключил контроллер и действие. Сначала идет действие, затем контроллер. Это несколько странно, но как выглядит подпись.

Просто чтобы прояснить ситуацию, это версия, которая работает (адаптация примера Джозефа):

Html.ActionLink(article.Title, 
    "Login",  // <-- ActionMethod
    "Item",   // <-- Controller Name
    new { id = article.ArticleID }, // <-- Route arguments.
    null  // <-- htmlArguments .. which are none
    )
agez
источник
11

как насчет этого

<%=Html.ActionLink("Get Involved", 
                   "Show", 
                   "Home", 
                   new 
                       { 
                           id = "GetInvolved" 
                       }, 
                   new { 
                           @class = "menuitem", 
                           id = "menu_getinvolved" 
                       }
                   )%>
Hasan
источник
10
Html.ActionLink(article.Title, "Login/" + article.ArticleID, 'Item") 
Адхип Гупта
источник
Это действительно должно быть помечено как ответ, так как оно делает именно то, что искал человек, задававший вопрос ... однако я отмечу, что помеченный ответ очень подробно рассказал пользователю о правильной настройке маршрутов в различных версиях. MVC.
Инди-Джонс
9

Если вы хотите использовать все модные штаны, вот как вы можете расширить это, чтобы иметь возможность сделать это:

@(Html.ActionLink<ArticlesController>(x => x.Details(), article.Title, new { id = article.ArticleID }))

Вам нужно будет поместить это в System.Web.Mvcпространство имен:

public static class MyProjectExtensions
{
    public static MvcHtmlString ActionLink<TController>(this HtmlHelper htmlHelper, Expression<Action<TController>> expression, string linkText)
    {
        var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection);

        var link = new TagBuilder("a");

        string actionName = ExpressionHelper.GetExpressionText(expression);
        string controllerName = typeof(TController).Name.Replace("Controller", "");

        link.MergeAttribute("href", urlHelper.Action(actionName, controllerName));
        link.SetInnerText(linkText);

        return new MvcHtmlString(link.ToString());
    }

    public static MvcHtmlString ActionLink<TController, TAction>(this HtmlHelper htmlHelper, Expression<Action<TController, TAction>> expression, string linkText, object routeValues)
    {
        var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection);

        var link = new TagBuilder("a");

        string actionName = ExpressionHelper.GetExpressionText(expression);
        string controllerName = typeof(TController).Name.Replace("Controller", "");

        link.MergeAttribute("href", urlHelper.Action(actionName, controllerName, routeValues));
        link.SetInnerText(linkText);

        return new MvcHtmlString(link.ToString());
    }

    public static MvcHtmlString ActionLink<TController>(this HtmlHelper htmlHelper, Expression<Action<TController>> expression, string linkText, object routeValues, object htmlAttributes) where TController : Controller
    {
        var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection);

        var attributes = AnonymousObjectToKeyValue(htmlAttributes);

        var link = new TagBuilder("a");

        string actionName = ExpressionHelper.GetExpressionText(expression);
        string controllerName = typeof(TController).Name.Replace("Controller", "");

        link.MergeAttribute("href", urlHelper.Action(actionName, controllerName, routeValues));
        link.MergeAttributes(attributes, true);
        link.SetInnerText(linkText);

        return new MvcHtmlString(link.ToString());
    }

    private static Dictionary<string, object> AnonymousObjectToKeyValue(object anonymousObject)
    {
        var dictionary = new Dictionary<string, object>();

        if (anonymousObject == null) return dictionary;

        foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(anonymousObject))
        {
            dictionary.Add(propertyDescriptor.Name, propertyDescriptor.GetValue(anonymousObject));
        }

        return dictionary;
    }
}

Это включает в себя два переопределения для Route Valuesи HTML Attributes, кроме того, все ваши представления нужно будет добавить: @using YourProject.Controllersили вы можете добавить его в свойweb.config <pages><namespaces>

Серж Саган
источник
1
Я удивлен больше, не используйте этот подход. Кажется, действительно опасно использовать строковые литералы повсюду в ваших представлениях для представления контроллера / действия.
Джонатон Саллингер
Я искал это всю свою жизнь
Worthy7
Пробовал это, не сработало. Дали мне пустую строку в конце - я предполагаю, потому что у меня есть параметры в моих функциях.
Достойно7
Можете ли вы опубликовать github или другое место с этим кодом, чтобы я мог посмотреть и понять, почему он не работает для вас?
Серж Саган
2
Хорошее использование слова FancyPants. Мы не видим этого достаточно.
gdbj
7

Используйте именованные параметры для удобства чтения и избежания путаницы.

@Html.ActionLink(
            linkText: "Click Here",
            actionName: "Action",
            controllerName: "Home",
            routeValues: new { Identity = 2577 },
            htmlAttributes: null)
guneysus
источник
1

С MVC5 я сделал это так, и это 100% рабочий код ....

@Html.ActionLink(department.Name, "Index", "Employee", new { 
                            departmentId = department.DepartmentID }, null)

Вы, ребята, можете получить представление об этом ...

Сохаил Малик
источник
0

Этот тип использования:

@ Html.ActionLink ( "MainPage", "Index", "Начало")

MainPage: Имя текста Указатель: Action View Home: HomeController

Базовое использование ActionLink

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>_Layout</title>
    <link href="@Url.Content("~/Content/bootsrap.min.css")" rel="stylesheet" type="text/css" />
</head>
<body>
    <div class="container">
        <div class="col-md-12">
            <button class="btn btn-default" type="submit">@Html.ActionLink("AnaSayfa","Index","Home")</button>
            <button class="btn btn-default" type="submit">@Html.ActionLink("Hakkımızda", "Hakkimizda", "Home")</button>
            <button class="btn btn-default" type="submit">@Html.ActionLink("Iletişim", "Iletisim", "Home")</button>
        </div> 
        @RenderBody()
        <div class="col-md-12" style="height:200px;background-image:url(/img/footer.jpg)">

        </div>
    </div>
</body>
</html>

Сердин Челик
источник