Using Html.ActionLink and Url.Action(...) from inside Controller

21,657

Not sure I actually understood your question clearly, but, let me try.

To create a HtmlHelper extension like you described, try something like:

using System;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace Something {
    public static class PageLinkHelper
    {
        public static string PageLink(
            this HtmlHelper helper,
            string linkText, string actionName,
            string controllerName, object routeValues,
            object htmlAttributes)
        {
            return helper.ActionLink(
                linkText, actionName, controllerName,
                routeValues, htmlAttributes);
        }
    }
}

As for your question on getting a URL from a class, depends on what kind of class you'll implement it. For example, if you want to get the current controller and action from a HtmlHelper extension, you can use:

string currentControllerName = (string)helper.ViewContext
    .RouteData.Values["controller"];
string currentActionName = (string)helper.ViewContext
    .RouteData.Values["action"];

If you want to get it from a controller, you can use properties/methods from the base class (Controller) to build the URL. For example:

var url = new UrlHelper(this.ControllerContext.RequestContext);
url.Action(an_action_name, route_values);
Share:
21,657
Petrus Theron
Author by

Petrus Theron

I solve business problems with software. Over the past 15 years I have risked significant personal wealth to work on multiple startups. My unique experience allows me to understand a human desire, design a product that satisfies that need - then build and deploy it single-handedly from concept to scale. Sometimes I write about it. I primarily work in Clojure/ClojureScript, but I have built small to medium-sized products (sub-million LOC) using Python, C#, C/C++, Java, Pascal and JavaScript. Products I built: 2007-2011 Rhythm Music Store: online music store / record label that that sold 80k MP3s online. MyNames: an API to register .CO.ZA domains and provision nameservers. Stack: Python, AngularJS. Krit.com: a mobile customer feedback tool that used geolocation and SMS to bridge the gap between customers and retail managers 2007-2016: iFix (now weFix) Repair Management System tracks 500k repairs and millions in revenues at 36+ branches. Acquired by weFix. ...several others. There are more. Happy to delve into technical details. Good with people and recruiting.

Updated on July 05, 2022

Comments

  • Petrus Theron
    Petrus Theron almost 2 years

    I want to write an HtmlHelper to render an ActionLink with pre-set values, eg.

    <%=Html.PageLink("Page 1", "page-slug");%>
    

    where PageLink is a function that calls ActionLink with a known Action and Controller, eg. "Index" and "Page".

    Since HtmlHelper and UrlHelper do not exist inside a Controller or class, how do I get the relative URL to an action from inside a class?

    Update: Given the additional three years of accrued experience I have now, here's my advice: just use Html.ActionLink("My Link", new { controller = "Page", slug = "page-slug" }) or better yet,

    <a href="@Url.Action("ViewPage",
                         new {
                               controller = "Page",
                               slug = "my-page-slug" })">My Link</a>
    

    Your extension method may be cute and short, but it adds another untested point-of-failure and a new learning requirement for hires without adding any real value whatsoever. Think of it as designing a complex system. Why add another moving part, unless it adds reliability (no), readability (little, once you read more docs), speed (none) or concurrency (none).

  • Petrus Theron
    Petrus Theron about 14 years
    Excellent answer. I tried that without a wrapping it in a static class and it wouldn't register helper.ActionLink(...). Thanks.
  • Petrus Theron
    Petrus Theron about 14 years
    Ah, and I wasn't importing System.Web.Mvc; My bad.