Méthode HTML.ActionLink


249

Disons que j'ai une classe

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

Sur une page qui ne se trouve pas dans le dossier Élément, où ItemController réside, je souhaite créer un lien vers la Loginméthode. Alors, quelle Html.ActionLinkméthode dois-je utiliser et quels paramètres dois-je passer?

Plus précisément, je recherche le remplacement de la méthode

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

qui a été retiré dans la récente incarnation ASP.NET MVC.


17
Documentation, pour tous ceux qui la recherchent: msdn.microsoft.com/en-us/library/…
BlueRaja - Danny Pflughoeft

@Danny Merci, je le cherchais sur Google lorsque je me suis retrouvé ici.
Rei Miyasaka

Réponses:


491

Je pense que ce que vous voulez c'est:

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).
                )

Cela utilise la méthode ActionLink signature suivante:

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

ASP.NET MVC2

deux arguments ont été inversés

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).
                )

Cela utilise la méthode ActionLink signature suivante:

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

ASP.NET MVC3 +

les arguments sont dans le même ordre que MVC2, mais la valeur id n'est plus requise:

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).
                )

Cela évite de coder en dur toute logique de routage dans la liaison.

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

Cela vous donnera la sortie html suivante, en supposant:

  1. article.Title = "Title"
  2. article.ArticleID = 5
  3. vous avez toujours l'itinéraire suivant défini

. .

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

7
Mais cela ne donne-t-il pas une URL comme / Item / Login? Id = 5?
Adhip Gupta

21
Ce qui est étrange, c'est que si vous manquez le dernier paramètre, il s'ajoute pour moi? Longueur = 8 à l'action en cours
Chris S

32
@Chris S - Je sais que c'est un ancien article, mais la raison de la? Length = 8 est parce que vous devez avoir un , nullparamètre APRÈS votre new { ... }... parce que si vous vérifiez les surcharges de cette méthode, c'est en pensant que vos paramètres sont htmlArguments ... pas acheminer les arguments. Pour utiliser la bonne méthode, vous devez utiliser la méthode qui a routeArguments, htmlArguments.. il suffit donc de passer null pour ce dernier htmlArgument. Le premier morceau de code dans cette réponse l'a. J'ai mis à jour ce message pour que vous puissiez le voir facilement (c'est-à-dire qu'il ne défile pas).
Pure.Krome

7
Quelqu'un at-il essayé cela avec MVC 3? Il semble que les lignes ControllerName et ActionMethod dans l'exemple ci-dessus soient inversées. Quelqu'un d'autre a vu ça?
Steve Duitsman

8
Dans MVC3, la propriété id est introuvable ... ce qui suit devrait être utilisé à la place:@Html.ActionLink("Text","Action","Controller", new { item.ID }, null)
Gavin Coates

30

Je voulais ajouter quelque chose à la réponse de Joseph Kingry . Il a fourni la solution, mais au début, je n'ai pas pu le faire fonctionner non plus et j'ai obtenu un résultat tout comme Adhip Gupta. Et puis j'ai réalisé que l'itinéraire doit exister en premier lieu et que les paramètres doivent correspondre exactement à l'itinéraire. J'ai donc eu un identifiant, puis un paramètre de texte pour mon itinéraire qui devait également être inclus.

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

4
C'est exactement ce dont j'avais besoin - j'avais oublié d'ajouter l' argument nul final . Merci.
Ian Oxley

1
Merci d'avoir également montré le mappage à partir du nom du paramètre de l'itinéraire (par exemple, nouveau {id = ..., bar = ...}.
William Rose

17

Vous voudrez peut-être regarder la RouteLink()méthode, celle-ci vous permet de tout spécifier (sauf le texte du lien et le nom de l'itinéraire) via un dictionnaire.


4
Ce serait formidable de voir un exemple de la façon dont cela résout le problème; la page MSDN a beaucoup de surcharges et savoir quoi chercher peut être déroutant
Simon Martin

14

Je pense que Joseph a inversé le contrôleur et l'action. Vient d'abord l'action puis le contrôleur. C'est un peu étrange, mais à quoi ressemble la signature.

Juste pour clarifier les choses, voici la version qui fonctionne (adaptation de l'exemple de Joseph):

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

11

Et ça

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

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

Cela aurait vraiment dû être marqué comme réponse car il fait exactement ce que la personne qui posait la question recherchait ... Cependant, je noterai que la réponse marquée est entrée dans les moindres détails pour l'utilisateur en configurant correctement les itinéraires dans différentes versions de MVC.
Indy-Jones

9

Si vous voulez aller à tous les pantalons fantaisie, voici comment vous pouvez l'étendre pour pouvoir le faire:

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

Vous devrez mettre ceci dans l' System.Web.Mvcespace de noms:

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

Cela inclut deux remplacements pour Route Valueset HTML Attributes, également, toutes vos vues devraient être ajoutées: @using YourProject.Controllersou vous pouvez l'ajouter à votreweb.config <pages><namespaces>


1
Je suis plus surpris de ne pas utiliser cette approche. Il semble vraiment dangereux d'utiliser des chaînes de caractères partout dans vos vues pour représenter un contrôleur / une action.
Johnathon Sullinger du

J'ai cherché ça toute ma vie
Worthy7

J'ai essayé ça, ça n'a pas marché. M'a donné une chaîne vide à la fin - je suppose que j'ai des paramètres dans mes fonctions.
Worthy7

Pouvez-vous publier un github ou un autre endroit avec ce code afin que je puisse jeter un œil et voir pourquoi cela ne fonctionne pas pour vous?
Serj Sagan

2
Belle utilisation du mot fancypants. Nous ne le voyons pas assez.
gdbj

7

Utilisez des paramètres nommés pour plus de lisibilité et pour éviter les confusions.

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

1

Avec MVC5, je l'ai fait comme ça et c'est 100% de code de travail ....

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

Vous pouvez vous faire une idée de ça ...


0

Ce type utilise:

@ Html.ActionLink ("MainPage", "Index", "Home")

MainPage: Nom du texte Index: Action View Accueil: HomeController

Base Use 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>

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.