Метод HTML.ActionLink


249

Скажімо, у мене клас

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

На сторінці, яка не знаходиться в папці "Елемент", де 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 - Danny Pflughoeft

@Danny Спасибі, шукав його в 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 до поточної дії
Chris S

32
@Chris S - Я знаю, що це стара публікація, але причина? Длина = 8 полягає в тому, що вам потрібно мати , nullпараметр ПІСЛЯ свого new { ... }... тому що якщо ви перевіряєте перевантаження цього методу, це думає, що ваші параметри - це htmlArguments ... не аргументи маршруту. Щоб скористатися правильним методом, вам потрібно використовувати метод, який має routeArguments, htmlArguments.. так що просто переведіть нуль для останнього htmlArgument. Перший фрагмент коду у цій відповіді. Я оновив цю публікацію, щоб ви могли легко побачити її (тобто вона не прокручується).
Pure.Krome

7
Хтось пробував це з MVC 3? Схоже, що рядки ControllerName та ActionMethod у наведеному вище прикладі перевернуті. Хтось ще це бачив?
Стів Дуйтсман

8
У MVC3 властивість id не знайдено ... замість цього слід використовувати наступне:@Html.ActionLink("Text","Action","Controller", new { item.ID }, null)
Gavin Coates

30

Я хотів додати відповідь Джозефу Кінгрі . Він запропонував рішення, але спочатку я не міг змусити його працювати, і я отримав результат так само, як Адіп Гупта. І тоді я зрозумів, що маршрут повинен існувати в першу чергу і параметри повинні точно відповідати маршруту. Тож у мене був ідентифікатор, а потім текстовий параметр для мого маршруту, який теж потрібно було включити.

Html.ActionLink(article.Title, "Login", "Item", new { id = article.ArticleID, title = article.Title }, null)

4
Це саме те, що мені було потрібно - я забув додати остаточний нульовий аргумент. Дякую.
Ян Окслі

1
Дякуємо, що також показали відображення назви параметра параметра маршруту (наприклад, новий {id = ..., bar = ...}.
William Rose,

17

Можливо, ви захочете подивитися на RouteLink()метод. Це дозволяє вам задавати все (крім тексту посилання та назви маршруту) через словник.


4
Було б чудово побачити приклад того, як це вирішує проблему; на сторінці MSDN є багато перевантажень, і знати, на що звернути увагу, може бути заплутано
Саймон Мартін

14

Я думаю, що Джозеф перевернув контролер і дії. Спочатку йде дія, потім контролер. Це дещо дивно, але те, як виглядає підпис

Просто для уточнення речей, це версія, яка працює (адаптація прикладу Йосипа):

Html.ActionLink(article.Title, 
    "Login",  // <-- ActionMethod
    "Item",   // <-- Controller Name
    new { id = article.ArticleID }, // <-- Route arguments.
    null  // <-- htmlArguments .. which are none
    )

11

як що до цього

<%=Html.ActionLink("Get Involved", 
                   "Show", 
                   "Home", 
                   new 
                       { 
                           id = "GetInvolved" 
                       }, 
                   new { 
                           @class = "menuitem", 
                           id = "menu_getinvolved" 
                       }
                   )%>

10
Html.ActionLink(article.Title, "Login/" + article.ArticleID, 'Item") 

Це дійсно повинно було бути позначене як відповідь, оскільки воно робить саме те, що шукала людина, яка шукала питання ... однак зауважу, що помічена відповідь дуже детально розібралася для користувача при правильному налаштуванні маршрутів у різних версіях МВЦ.
Інді-Джонс

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
Я здивований, що більше не використовують такий підхід. Здається, справді небезпечно використовувати рядкові літерали у своїх представленнях для представлення контролера / дії.
Джоннатан Суллінгер


Спробував це, не вийшло. Зрештою, дайте мені порожній рядок - я вважаю, що у мене є параметри у своїх функціях.
Варто7

Чи можете ви опублікувати github чи інше місце з цим кодом, щоб я міг подивитися і зрозуміти, чому це не працює для вас?
Серж Саган

2
Гарне вживання слова fancypants. Ми цього не бачимо достатньо.
gdbj

7

Використовуйте названі параметри для читабельності та уникнення плутанини.

@Html.ActionLink(
            linkText: "Click Here",
            actionName: "Action",
            controllerName: "Home",
            routeValues: new { Identity = 2577 },
            htmlAttributes: null)

1

З MVC5 я зробив це так, і це 100% робочий код ....

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

Ви, хлопці, можете отримати уявлення з цього ...


0

Цей тип використання:

@ Html.ActionLink ("Головна сторінка", "Індекс", "Головна")

Головна сторінка: Назва тексту Індекс: Дія Перегляд Головна: 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>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.