0

I am working on a Restful application that uses mvc and razor to return xml (let's skip right past how this is a bad idea)

I have a foreach within a partial view that generates xml nodes based on the item:

@foreach (var item in Model)
{
   @Html.RenderElement(item.Type.ToString(), item.Value)
}

RenderElement Helper:

    public static string RenderElement(this HtmlHelper helper, string elementName, object elementValue)
    {
        return string.Format("<{0}>{1}</{0}>", elementName, helper.Encode(elementValue));
    }

I am seeing two issues with this for each loop

  • The items are all being placed on the same line in the output
  • The output of RenderElement is being html encoded

For the first issue is there an accepted method of forcing razor to render a new line? Let me reiterate that I am NOT outputting html with this razor. So a <br> tag is not an option.

I can fix the second issue by wrapping the RenderElement call in a call to @Html.Raw() but this feels messy, so ideally I would like to understand why it is being encoded in the first place and if there is a cleaner way to prevent that.

  • If I had to do it the bad way as you have to (I know you know), I'd probably use [`DisplayFor`](http://msdn.microsoft.com/en-us/library/ee430910%28v=vs.98%29.aspx) and a custom template. – cheesemacfly Aug 27 '14 at 20:39
  • @cheesemacfly not a bad idea but adding display templates will only further complicate an already extremely complicated application. So I'd rather just use the `@Html.Raw` and brute force in an Environment.Newline somewhere. –  Aug 27 '14 at 20:49
  • Well, it adds one element but at least the display is not half generated inside a method but in a Partial View so it can be changed easily. That being said, if you choose to use the extension method, I think `@Html.Raw()` is your only option. – cheesemacfly Aug 27 '14 at 20:59

2 Answers2

0

The reason for issue 2 is that the HtmlHelper.Encode function HTML encodes the value. http://msdn.microsoft.com/en-us/library/system.web.mvc.htmlhelper.encode(v=vs.118).aspx

For issue 1, try and use a <br/> after each node.

Issue 1, since it is not html output (sorry!).. Check the solution to How to insert newline in string literal?

Use \n or Environment.Newline.

Community
  • 1
  • 1
Jason Conville
  • 1,025
  • 10
  • 10
  • Yes it is encoding the value, but am I not correct in believing that is should not be encoding the text that contains it, in the string.Format the value of arg 1 is being encoded explicitly, but somehow the entire format string is being encoded. And for issue one this is NOT html output. –  Aug 27 '14 at 20:10
0

OK after some random poking I came up with a solution to both problems.

Issue #1: The issue here was that because RenderElement was returning a string, razor was implicitly encoding the entire string, the fix was to return an IHtmlString.

public static IHtmlString RenderElement(this HtmlHelper helper, string elementName, object elementValue)
{
    return new HtmlString(string.Format("<{0}>{1}</{0}>", elementName, helper.Encode(elementValue)));
}

Issue #2: I don't have an explanation as to why my solution works, the most I can say is that it makes razor treat the output as a line (if someone can offer a technical explanation of this, that would be fantastic)

@foreach (var item in Model)
{
    <text>@Html.RenderElement(item.Type.ToString(), item.Value)</text>
}
  • This is very strange because even `HtmlString` objects are html encoded (see http://msdn.microsoft.com/en-us/library/system.web.htmlstring.tohtmlstring%28v=vs.110%29.aspx and http://msdn.microsoft.com/en-us/library/system.web.htmlstring.tostring%28v=vs.110%29.aspx) – cheesemacfly Aug 27 '14 at 21:07
  • @cheesemacfly No that makes sense, by calling `ToHtmlString()` you are telling it to encode the string, so from there it will not try to encode it again, whereas I am just creating an HtmlString. –  Aug 27 '14 at 21:11