【问题标题】:merge HtmlAttributes in asp.net core在 asp.net 核心中合并 HtmlAttributes
【发布时间】:2017-10-12 11:48:59
【问题描述】:

我在我的 asp.net mvc 5 编辑器模板中使用 Chris Pratt 的 MergeHtmlAttributes Html Helper Extension 方法有一段时间了。我开始了将应用程序切换到 Asp.net core 1.1(.net framework 4.5.2)的过程。并且 htmlhelperExtension 对我不起作用。

public static partial class HtmlHelperExtensions
{
    //https://cpratt.co/html-editorfor-and-htmlattributes/
    public static IDictionary<string, object> MergeHtmlAttributes(this HtmlHelper helper, object htmlAttributesObject, object defaultHtmlAttributesObject)
    {
        var concatKeys = new string[] { "class" };

        var htmlAttributesDict = htmlAttributesObject as IDictionary<string, object>;
        var defaultHtmlAttributesDict = defaultHtmlAttributesObject as IDictionary<string, object>;

        RouteValueDictionary htmlAttributes = (htmlAttributesDict != null)
            ? new RouteValueDictionary(htmlAttributesDict)
            : HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributesObject);

        RouteValueDictionary defaultHtmlAttributes = (defaultHtmlAttributesDict != null)
            ? new RouteValueDictionary(defaultHtmlAttributesDict)
            : HtmlHelper.AnonymousObjectToHtmlAttributes(defaultHtmlAttributesObject);

        foreach (var item in htmlAttributes)
        {
            if (concatKeys.Contains(item.Key))
            {
                defaultHtmlAttributes[item.Key] = (defaultHtmlAttributes[item.Key] != null)
                    ? string.Format("{0} {1}", defaultHtmlAttributes[item.Key], item.Value)
                    : item.Value;
            }
            else
            {
                if(item.Key?.ToString() == "divClass")
                {
                    continue;
                }
                defaultHtmlAttributes[item.Key] = item.Value;
            }
        }

        return defaultHtmlAttributes;
    }
}

当我将类复制到它上面时,会标记声明: using System.Web.Mvc; - 无法解析符号 MVC。 在删除该 using 语句后,我收到消息 cannot resolve symbol "HtmlHelper" in MergeHtmlAttributes(this HtmlHelper helper, ...) 我可以选择添加 Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.HtmlHelper&lt;Tmodel&gt; 我选择了.HtmlHelper。 之后,它引用 RouteValueDictionary htmlAttributes = 行并表示它无法将IDictionary&lt;string, object&gt; 转换为system.web.Routing.RouteValueDictionary。我应该将类型更改为IDictionary&lt;string, object&gt; 或转换为RouteValueDictionary。无论哪种方式,在我的一个编辑器模板中尝试使用 MergeHtmlAttributes 时都会出现以下错误。

'IHtmlHelper&lt;object&gt;' 不包含“MergeHtmlAttributes”的定义,并且最佳扩展方法重载“HtmlHelperExtensions.MergeHtmlAttributes(HtmlHelper, object, object)”需要“HtmlHelper”类型的接收器

这一行抛出错误-> var htmlAttributes = Html.MergeHtmlAttributes(ViewData, defaultHtmlAttributesObject);

有没有办法让它在 asp.net 核心中工作,或者有没有不同的方法来达到相同的结果?这是我的编辑器模板之一的示例,因此您可以看到正在使用的 MergeHtmlAttributes。如果我不能再像这样构建模板,是否有更新/更好的方法来使用标签助手?我真的很喜欢 labelfor、txtboxfor、ValidationMessageFor 等都在一个 html 助手中。

@model int?

@{
    var defaultHtmlAttributesObject = new { @class = "form-control" };
    var htmlAttributes = Html.MergeHtmlAttributes(ViewData, defaultHtmlAttributesObject);

    object divClass;
    ViewData.TryGetValue("divClass", out divClass);
    if (divClass == null) { divClass = ""; }

    IDictionary<string, object> validationAttributes = Html.GetUnobtrusiveValidationAttributes("");
    Html.ViewContext.FormContext.RenderedField(ViewData.TemplateInfo.GetFullHtmlFieldName(null), false);
}

<div class="form-group @divClass @(Html.ValidationErrorFor(x => x, " has-error"))">
    @Html.LabelFor(x => x, new { @class = "control-label" })
    @if (validationAttributes.ContainsKey("data-val-required"))
    {<span class="text-danger">*</span>}
    @Html.TextBoxFor(x => x, htmlAttributes)
    @Html.ValidationMessageFor(model => model, "", new { @class = "text-danger" })
