我正在尝试为HtmlHelper实现我自己的扩展,它将以与ActionLink类似的方式输出链接。
我知道我可以用TagBuilder轻松地做到这一点,但是我想利用路由系统的能力构建出口网址,如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
}
);
对于路线“租户”,控制器始终是组织。该部分应用程序负责整个组织的管理操作。此处的上下文包含租户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()来实现这一目标?
已有一个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