ActionLink扩展方法MVC5中的htmlAttributes

Pur*_*rph 2 asp.net-mvc html-helper razor

我正在使用扩展方法在菜单上的活动链接上维护css类.

但是我遇到了htmlAttributes和对象值导致错误的问题.

我在Razor页面中有以下内容,但我不明白我是如何解析htmlAttributes的.

@Html.MenuLink("Summary", "Summary", "Graphs", null, new { @class = "dropdown-toggle caret", data_target = "#", data_toggle = "dropdown" })
Run Code Online (Sandbox Code Playgroud)

从查看HtmlHelper开始,该方法应该具有IDictionary<object, string>htmlAttributes的类型.新{ @class = "dropdown-toggle caret", data_target = "#", data_toggle = "dropdown" }语法对于字典来说并不常见,所以这是正确的吗?

显然我做错了,因为它返回了以下错误:

Argument 6: cannot convert from '<anonymous type: string class, string data_target, string data_toggle>' to 'System.Collections.Generic.IDictionary<object, string>'
Run Code Online (Sandbox Code Playgroud)

扩展方法我试图在下面工作:

public static MvcHtmlString MenuLink(this HtmlHelper htmlHelper, string text, string action, string controller, RouteValueDictionary routeValues, IDictionary<object, string> htmlAttributes)
        {
            var routeData = htmlHelper.ViewContext.RouteData.Values;

            var currentController = routeData["controller"];
            var currentAction = routeData["action"];

            if (string.Equals(action, currentAction as string, StringComparison.OrdinalIgnoreCase) &&
                string.Equals(controller, currentController as string, StringComparison.OrdinalIgnoreCase))
            {
                return htmlHelper.ActionLink(text, action, controller, null, new { @class = "currentMenu" });
            }

            return htmlHelper.ActionLink(text, action, controller);
        }
Run Code Online (Sandbox Code Playgroud)

小智 6

从更改参数IDictionary<object, string> htmlAttributesobject htmlAttributes,因为你传递的属性的对象.

然后,您可以使用转换对象

var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
Run Code Online (Sandbox Code Playgroud)

但是,在扩展方法中没有使用属性的地方.您的所有生class = "currentMenu"成都取决于当前的控制器和操作名称.如果您打算添加属性加上类名(取决于条件),则可以使用

attributes.Add("class", "currentMenu");
Run Code Online (Sandbox Code Playgroud)

您可以使用完整的方法来定义路由值和html属性,并有条件地包含"currentMenu"类名

public static MvcHtmlString MenuLink(this HtmlHelper htmlHelper, string text, string action, string controller, object routeValues, object htmlAttributes)
{
    var routeData = htmlHelper.ViewContext.RouteData.Values;
    string currentController = (string)routeData["controller"];
    string currentAction = (string)routeData["action"];
    if (string.Equals(action, currentAction, StringComparison.OrdinalIgnoreCase) && string.Equals(controller, currentController, StringComparison.OrdinalIgnoreCase))
    {
        if (htmlAttributes == null)
        {
            return htmlHelper.ActionLink(text, action, controller, routeValues, new { @class = "currentMenu" });
        }
        else
        {
            // convert object to RouteValueDictionary
            var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
            if (attributes.ContainsKey("class"))
            {
                // append the class name
                attributes["class"] = string.Format("{0} currentMenu", attributes["class"]);
            }
            else
            {
                // add the class name
                attributes.Add("class", "currentMenu");
            }
            return htmlHelper.ActionLink(text, action, controller, new RouteValueDictionary(routeValues), attributes);
        }
    }
    return htmlHelper.ActionLink(text, action, controller, routeValues, htmlAttributes);
}
Run Code Online (Sandbox Code Playgroud)

旁注:您还应该考虑包含其他重载以接受RouteValueDictionary routeValuesIDictionary<String, Object>) htmlAttributes根据内置ActionLink()方法,您可以检查源代码以查看各种重载如何通过其他重载.