merge HtmlAttributes in asp.net core

Viewed 1926

I've been using Chris Pratt's MergeHtmlAttributes Html Helper Extension method for a while in my asp.net mvc 5 editor templates. I started the process of switching over an application to Asp.net core 1.1(.net framework 4.5.2). And The htmlhelperExtension isn't working for me.

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

When I copy the class over it flags the statment: using System.Web.Mvc; -Cannot resolve symbol MVC. And after removing that using statement I get the message cannot resolve symbol "HtmlHelper" in MergeHtmlAttributes(this HtmlHelper helper, ...) I have the option of adding either Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper or .HtmlHelper<Tmodel> I chose .HtmlHelper. After that it refers to the line RouteValueDictionary htmlAttributes = and says it cannot convert IDictionary<string, object> to system.web.Routing.RouteValueDictionary. And I should change the type to IDictionary<string, object> or cast to RouteValueDictionary. Either way I get the following error when trying to use MergeHtmlAttributes in one of my editor templates.

'IHtmlHelper<object>' does not contain a definition for 'MergeHtmlAttributes' and the best extension method overload 'HtmlHelperExtensions.MergeHtmlAttributes(HtmlHelper, object, object)' requires a receiver of type 'HtmlHelper'

This line is throwing the error-> var htmlAttributes = Html.MergeHtmlAttributes(ViewData, defaultHtmlAttributesObject);

Is there a way to get this to work in asp.net core or is there a different method to achieve the same results? Here's an example of one of my editor templates so you can see the MergeHtmlAttributes being used. If I can't build the template like this anymore is there a newer/better way to do it using tag helpers? I really like having the labelfor, txtboxfor, ValidationMessageFor, etc all in one html helper.

@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>

F.Y.I. while converting to asp.net core 1.1 (and .net framework 4.5.2) I ended up putting the connection string in it's app.config file which allowed EF6 to work with Asp.net core so I can keep using the EF code I had built, for whatever reason it wouldn't find the connection string in appsettings.json.

1 Answers
Related