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.

Graviton
la source
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
);
Joseph Kingry
la source
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)
Jeff Widmer
la source
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.

Piraté
la source
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
    )
agez
la source
11

Et ça

<%=Html.ActionLink("Get Involved", 
                   "Show", 
                   "Home", 
                   new 
                       { 
                           id = "GetInvolved" 
                       }, 
                   new { 
                           @class = "menuitem", 
                           id = "menu_getinvolved" 
                       }
                   )%>
Hasan
la source
10
Html.ActionLink(article.Title, "Login/" + article.ArticleID, 'Item") 
Adhip Gupta
la source
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>

Serj Sagan
la source
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)
guneysus
la source
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 ...

Sohail Malik
la source
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>

Serdin çelik
la source