实施使用路由系统的HtmlHelper扩展

时间:2018-09-07 10:34:11

标签: c# asp.net-mvc asp.net-mvc-5 html-helper

我正在尝试为HtmlHelper实现自己的扩展程序,该扩展程序将以类似于ActionLink的方式输出链接。

例如,我知道我可以使用TagBuilder轻松完成此操作,但是我想利用路由系统的功能来构造传出url,如this vintage article中的Scott Guthrie所述。

我的应用程序以组织为中心。一个用户可以创建一个组织,并且一个组织可以具有多个位置。主要动作发生在当前位置。我认为某个组织是我的应用程序中的租户,并且该组织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,以生成如下链接:

/Tenants/150/Dashboard

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

“ / Tenants / 150 / Locations / 300 /”部分可以看作是URL的前缀,id由ActionFilterAttribute提取并作为属性存储在BaseController类中。

如前所述,我可以使用TagBuilder轻松生成链接,但是如果以后更改路由,则必须在所有视图和控制器中更新租户操作链接方法的所有调用。

有关如何解决此问题的任何建议? 我正在使用ASP.NET MVC 5和.NET Framework 4.6.1

谢谢。


更新以回答Stephen Muecke的questions

  

到目前为止,您尝试了什么?

我实现了这样的扩展(为简单起见,我仅包括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));
}
  

您遇到什么问题?

我不知道如何处理routeValues。我的实现在某种程度上比ActionLink的更灵活的实现要低一些,尤其是因为它没有考虑routeValues。 当路由配置变得更加复杂时,我该如何处理?

  

您希望扩展方法能够做到这一点吗?   内置的ActionLink()或RouteLink()不会吗?

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

1 个答案:

答案 0 :(得分:1)

已经有一个RouteLink()扩展方法可用于此目的。您将链接文本和路径定义的名称以及参数的对象(或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