我正在尝试创建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;
}

所以在我看来,我会这样:
@Html.NoFollowActionLink("Link Text", "MyAction", "MyController")

我希望呈现出这样的链接:
<a href="/MyController/MyAction" rel="nofollow">Link Text</a>

但是我得到了:
<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>

我尝试了多种方法将匿名类型转换为RouteValueDictionary,然后将其添加到根ActionLink(...)方法中,或者转换为Dictionary,或者使用HtmlHelper.AnonymousObjectToHtmlAttributes进行相同的操作,但似乎没有做任何事情工作。

最佳答案

您得到的结果是由以下来源code引起的:

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

如您所见,HtmlHelper.AnonymousObjectToHtmlAttributes在内部被调用。这就是为什么将values对象传递给keysRouteValueDictionary的原因。

只有两种与您的参数列表匹配的方法:
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)

第二次重载不会对您的参数做任何事情,只需传递它们即可。
您需要修改代码以调用其他重载:
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);
}

当您将routeValues传递为RouteValueDictionary时,会选择其他重载(RouteValueDictionary正在实现IDictionary<string, object>,这样就可以了),并且返回的链接是正确的。

如果rel对象中已经存在htmlAttributes属性,则将引发异常:
System.ArgumentException: An item with the same key has already been added.

关于c# - 为自定义ActionLink帮助程序扩展添加到htmlAttributes,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21188570/

10-13 01:23