Simone
Simone

Reputation: 1337

Generating HTML from non-MVC class

I have a method that grabs the localization of a given string and returns it. This method is called by an extension method of HtmlHelper, so that it is accessible from Razor views. However, sometimes we also use it in controllers and other non-Razor places, and that's why we have the "inner" method.

Now, for debug purposes, I'd like to wrap the returned, localized (or maybe not) string into some HTML (something like <span class="localized">Returned text</span>). However, if I write

return string.Format("<span class=\"localized\">{0}</span>", text);

then the rendered page includes the < and > characters as if they were HTML-encoded, so the output is bogus.

I can't, of course, call HtmlHelper.Raw(string s), partly because I wouldn't know how to create an HtmlHelper from outside an MVC controller, and then because it returns an IHtmlString which isn't assignable to string.

If I call HttpUtility.HtmlEncode(string s), the text is twice-encoded, and the rendered page shows &lt;span class&eq;&quot;....

What should I do to have a string that renders to HTML in the view?


EDIT

Here's the code, from a Helper static class (all extension methods work, except they behave wrong):

public static string localize(string textId)
{
    string ret = "";

    // Query to obtain the localized string, 
    //   or to obtain a fallback in case there are issues 
    //   (missing localization, wrong id...)
    // In the end, ret is filled with the output string

#if !OFFICIAL
    ret = string.Format("<span class=\"localized\" title=\"{1}\">{0}</span>", ret, expression);
#endif

    return ret;
}

public static string localize(this HtmlHelper htmlhelper, string expression)
{
    return trad(textId);
}

Upvotes: 1

Views: 288

Answers (3)

Reza Aghaei
Reza Aghaei

Reputation: 125197

I think you should create your methods this way:

  • The non-helper Localize method should only try to return localized string. Adding html tags is not concern of this method. (You can add html tags also here without any problem because in the next method, we use HtmlString to create output.)
  • The helper method, should use previous method and then add html tags you need and at last return an HtmlString.

Code:

public static class Extensions
{
    public static string Localize(string exp)
    {
        var ret = exp;
        try
        {
            //try to apply localized version of exp, for example:
            ret = exp + "_Localized";
        }
        catch(Exception ex)
        { 
            //Log ex
        }

        return ret;
    }

    public static IHtmlString Localize(this HtmlHelper htmlhelper, string exp)
    {
        var ret = string.Format("<span class=\"localized\" title=\"{0}\">{1}</span>",
                                exp, Localize(exp));
        return new HtmlString(ret);
    }
}

Upvotes: 2

Mikhail Tulubaev
Mikhail Tulubaev

Reputation: 4251

Razor render string as is. You should use HtmlString for extension methods with markup.

If you declare your method as follows:

public static HtmlString localize(this HtmlHelper htmlhelper, string expression)
{
    return new HtmlString(trad(textId));
}

You wiil be able to use your own extension method like

@Html.localize('your string')

which will be rendered as correct markup

Upvotes: 1

user743382
user743382

Reputation:

Given that you commented you want to make

@Html.localize("textId")

output an HTML element, the solution seems obvious: with a return type of string that's plain impossible by design. So change your method to not return string.

You already found you could in principle use HtmlHelper.Raw which returns IHtmlString, except that IHtmlString isn't assignable to string. If you change your return type to IHtmlString, problem solved.

Upvotes: 2

Related Questions