0

I'm trying to follow the answer from this Stack Overflow question regarding a custom Image Link helper. The code works, as long as I remove the .MergeAttributes command. When used, this command blows up, throwing the following exception

Unable to cast object of type '<>f__AnonymousType11[System.String]' to type 'System.Collections.Generic.IDictionary2[System.String,System.String]'.

Below is the code from the helper class I'm using. The idea was to only use two string values as input parameters, and any other HTML/img tag attributes input as properties of the input objects.

    public static MvcHtmlString ImageLink(this HtmlHelper htmlHelper, string imgSrc, string url, object imgAttributes, object htmlAttributes)
    {
        UrlHelper urlHelper = ((Controller)htmlHelper.ViewContext.Controller).Url;
        var imgTag = new TagBuilder("img");
        imgTag.MergeAttribute("src", imgSrc);
        imgTag.MergeAttributes((IDictionary<string, string>)imgAttributes, true); //Exception thrown here

        var imgLink = new TagBuilder("a");
        imgLink.MergeAttribute("href", url);
        imgLink.InnerHtml = imgTag.ToString();
        imgLink.MergeAttributes((IDictionary<string, string>)htmlAttributes, true);

        return MvcHtmlString.Create(imgLink.ToString());
    }

And here is the code from the Razor/.cshtml file.

@Html.ImageLink(Url.Content("~/Content/images/Screen.PNG"), System.Configuration.ConfigurationManager.AppSettings["Periscope"], 
                               new {title="Search Periscope"} , new { target="_blank"})
Community
  • 1
  • 1
NealR
  • 10,189
  • 61
  • 159
  • 299

2 Answers2

1

You can use the AnonymousObjectToHtmlAttributes() method of HtmlHelper to cast your object. Replace the following lines

imgTag.MergeAttributes((IDictionary<string, string>)imgAttributes, true);
imgLink.MergeAttributes((IDictionary<string, string>)htmlAttributes, true);

with

imgTag.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(imgAttributes), true);
imgLink.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes), true);
0

The way you are casting is not seems valid.

use this following extension method to make it working.

public static MvcHtmlString ImageLink(this HtmlHelper htmlHelper, string imgSrc, string url, object imgAttributes, object htmlAttributes)
    {
        UrlHelper urlHelper = ((Controller)htmlHelper.ViewContext.Controller).Url;
        var imgTag = new TagBuilder("img");
        imgTag.MergeAttribute("src", imgSrc);
        var color = imgAttributes.ToDictionary<string>();
        imgTag.MergeAttributes(color, true); //No moer Exception thrown here

        var imgLink = new TagBuilder("a");
        imgLink.MergeAttribute("href", url);
        imgLink.InnerHtml = imgTag.ToString();
        imgLink.MergeAttributes(new RouteValueDictionary(htmlAttributes), true);

        return MvcHtmlString.Create(imgLink.ToString());
    }
    public static IDictionary<string, object> ToDictionary(this object source)
    {
        return source.ToDictionary<object>();
    }

    public static IDictionary<string, T> ToDictionary<T>(this object source)
    {
        if (source == null)
            ThrowExceptionWhenSourceArgumentIsNull();

        var dictionary = new Dictionary<string, T>();
        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source))
            AddPropertyToDictionary<T>(property, source, dictionary);
        return dictionary;
    }

    private static void AddPropertyToDictionary<T>(PropertyDescriptor property, object source, Dictionary<string, T> dictionary)
    {
        object value = property.GetValue(source);
        if (IsOfType<T>(value))
            dictionary.Add(property.Name, (T)value);
    }

    private static bool IsOfType<T>(object value)
    {
        return value is T;
    }

    private static void ThrowExceptionWhenSourceArgumentIsNull()
    {
        throw new ArgumentNullException("source", "Unable to convert object to a dictionary. The source object is null.");
    }
Kaushik Thanki
  • 3,334
  • 3
  • 23
  • 50