Método HTML.ActionLink

249

Digamos que eu tenho uma aula

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

Em uma página que não está localizada na pasta Item, onde ItemControllerreside, desejo criar um link para o Loginmétodo. Então, qual Html.ActionLinkmétodo devo usar e quais parâmetros devo passar?

Especificamente, estou procurando a substituição do método

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

que foi aposentado na recente encarnação do ASP.NET MVC.

Graviton
fonte
17
Documentação, para quem procura: msdn.microsoft.com/en-us/library/…
BlueRaja - Danny Pflughoeft 4/10/10
@ Danny Obrigado, estava procurando no Google quando acabei aqui.
Rei Miyasaka

Respostas:

491

Eu acho que o que você quer é isso:

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

Isso usa o seguinte método ActionLink signature:

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

ASP.NET MVC2

dois argumentos foram trocados

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

Isso usa o seguinte método ActionLink signature:

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

ASP.NET MVC3 +

argumentos estão na mesma ordem que o MVC2, no entanto, o valor do ID não é mais necessário:

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

Isso evita a codificação embutida de qualquer lógica de roteamento no link.

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

Isso fornecerá a seguinte saída html, assumindo:

  1. article.Title = "Title"
  2. article.ArticleID = 5
  3. você ainda tem a seguinte rota definida

. .

routes.MapRoute(
    "Default",     // Route name
    "{controller}/{action}/{id}",                           // URL with parameters
    new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
);
Joseph Kingry
fonte
7
Mas, isso não fornece uma URL como / Item / Login? Id = 5?
Adhip Gupta 14/10/08
21
O que é estranho é que se você perder o último parâmetro, ele acrescenta para mim Comprimento = 8 para a ação atual?
Chris S
32
@ Chris S - Eu sei que este é um post antigo, mas a razão para o comprimento = 8 é porque você precisa ter um , nullparâmetro APÓS o seu new { ... }... porque se você verificar as sobrecargas desse método, está pensando que seus parâmetros são htmlArguments ... não rotear argumentos. Para usar o método correto , você precisa usar o método que possui routeArguments, htmlArguments.. então basta passar nulo para esse último htmlArgument. O primeiro trecho de código nesta resposta possui. Atualizei esta postagem para que você possa ver com facilidade (ou seja, ela não rola).
precisa saber é o seguinte
7
Alguém já tentou isso com o MVC 3? Parece que as linhas ControllerName e ActionMethod na amostra acima são invertidas. Alguém mais viu isso?
Steve Duitsman 9/09/10
8
Em MVC3 a propriedade id não é encontrado ... o seguinte deve ser usado em vez disso:@Html.ActionLink("Text","Action","Controller", new { item.ID }, null)
Gavin Coates
30

Eu queria acrescentar à resposta de Joseph Kingry . Ele forneceu a solução, mas no começo eu também não consegui fazê-la funcionar e obtive um resultado exatamente como Adhip Gupta. E então percebi que a rota precisa existir em primeiro lugar e os parâmetros precisam corresponder exatamente à rota. Então, eu tinha um ID e, em seguida, um parâmetro de texto para minha rota, que também precisava ser incluído também.

Html.ActionLink(article.Title, "Login", "Item", new { id = article.ArticleID, title = article.Title }, null)
Jeff Widmer
fonte
4
Era exatamente disso que eu precisava - eu tinha esquecido de adicionar o argumento nulo final . Obrigado.
23610 Ian Oxley
1
Obrigado por mostrando o mapeamento de nome de parâmetro rota, também (por exemplo, novo {id = ..., bar = ...}.
William Rose
17

Você pode querer olhar para o RouteLink()método. Esse permite especificar tudo (exceto o texto do link e o nome da rota) por meio de um dicionário.

Haacked
fonte
4
Seria ótimo ver um exemplo de como isso resolve o problema; na página MSDN tem muitas sobrecargas e saber o que procurar pode ser confuso
Simon Martin
14

Eu acho que Joseph inverteu o controle e a ação. Primeiro vem a ação e depois o controlador. Isso é um pouco estranho, mas a aparência da assinatura.

Apenas para esclarecer as coisas, esta é a versão que funciona (adaptação do exemplo de Joseph):

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

que tal isso

<%=Html.ActionLink("Get Involved", 
                   "Show", 
                   "Home", 
                   new 
                       { 
                           id = "GetInvolved" 
                       }, 
                   new { 
                           @class = "menuitem", 
                           id = "menu_getinvolved" 
                       }
                   )%>
Hasan
fonte
10
Html.ActionLink(article.Title, "Login/" + article.ArticleID, 'Item") 
Adhip Gupta
fonte
Isso realmente deveria ter sido marcado como a resposta, pois faz exatamente o que a pessoa que estava fazendo a pergunta estava procurando ... no entanto, observarei que a resposta marcada foi um grande detalhe para o usuário configurar corretamente rotas em várias versões do MVC.
Indianapolis-Jones
9

Se você quiser usar calças justas, veja como você pode estendê-lo para poder fazer isso:

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

Você precisará colocar isso no System.Web.Mvcespaço para nome:

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

Isso inclui duas substituições para Route Valuese HTML Attributes, também, todas as suas visualizações precisariam ser adicionadas: @using YourProject.Controllersou você pode adicioná-lo ao seuweb.config <pages><namespaces>

Serj Sagan
fonte
1
Estou surpreso que mais não use essa abordagem. Parece realmente perigoso usar literais de string em todas as suas visualizações para representar um controlador / ação.
Johnathon Sullinger
Procurado este toda a minha vida
Worthy7
Tentei isso, não funcionou. Deu-me uma string em branco no final - presumo que possuo parâmetros em minhas funções.
usar o seguinte código
Você pode postar um github ou outro local com esse código para que eu possa dar uma olhada e ver por que ele não está funcionando para você?
Serj Sagan
2
Bom uso da palavra fantasia. Não vemos isso o suficiente.
Gdbj #
7

Use parâmetros nomeados para facilitar a leitura e evitar confusões.

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

Com MVC5 eu fiz isso assim e é 100% código de trabalho ....

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

Vocês podem ter uma idéia disso ...

Sohail Malik
fonte
0

Este tipo usa:

@ Html.ActionLink ("MainPage", "Índice", "Página Inicial")

MainPage: Nome do texto Índice: Ação Exibir Home: HomeController

ActionLink de uso básico

<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
fonte