Search code examples
c#htmlasp.net-coreasp.net-core-tag-helpersasp-append-version

How to implement asp-append-version="true" to background-image property?


I am trying to implement the HTMLTagHelper asp-append-version="true" to my images. The problem is as regards the DOM distribution, I am not assigning the attribute to an <img> tag but to to a <div> containing the image with the background-url property.

Moreover, the div is generated before all the DOM is loaded and I don't know if there would be a different approach of doing it.

One is obvious, change the div to an img tag, but I don't want it as my design has to remain the same.

My javascript has hitherto been like this:

cardHTML += '<div asp-append-version="true" class="card littleCard" style="background-image: url(/Content/Img/Especialistas/LittleCard/' + especialista.idEspecialista + '.jpg' + ')' + '" >';
cardHTML += '</div>';

The asp-append-version="true" won't work on the div tag. Any ideas on how to find an approach of dealing with this ?

Thanks


Solution

  • You can create a custom TagHelper to target all elements having an inline style attribute. The following example I've tried looks working fine but if you want something more standard (similar to ImageTagHelper, ...), you can try looking into the base class UrlResolutionTagHelper. I'm not so sure why it need to be more complicated in there in which basically you need to resolve the URL before actually processing it more. I've tried with a simple IFileVersionProvider and it works for relative paths as well (of course the resolved path should be at the current server's web root).

    The following simple example works fine for attribute values of HtmlString (which is almost the usual case, some custom rendering may inject IHtmlContent that is not of HtmlString, for such complicated cases, you can refer to the source code for UrlResolutionTagHelper, even copying almost the exact relevant code there is fine):

    //target only elements having an inline style attribute
    [HtmlTargetElement(Attributes = "style")]
    public class InlineStyleBackgroundElementTagHelper : TagHelper
    {
        readonly IFileVersionProvider _fileVersionProvider;        
        const string BACKGROUND_URL_PATTERN = "(background(?:-image)?\\s*:[^;]*url)(\\([^)]+\\))";
        public InlineStyleBackgroundElementTagHelper(IFileVersionProvider fileVersionProvider)
        {
            _fileVersionProvider = fileVersionProvider;
        }
        //bind the asp-append-version property
        [HtmlAttributeName("asp-append-version")]
        public bool AppendsVersion { get; set; }
        //inject ViewContext from the current request
        [HtmlAttributeNotBound]
        [ViewContext]
        public ViewContext ViewContext { get; set; }
    
        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            if (AppendsVersion)
            {
                if (output.Attributes.TryGetAttribute("style", out var styleAttr))
                {
                    //the value here should be an HtmlString, so this basically 
                    //gets the raw plain string of the style attribute's value
                    var inlineStyle = styleAttr.Value.ToString();
                    var basePath = ViewContext.HttpContext.Request.PathBase;
                    inlineStyle = Regex.Replace(inlineStyle, BACKGROUND_URL_PATTERN, m =>
                    {
                        //extract the background url contained in the inline style
                        var backgroundUrl = m.Groups[2].Value.Trim('(', ')', ' ');
                        //append the version
                        var versionedUrl = _fileVersionProvider.AddFileVersionToPath(basePath, backgroundUrl);
    
                        //format back the inline style with the versioned url
                        return $"{m.Groups[1]}({versionedUrl})";
                    }, RegexOptions.Compiled | RegexOptions.IgnoreCase);
                    output.Attributes.SetAttribute("style", inlineStyle);
                }
            }
        }
    }
    

    Usage: just like how you use the asp-append-version on other built-in tag helps. (like in your example).