Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rendering html with tag helpers into string variable

I'm currently localising a ASP.NET Core Razor Pages application. I use the "old" way of localising, with a compiled ResX file, and in my cshtml I use

<h3>@Global.Access</h3>

"Global" being the resource file, "Access" being the key to the resource string.

I prefer to use this approach over an injected localizer:

@localiser["Access"]

Because this allows me to identify missing strings in the resource file during compile time.

Now, I have a resource string with a placeholder:

StringWithPlaceholder: "You can visit {0} for more information"

When I use following code in the cshtml everything works:

@{
    var linkvariable = "<a href=\"url-to-my-page\">blabla</a>";
 }

@string.Format(Global.StringWithPlaceHolder, linkvariable);

But if I replace the href by the asp-page tag helper, the tag helper is not rendered.

@{
    linkvariable = "<a asp-page=\"my-page\">blabla</a>";
 }

How could I resolve this?

like image 792
StevenQ Avatar asked Oct 28 '25 13:10

StevenQ


1 Answers

To get the result of a tag helper into a string variable, you can do this:

@{
    Func<string, Microsoft.AspNetCore.Html.IHtmlContent> Hyperlink = @<a asp-area="Area" asp-controller="Controller">@item</a>;
    string value = Html.ToHtmlString(Hyperlink("Link text"));
}

The argument to that Func - a Templated Razor delegate - is a Dynamic object, so you could easily have a generic hyperlink template and pass it an object with Controller, Action, Area etc.

The ToHtmlString() extension method looks like this:

public static string ToHtmlString(this IHtmlHelper source, IHtmlContent htmlContent)
{
    var sb = new StringBuilder();

    using (TextWriter tw = new StringWriter(sb))
    {
        var encoder = (HtmlEncoder?)source.ViewContext.HttpContext.RequestServices.GetService(typeof(HtmlEncoder)) ?? HtmlEncoder.Default;
            htmlContent.WriteTo(tw, encoder);
    }

    return sb.ToString();
}

From there, it's easy to use String.Format to render your localised hyperlink.

A more succinct alternative which avoids the variable is this:

@Html.Raw(Html.StringFormat("Click {0} to proceed", @<a asp-area="Area" asp-controller="Controller">here</a>))

The StringFormat extension method:

public static string StringFormat(this IHtmlHelper source, string format, params Func<dynamic, IHtmlContent>[] formatArgs)
{
    var stringFormatArgs = new List<string>();

    foreach (var item in formatArgs)
    {
        var sb = new StringBuilder();
        using (TextWriter tw = new StringWriter(sb))
        {
            var encoder = (HtmlEncoder?)source.ViewContext.HttpContext.RequestServices.GetService(typeof(HtmlEncoder)) ?? HtmlEncoder.Default;
            item("").WriteTo(tw, encoder);

            stringFormatArgs.Add(sb.ToString());
        }
    }

    return string.Format(format, args: stringFormatArgs.ToArray());
}
like image 87
Nugsson Avatar answered Oct 30 '25 09:10

Nugsson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!