在控制器中使用Html.ActionLink和Url.Action(...)

12

我想编写一个HtmlHelper来渲染带有预设值的ActionLink,例如:

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

其中PageLink是一个调用ActionLink的函数,已知Action和Controller,例如"Index"和"Page"。

由于HtmlHelperUrlHelper不存在于Controller或类中,所以我如何从类内部获取到一个操作的相对URL呢?

更新:考虑到我现在已经积累了三年的经验,这里是我的建议:只需使用Html.ActionLink("My Link", new { controller = "Page", slug = "page-slug" })或者更好的方法,

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

你的扩展方法可能很短小可爱,但它会增加另一个未经测试的故障点,并且对新员工提出了一个新的学习要求,而没有添加任何真正的价值。把它看作是设计一个复杂系统。除非它增加了可靠性(不是),可读性(有点,一旦你阅读了更多文档),速度(没有)或并发性(没有),否则为什么要添加另一个动态部分。


+1 给更新。我还会将未来的搜索者指向这个关于如何从控制器内部调用 Url.Action 的问题 - https://dev59.com/eXI-5IYBdhLWcg3wED9V - brichins
1个回答

20

我不太确定是否完全理解了你的问题,但是让我试着回答一下。

要创建一个像你描述的HtmlHelper扩展,可以尝试以下代码:

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

关于如何从一个类获取URL的问题,取决于你要实现哪种类。例如,如果你想从HtmlHelper扩展中获取当前控制器和操作的URL,可以使用以下代码:

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

如果您想从控制器中获取它,您可以使用基类(Controller)的属性/方法来构建URL。例如:

var url = new UrlHelper(this.ControllerContext.RequestContext);
url.Action(an_action_name, route_values);

1
非常好的答案。我之前尝试过不使用静态类进行包装,但是它无法注册 helper.ActionLink(...)。谢谢。 - Petrus Theron
啊,我没有导入 System.Web.Mvc; 是我的错误。 - Petrus Theron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接