Método HTML.ActionLink

249

Digamos que tengo una clase

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

En una página que no se encuentra en la carpeta Elemento, donde ItemControllerreside, quiero crear un enlace al Loginmétodo. Entonces, ¿qué Html.ActionLinkmétodo debo usar y qué parámetros debo pasar?

Específicamente, estoy buscando el reemplazo del método

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

que se retiró en la reciente encarnación ASP.NET MVC.

Graviton
fuente
17
Documentación, para cualquiera que la busque: msdn.microsoft.com/en-us/library/…
BlueRaja - Danny Pflughoeft
@Danny Gracias, lo estaba buscando en Google cuando terminé aquí.
Rei Miyasaka

Respuestas:

491

Creo que lo que quieres es esto:

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

Utiliza el siguiente método de firma de ActionLink:

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

ASP.NET MVC2

se han cambiado dos argumentos

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

Utiliza el siguiente método de firma de ActionLink:

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

ASP.NET MVC3 +

los argumentos están en el mismo orden que MVC2, sin embargo, el valor de id ya no es necesario:

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

Esto evita la codificación rígida de cualquier lógica de enrutamiento en el enlace.

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

Esto le dará la siguiente salida html, suponiendo:

  1. article.Title = "Title"
  2. article.ArticleID = 5
  3. todavía tienes la siguiente ruta definida

. .

routes.MapRoute(
    "Default",     // Route name
    "{controller}/{action}/{id}",                           // URL with parameters
    new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
);
Joseph Kingry
fuente
77
Pero, ¿no da esto una URL como / Item / Login? Id = 5?
Adhip Gupta
21
Lo que es extraño es que si te pierdes el último parámetro, se agrega a mí. Longitud = 8 a la acción actual
Chris S
32
@ Chris S - Sé que esta es una publicación antigua, pero la razón de la? Longitud = 8 es porque necesita tener un , nullparámetro DESPUÉS de su new { ... }... porque si verifica las sobrecargas de ese método, está pensando que sus parámetros son html ... no enrutar argumentos. Para usar el método correcto , debe usar el método que tiene routeArguments, htmlArguments... así que simplemente pase nulo para eso último htmlArgument. El primer fragmento de código en esta respuesta lo tiene. He actualizado esta publicación para que pueda verla fácilmente (es decir, no se desplaza).
Pure.Krome
77
¿Alguien ha intentado esto con MVC 3? Parece que las líneas ControllerName y ActionMethod en la muestra anterior están invertidas. ¿Alguien más ha visto eso?
Steve Duitsman el
8
En MVC3 no se encuentra la propiedad id ... se debe usar lo siguiente:@Html.ActionLink("Text","Action","Controller", new { item.ID }, null)
Gavin Coates
30

Quería agregar a la respuesta de Joseph Kingry . Él proporcionó la solución, pero al principio tampoco pude lograr que funcionara y obtuve un resultado como Adhip Gupta. Y luego me di cuenta de que la ruta tiene que existir en primer lugar y que los parámetros deben coincidir exactamente con la ruta. Entonces tenía una identificación y luego un parámetro de texto para mi ruta que también necesitaba ser incluido.

Html.ActionLink(article.Title, "Login", "Item", new { id = article.ArticleID, title = article.Title }, null)
Jeff Widmer
fuente
44
Esto es justo lo que necesitaba: me había olvidado de agregar el argumento nulo final . Gracias.
Ian Oxley
1
Gracias por mostrar también la asignación del nombre del parámetro de ruta (por ejemplo, nuevo {id = ..., bar = ...}.
William Rose
17

Es posible que desee ver el RouteLink()método, que le permite especificar todo (excepto el texto del enlace y el nombre de la ruta) a través de un diccionario.

Hackeado
fuente
44
Sería genial ver un ejemplo de cómo eso resuelve el problema; la página de MSDN tiene muchas sobrecargas y saber qué buscar podría ser confuso
Simon Martin
14

Creo que Joseph volteó el controlador y la acción. Primero viene la acción, luego el controlador. Esto es algo extraño, pero la apariencia de la firma.

Solo para aclarar las cosas, esta es la versión que funciona (adaptación del ejemplo de Joseph):

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

que hay de esto

<%=Html.ActionLink("Get Involved", 
                   "Show", 
                   "Home", 
                   new 
                       { 
                           id = "GetInvolved" 
                       }, 
                   new { 
                           @class = "menuitem", 
                           id = "menu_getinvolved" 
                       }
                   )%>
Hasan
fuente
10
Html.ActionLink(article.Title, "Login/" + article.ArticleID, 'Item") 
Adhip Gupta
fuente
Esto realmente debería haber sido marcado como la respuesta ya que hace exactamente lo que la persona que hizo la pregunta estaba buscando ... sin embargo, notaré que la respuesta marcada entró en un gran detalle para el usuario al configurar correctamente las rutas en varias versiones de MVC.
Indy-Jones
9

Si quieres usar todos los pantalones elegantes, así es como puedes extenderlo para poder hacer esto:

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

Deberá poner esto en el System.Web.Mvcespacio de nombres:

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

Esto incluye dos anulaciones para Route Valuesy HTML Attributes, además, todas sus vistas tendrían que agregar: @using YourProject.Controllerso puede agregarlo a suweb.config <pages><namespaces>

Serj Sagan
fuente
1
Me sorprende más no utilizar este enfoque. Parece realmente peligroso usar literales de cadena por todas partes en sus vistas para representar un controlador / acción.
Johnathon Sullinger
He
Intenté esto, no funcionó. Me dio una cadena en blanco al final, supongo porque tengo parámetros en mis funciones.
Digno7
¿Puedes publicar un github u otro lugar con este código para que pueda echar un vistazo y ver por qué no te funciona?
Serj Sagan
2
Buen uso de la palabra fancypants. No vemos eso lo suficiente.
gdbj
7

Utilice parámetros con nombre para facilitar la lectura y evitar confusiones.

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

Con MVC5 lo he hecho así y es 100% código de trabajo ...

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

Ustedes pueden tener una idea de esto ...

Sohail Malik
fuente
0

Este tipo de uso:

@ Html.ActionLink ("Página principal", "Índice", "Inicio")

Página principal: Nombre del texto Índice: Vista de acción Inicio: HomeController

Uso base 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
fuente