55

Embarrassingly newbie question:

I have a string field in my model that contains line breaks.

@Html.DisplayFor(x => x.MultiLineText)

does not display the line breaks.

Obviously I could do some fiddling in the model and create another field that replaces \n with <br/>, but that seems kludgy. What's the textbook way to make this work?

1

9 Answers 9

79

A HtmlHelper extension method to display string values with line breaks:

public static MvcHtmlString DisplayWithBreaksFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
    var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
    var model = html.Encode(metadata.Model).Replace("\r\n", "<br />\r\n");

    if (String.IsNullOrEmpty(model))
        return MvcHtmlString.Empty;

    return MvcHtmlString.Create(model);
}

And then you can use the following syntax:

@Html.DisplayWithBreaksFor(m => m.MultiLineField)
Sign up to request clarification or add additional context in comments.

4 Comments

Where can I define it in MVC 4 ?
Good, but instead of returning MvcHtmlString.Empty when the value is null or empty I would invoke the standard HtmlHelper.DisplayFor method so that any NullDisplayText decoration can be used.
For other newbs who might not know, define cwills' DisplayWithBreaksFor() method inside "public static class HtmlExtensions { <put the method here> }"
Using a DisplayTemplate instead of introducing a HtmlHelper-method has the advantage, that it trickles down to properties and views that are not explicitly defined (see my answer).
63

i recommend formatting the output with css instead of using cpu consuming server side strings manipulation like .replace,

just add this style property to render multiline texts :

.multiline
{
   white-space: pre-wrap;
}

then

<div class="multiline">
  my
  multiline
  text
</div>

newlines will render like br elements, test it here https://refork.codicode.com/xaf4

2 Comments

To improve on this so that Html.DisplayFor can still be used apply the [System.ComponentModel.DataAnnotations.DataType(System.ComponentModel.DataAnnotations.DataType.MultilineText)] attribute to the MultiLineText property on the model and create a DisplayTemplate with the contents @model string <span class="multiline">@Model</span>
It probably doesn't matter any more, but this doesn't work on IE9 and below
48

In your view, you can try something like

@Html.Raw(Html.Encode(Model.MultiLineText).Replace("\n", "<br />"))

4 Comments

should be at least .Replace("\r\n", ...). Also, the solution from cwills below is much better, in my opinion.
No \n is really enough : remaining \r will not harm since they are juste whitespace for html. While matching on \r\n will miss unix style newline and will not handle them.
Not sure if it was because I'm using ViewData instead of a regular property, but in ASP.NET Core Razor, I had to use @Html.Raw(((string)ViewData["MyText"]).Replace("\n", "<br />"))
I used a slightly different approach, data stored in my case was SQL text: @Html.Raw(field.Replace("\n", "<br />"))
4

The display template is probably the best solution but there is another easy option of using an html helper if you know you're just displaying a string, e.g.:

namespace Shaul.Web.Helpers
{
    public static class HtmlHelpers
    {
        public static IHtmlString ReplaceBreaks(this HtmlHelper helper, string str)
        {
            return MvcHtmlString.Create(str.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None).Aggregate((a, b) => a + "<br />" + b));
        }
    }
}

And then you'd use it like:

@using Shaul.Web.Helpers

@Html.ReplaceBreaks(Model.MultiLineText)

Comments

3

You create a display template for your data. Here's a post detailing how to do it. How do I create a MVC Razor template for DisplayFor()

In that template you do the actual translating of newlines into
and whatever other work needs to be done for presentation.

1 Comment

+1 for the template idea but answer credit goes to the actual implementation given by @slapthelownote
3

Inspired by DisplayTemplates for common DataTypes, I override (introduce?) a default DisplayTemplate for DataType.MultilineText, /Views/Shared/DisplayTemplates/MultilineText.cshtml containing just this line:

<span style="white-space: pre-wrap">@this.Model</span>

(Of course you could replace this style, by a css-class, or replace newlines inside the view, if you prefer that.)

I guess this template is automatically resolved, because I had no need for UIHint or any other reference or registration.

Using the DisplayTemplate instead of introducing a HtmlHelper-method has the advantage, that it trickles down to properties and views that are not explicitly defined.
E.g. DisplayFor(MyClassWithMultilineProperties) will now also correctly display MyClassWithMultilineProperties.MyMultilineTextProperty, if the property was annotated with [DataType(DataType.MultilineText)].

2 Comments

The file name must be MultilineText.cshtml
This is the perfect and very clean solution ,without suffering from un-cleaned css or js changes
2

Try using
@Html.Raw("<p>" + Html.LabelFor(x => x.Name) + "</p>")

Comments

1

Here's another extension method option.

    public static IHtmlString DisplayFormattedFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, string>> expression)
    {
        string value = Convert.ToString(ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).Model);

        if (string.IsNullOrWhiteSpace(value))
        {
            return MvcHtmlString.Empty;
        }

        value = string.Join("<br/>", value.Split(new[] { Environment.NewLine }, StringSplitOptions.None).Select(HttpUtility.HtmlEncode));

        return new HtmlString(value);
    }

Comments

0

I had this problem with ASP.NET Core 6. The previous answers here did not work with a linq expression in Html.DisplayFor. Instead I was constantly getting the <br/> tag escaped out in the output HTML. Trying HtmlString helper methods suggestions did not work.

The following solution was discovered through trial and error. The InfoString had CRLF replaced with the <br/> tags as shown in the property code.

Works

@Html.Raw(@Convert.ToString(item.InfoString))

Did not work

@Html.DisplayFor(modelItem => item.InfoString)

FYI - my Info String property:

public string InfoString
{
   get { return MyInfo.Replace(Environment.NewLine,"<br />"); }
}

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.