</div>

仅供参考在转换为 asp.net core 1.1(和 .net framework 4.5.2)时,我最终将连接字符串放入它的 app.config 文件中,该文件允许 EF6 与 Asp.net core 一起工作,因此我可以继续使用我拥有的 EF 代码构建,无论出于何种原因,它都不会在 appsettings.json 中找到连接字符串。

【问题讨论】:

  • 我认为函数定义应该是: public static IDictionary MergeHtmlAttributes(this IHtmlHelper helper, object htmlAttributesObject, object defaultHtmlAttributesObject) 一旦我这样做了,我就会得到“无法解析符号 AnonymousObjectToHtmlAttributes” IHtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributesObject);我在这里找到了 AnonymousObjectToHtmlAttributes 是如何在 github 上实现的:github.com/aspnet/Mvc/blob/dev/src/…

标签: asp.net-core-1.1


【解决方案1】:

最初我没有意识到微软现在使用的是 IHtmlHelper 而不是 HtmlHelper

一旦我修改了代码以反映该更改并在 github 上找到 Microsoft 的 mvc 存储库,我就能够找到他们对 AnonymousObjectToHtmlAttributes 的实现,这一切都落到了一起。

下面的代码对我有用,但我可能需要对我还没有想到的边缘情况进行一些更改。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Routing;

using Microsoft.AspNetCore.Mvc.Rendering;

public static class HtmlHelperExtensions
{
    //http://cpratt.co/html-editorfor-and-htmlattributes/
    /// <summary>
    /// This is used with the EditorTemplates to copy the page element's htmlAttributes over to the editorTemplates 
    /// while still being able to specify values to always use (like @class = "form-control") in the editorTemplates.
    /// </summary>
    public static IDictionary<string, object> MergeHtmlAttributes(this IHtmlHelper helper, object htmlAttributesObject, object defaultHtmlAttributesObject)
    {
        var concatKeys = new[] { "class" };

        var htmlAttributesDict = htmlAttributesObject as IDictionary<string, object>;
        var defaultHtmlAttributesDict = defaultHtmlAttributesObject as IDictionary<string, object>;

        RouteValueDictionary htmlAttributes = new RouteValueDictionary(htmlAttributesDict != null
            ? htmlAttributesDict
            : AnonymousObjectToHtmlAttributes(htmlAttributesObject));

        RouteValueDictionary defaultHtmlAttributes = new RouteValueDictionary(defaultHtmlAttributesDict != null
            ? defaultHtmlAttributesDict
            : AnonymousObjectToHtmlAttributes(defaultHtmlAttributesObject));

        foreach (var item in htmlAttributes)
        {
            if (concatKeys.Contains(item.Key))
            {
                defaultHtmlAttributes[item.Key] = defaultHtmlAttributes[item.Key] != null
                    ? string.Format("{0} {1}", defaultHtmlAttributes[item.Key], item.Value)
                    : item.Value;
            }
            else
            {
                if(item.Key == "divClass")
                {
                    continue;
                }
                defaultHtmlAttributes[item.Key] = item.Value;
            }
        }

        return defaultHtmlAttributes;
    }

    private static IDictionary<string, object> AnonymousObjectToHtmlAttributes(object htmlAttributes)
    {
        var dictionary = htmlAttributes as IDictionary<string, object>;
        if (dictionary != null)
        {
            return new Dictionary<string, object>(dictionary, StringComparer.OrdinalIgnoreCase);
        }

        dictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);

        if (htmlAttributes != null)
        {
            var stringAttributes = htmlAttributes.ToString();
            stringAttributes = stringAttributes.Replace("{", "").Replace("}", "");
            string[] attributesArray = stringAttributes.Split(new[] { ','}, StringSplitOptions.RemoveEmptyEntries);

            foreach (var helper in attributesArray)
            {
                string[] attribKeyValue = helper.Trim().Split(' ');
                dictionary[attribKeyValue.First()] = attribKeyValue.Last();
            }
        }

        return dictionary;
    }
}

【讨论】:

  • 不应该是=而不是空格吗? string[] attribKeyValue = helper.Trim().Split(' ');
  • 这里:var htmlAttributes = Html.MergeHtmlAttributes(ViewData, DefaultHtmlAttributesObject);上面以@model int 开头的代码块?是我如何使用它的一个更好的例子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-23
  • 1970-01-01
  • 1970-01-01
  • 2021-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多