Search code examples
asp.net-mvchtml-helper

How can I convert anonymous object HTML attributes to a Dictionary<string, object>


I'm providing an extra overload to RadioButtonFor and want to add a Key Value pair to the HTML Attributes that are passed in.

As an example I am passing in something like:

new { id = "someID" }

When i the use the HtmlHelper.AnonymousObjectToHtmlAttributes method as seems to be the suggestions I'm finding), its resulting in a dictionary with 4 items with Keys of "Comparer", "Count", "Keys", "Values". I then try to use Reflection to iterate over the values in both "Keys" and "Values", but cannot get that to work either.

Essentially all I want to do is to be able to cast the htmlAttributes to an IDictionary , add a item and then pass it on to a regular RadioButtonFor method.

Edit: Heres what Im actually trying to do. Provide an overload called isDisabled to be able to set the disabled state of the radio button as this cant be easily done directly using HTML attributes because disabled = false stillr esults in disabled being rendered to tag and disables the radio.

public static MvcHtmlString RadioButtonFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object value, bool isDisabled, object htmlAttributes)
    {
        var linkAttributes = System.Web.Mvc.HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
        Dictionary<string, object> htmlAttributesDictionary = new Dictionary<string, object>();
        foreach (var a in linkAttributes)
        {
            if (a.Key.ToLower() != "disabled")
            {
                htmlAttributesDictionary.Add(a.Key, a.Value);
            }
        }

        if (isDisabled)
        {
            htmlAttributesDictionary.Add("disabled", "disabled");
        }

        return InputExtensions.RadioButtonFor<TModel, TProperty>(htmlHelper, expression, value, htmlAttributesDictionary);
    }

Solution

  • Looks like you might be applying the AnonymousObjectToHtmlAttributes either twice or to the wrong item.

    Without more of your code, it's hard to tell

    var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(new { id = "someID" });
    attributes.Count = 1
    attributes.Keys.First() = id
    

    compared with

    var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(new { id = "someID" }));
    attributes.Count = 3
    attributes.Keys.Join = Count,Keys,Values
    

    When writing your overload, make sure your parameter is: object htmlAttributes for the new { } part with an overload with the IDictionary, eg:

    Public static MvcHtmlString MyRadioButtonFor(..., object htmlAttributes)
    {
        return MyRadioButtonFor(...., HtmlHelper.AnonymousObjectToHtmlAttrbites(htmlAttributes);
    }
    
    public static MvcHtmlString MyRadioButtonFor(..., IDictionary<string, object> htmlAttributes)
    {
        htmlAttributes.Add("item", item);
        return RadioButtonFor(..., htmlAttributes);
    }
    

    (just to be clear, never use My... - it's just for illustration)