Search code examples
asp.net-mvchtml-helperactionlinkurlhelperhtml.actionlink

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


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


Solution

  • 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);