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.