10

I would like to render li items using TagBuilder.

My function

public static string RenderListTag(this HtmlHelper helper, string labelText, string action, string controller, bool isAdmin, string listCssClass = "")
        {
            string value = string.Empty;

            TagBuilder li = new TagBuilder("li");
            TagBuilder anchor = new TagBuilder("a");
            UrlHelper urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);

            if (string.IsNullOrEmpty(action) || string.IsNullOrEmpty(controller))
            {
                anchor.MergeAttribute("href", "#");
            }
            else
            {
                anchor.MergeAttribute("href", urlHelper.Action(action, controller, new
                {
                    area = isAdmin ? "Admin" : ""
                }));
            }

            anchor.SetInnerText(labelText);

            if (action.IsEqualWith(helper.ViewContext.RouteData.Values["action"].ToString()))
            {
                li.MergeAttribute("class", "active");
            }

            if (!string.IsNullOrEmpty(listCssClass))
            {
                li.MergeAttribute("class", listCssClass);
            }

            li.SetInnerText(anchor.ToString(TagRenderMode.Normal));

            return li.ToString(TagRenderMode.Normal);
        }

When I call using the following code:

@Html.RenderListTag("Home", "Index", "Contents", false)
@Html.RenderListTag("About", "About", "Home", false)
@Html.RenderListTag("Contact", "Contact", "Home", false)
@Html.RenderListTag("Show toolbar", "", "", false, "options no-display")
@Html.RenderListTag("CMS", "Index", "Home", true)

The results is printed as text NOT html tag.

<li class="active">&lt;a href=&quot;/Contents&quot;&gt;Home&lt;/a&gt;</li> <li>&lt;a href=&quot;/Home/About&quot;&gt;About&lt;/a&gt;</li> <li>&lt;a href=&quot;/Home/Contact&quot;&gt;Contact&lt;/a&gt;</li> <li class="options no-display">&lt;a href=&quot;#&quot;&gt;Show toolbar&lt;/a&gt;</li> <li class="active">&lt;a href=&quot;/Admin/Home&quot;&gt;CMS&lt;/a&gt;</li> 

I want to print the HTML tag not text.

Where is my mistake ?

5 Answers 5

29

I found my mistake :)

I used

li.SetInnerText(anchor.ToString(TagRenderMode.Normal));

The correct way is

li.InnerHtml = anchor.ToString(TagRenderMode.Normal);

I changed type of my function from string to MvcHtmlString like:

public static MvcHtmlString RenderListTag(this HtmlHelper helper, string labelText, string action, string controller, bool isAdmin, string listCssClass = "")

And the return of function is:

return MvcHtmlString.Create(li.ToString());

Now, works.

Sign up to request clarification or add additional context in comments.

2 Comments

This is the most correct answer. Why go to all the trouble to build an HTML helper only to have to use Html.Raw to render it?...that is the whole point of MvcHtmlString.
I'd always used: return new HtmlString(li.ToString()); (HtmlString is in System.Web) in NET 4.0
5

You must return a MvcHtmlString from method

public static MvcHtmlString RenderListTag(this HtmlHelper helper, string labelText, string action, string controller, bool isAdmin, string listCssClass = "")
{
    string value = string.Empty;

    TagBuilder li = new TagBuilder("li");
    TagBuilder anchor = new TagBuilder("a");
    UrlHelper urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);

    if (string.IsNullOrEmpty(action) || string.IsNullOrEmpty(controller))
    {
        anchor.MergeAttribute("href", "#");
    }
    else
    {
        anchor.MergeAttribute("href", urlHelper.Action(action, controller, new
        {
            area = isAdmin ? "Admin" : ""
        }));
    }

    anchor.SetInnerText(labelText);

    if (action.IsEqualWith(helper.ViewContext.RouteData.Values["action"].ToString()))
    {
        li.MergeAttribute("class", "active");
    }

    if (!string.IsNullOrEmpty(listCssClass))
    {
        li.MergeAttribute("class", listCssClass);
    }

    li.SetInnerText(anchor.ToString(TagRenderMode.Normal));

    return new MvcHtmlString(li.ToString(TagRenderMode.Normal));
}

Comments

3

Use @Html.Raw(Html.RenderListTag("CMS", "Index", "Home", true))

4 Comments

All strinsg in MVC are automatically HTML encoded so we use Raw()
Your code works and I voted up. But I will follow my method described above.
This is not an acceptable answer, extensions do not need to be wrapped with Raw to work. Extensions outputting the tag as text havn't been written correctly (In this case) . See op's "I found my Mistake"
Using return type MvcHtmlString instead of string should also fix the problem no ?
0

Try changing the last line to:

return helper.Raw(li.ToString(TagRenderMode.Normal)).ToHtmlString();

2 Comments

Well, it seems like the SetInnerText was the real problem!
Yes, true. That was my pain :))
0

For situations like this, I have a good friend in the static method HtmlDecode of the HttpUtility class. Try: return MvcHtmlString.Create(HttpUtility.HtmlDecode(li.ToString(TagRenderMode.Normal)));

HTH

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.