12

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

1
  • +1 for the update. I would also point future searchers to this question on calling Url.Action from inside the controller - stackoverflow.com/questions/2031995/… Commented Sep 29, 2015 at 21:49

1 Answer 1

20

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);
Sign up to request clarification or add additional context in comments.

2 Comments

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.