添加到htmlAttributes以获取自定义ActionLink帮助程序扩展

wys*_*wyg 8 .net c# asp.net asp.net-mvc-4

我正在尝试创建一个Html.ActionLink(...)HtmlHelper的简单自定义版本

我想为传入的htmlAttributes匿名对象附加一组额外的属性.

public static MvcHtmlString NoFollowActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
{
    var customAttributes = new RouteValueDictionary(htmlAttributes) {{"rel", "nofollow"}};
    var link = htmlHelper.ActionLink(linkText, actionName, controllerName, routeValues, customAttributes);
    return link;
}
Run Code Online (Sandbox Code Playgroud)

所以在我看来我会这样:

@Html.NoFollowActionLink("Link Text", "MyAction", "MyController")
Run Code Online (Sandbox Code Playgroud)

我希望能够呈现如下链接:

<a href="/MyController/MyAction" rel="nofollow">Link Text</a>
Run Code Online (Sandbox Code Playgroud)

但相反,我得到:

<a href="/MyController/MyAction" values="System.Collections.Generic.Dictionary`2+ValueCollection[System.String,System.Object]" keys="System.Collections.Generic.Dictionary`2+KeyCollection[System.String,System.Object]" count="1">Link Text</a>
Run Code Online (Sandbox Code Playgroud)

我已经尝试了将匿名类型转换为RouteValueDictionary的各种方法,添加到它然后将其传递到根ActionLink(...)方法或转换为Dictionary,或使用HtmlHelper.AnonymousObjectToHtmlAttributes并执行相同但似乎没有工作.

sla*_*wek 11

您得到的结果是由此源代码引起的:

public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
{
    return ActionLink(htmlHelper, linkText, actionName, controllerName, TypeHelper.ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的那样HtmlHelper.AnonymousObjectToHtmlAttributes被称为内部.这就是为什么你得到valueskeys当你传递它的RouteValueDictionary对象.

只有两种方法匹配您的参数列表:

public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
Run Code Online (Sandbox Code Playgroud)

第二个重载对你的参数没有任何作用,只是传递它们.您需要修改代码以调用其他重载:

public static MvcHtmlString NoFollowActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues = null, object htmlAttributes = null)
{
    var routeValuesDict = new RouteValueDictionary(routeValues);

    var customAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
    if (!customAttributes.ContainsKey("rel"))
        customAttributes.Add("rel", "nofollow");

    return htmlHelper.ActionLink(linkText, actionName, controllerName, routeValuesDict, customAttributes);
}
Run Code Online (Sandbox Code Playgroud)

当你通过routeValuesRouteValueDictionary其他超载拾取(RouteValueDictionary正在实施IDictionary<string, object>所以它的精细),返回的链接是正确的.

如果该rel属性已经存在于htmlAttributesobject中,则会抛出异常:

System.ArgumentException: An item with the same key has already been added.
Run Code Online (Sandbox Code Playgroud)