实现一个使用路由系统的 HtmlHelper 扩展

Implement a HtmlHelper extension that uses the routing system

我正在尝试为 HtmlHelper 实现我自己的扩展,它将以类似于 ActionLink 的方式输出 link。

我知道我可以使用 TagBuilder 轻松做到这一点,但我想利用路由系统的能力来构造传出 urls,如 Scott Guthrie 在 this vintage article 中所述.

我的申请以组织为中心。一个用户可以创建一个组织,一个组织可以有多个位置。主要动作发生在当前位置。我将组织视为我的应用程序中的租户,并且组织 ID 通过 url.

发送

上面的路由配置如下:

routes.MapRoute(
    name: "Tenant",
    url: "Tenants/{tenantId}/{action}",
    defaults: new
    {
        controller = "Organizations",
        action = "Dashboard",
        id = UrlParameter.Optional
    }
);

routes.MapRoute(
    name: "TenantLocation",
    url: "Tenants/{tenantId}/Locations/{locationId}/{controller}/{action}/{id}",
    defaults: new
    {
        controller = "Dashboard",
        action = "Index",
        id = UrlParameter.Optional
    }
);

对于路线 "Tenant",控制器始终是组织。应用程序的这一部分负责处理有关整个组织的管理操作。此处的上下文包含一个租户 ID。

对于路线 "TenantLocation",上下文在位置内部移动,因此上下文包含租户 ID 和位置 ID。

现在,我想为 HtmlHelper 创建两个名为 TenantActionLink 和 TenantLocationActionLink 的扩展方法,以生成如下 links:

/Tenants/150/Dashboard

/Tenants/150/Locations/300/Team/Edit/1000

“/Tenants/150/Locations/300/”部分可以被视为要添加到 URL 的前缀,ID 由 ActionFilterAttribute 提取并作为属性存储在 BaseController class.

正如我提到的,我可以使用 TagBuilder 轻松生成 links,但如果我稍后更改路由,我必须更新租户操作 links 方法的所有调用所有视图和控制器。

关于如何解决这个问题有什么建议吗? 我正在使用 ASP.NET MVC 5 和 .NET Framework 4.6.1

谢谢。


更新以回答 Stephen Muecke 的

What have you tried so far?

我实现了这样的扩展(为简单起见,我只包含了 TenantLocationActionLink 的代码,另一个是类似的):

public static MvcHtmlString TenantLocationActionLink(this HtmlHelper helper,
    int tenandId,
    int locationId,
    string linkText,
    string actionName,
    string controllerName,
    object htmlAttributes = null)
{
    var url = $"/Tenants/{tenandId}/Locations/{locationId}/{controllerName}/{actionName}";

    var tagBuilder = new TagBuilder("a");
    tagBuilder.InnerHtml = linkText;
    tagBuilder.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    tagBuilder.MergeAttribute("href", url);

    return new MvcHtmlString(tagBuilder.ToString(TagRenderMode.Normal));
}

and what problems are you having?

我不知道如何处理 routeValues。我的实现在某种程度上是更灵活的 ActionLink 实现的降级,特别是因为它没有考虑 routeValues。 当我的路由配置变得更复杂时,我将如何处理?

And what are you expecting your extension method to do that the inbuilt ActionLink() or RouteLink() don't?

如上所述添加租户和位置 ID。我如何使用 ActionLink() 或 RouteLink() 来实现这一点?

已经有一个 RouteLink() 扩展方法可以用于此目的。您将 link 文本和路由定义的名称以及参数的对象(或 RouteValueDictionary)传递给它,它将生成正确的 href 属性。在您的情况下,对于 Tenant 路线

@Html.RouteLink("...", "Tenant", new { tenantId = 150, action = "Dashboard" })

生成 .../Tenants/150/Dashboard

TenantLocation

@Html.RouteLink("...", "TenantLocation", new { tenantId = 150, locationId = 300, controller = "Team", action = "Edit", id = 1000 })

生成../Tenants/150/Locations/300/Team/Edit/1000