Posts
1150
Comments
891
Trackbacks
1
Fixing ImageLink code that Asp.NET Core broke

This code, prior to Asp.NET Core, worked to create an image link:

public static HtmlString ImageLink(this HtmlHelper htmlHelper, string imgSrc, string alt, string actionName, string controllerName, object routeValues, object htmlAttributes, object imgHtmlAttributes)
       {
           UrlHelper urlHelper = ((Controller)htmlHelper.ViewContext.Controller).Url;
           TagBuilder imgTag = new TagBuilder("img");
           imgTag.MergeAttribute("src", imgSrc);
           imgTag.MergeAttribute("alt", alt);
           imgTag.MergeAttributes((new RouteValueDictionary(imgHtmlAttributes)), true);
           string url = urlHelper.Action(actionName, controllerName, routeValues);

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

           return new HtmlString(imglink.ToString());
       }

 

It’s usage was:

@Html.ImageLink(Url.Content("~/content/images/product/4/" + Model.Image), Model.Name, “Detail”, “Product”, new { id = Model.ID }, null, null)

Now, given that Asp.NET Core is a huge re-write, one should expect the APIs to change.  What one might not expect is that:

imgTag.ToString()

Would return the fully qualified class name, as opposed to, you know, the string representation of the content of the TagBuilder.

Why did they choose to do something this stupid (and it was a choice, this is explicitly by design)?  Who knows?  After a long day dealing with deliberately obstinate people, I don’t care.

This fixes it:

public static HtmlString ImageLink(this IHtmlHelper htmlHelper, string imgSrc, string alt, string actionName, string controllerName, object routeValues, object htmlAttributes, object imgHtmlAttributes)
        {
            ActionContext ac = new ActionContext(htmlHelper.ViewContext.HttpContext, htmlHelper.ViewContext.RouteData, htmlHelper.ViewContext.ActionDescriptor);
            UrlHelper urlHelper = new UrlHelper(ac);
            TagBuilder imgTag = new TagBuilder("img");
            imgTag.TagRenderMode = TagRenderMode.SelfClosing;
            imgTag.MergeAttribute("src", imgSrc);
            imgTag.MergeAttribute("alt", alt);
            imgTag.MergeAttributes((new RouteValueDictionary(imgHtmlAttributes)), true);
            string url = urlHelper.Action(actionName, controllerName, routeValues);

            TagBuilder imglink = new TagBuilder("a");
            imglink.MergeAttribute("href", url);
            imglink.InnerHtml.Append(GetString(imgTag));
            imglink.MergeAttributes((IDictionary<string, string>)htmlAttributes, true);

            var imgLinkDecoded = System.Web.HttpUtility.HtmlDecode(GetString(imglink));

            return result = new HtmlString(imgLinkDecoded);        }

        public static string GetString(IHtmlContent content)
        {
            var writer = new System.IO.StringWriter();
            content.WriteTo(writer, HtmlEncoder.Default);
            return writer.ToString();
        }

Note the brilliant code that requires you to decode a string that was HtmlEncoded (since you cannot WriteTo() something that doesn’t HtmlEncode it).

Brilliant.

posted on Wednesday, July 27, 2016 9:41 PM Print
Comments
No comments posted yet.

Post Comment

Title *
Name *
Email
Url
Comment *  
Please add 6 and 7 and type the answer here: