Zamień znaki podziału linii na <br /> w widoku Razor ASP.NET MVC


241

Mam kontrolkę textarea, która przyjmuje dane wejściowe. Próbuję później renderować ten tekst do widoku, używając po prostu:

@ Model.CommentText

To poprawnie koduje dowolne wartości. Chcę jednak zastąpić znaki podziału wiersza <br />i nie mogę znaleźć sposobu, aby upewnić się, że nowe znaczniki br nie zostaną zakodowane. Próbowałem użyć HtmlString, ale nie miałem jeszcze szczęścia.


1
Zakładam, że podziały wierszy są przechowywane jak \nw bazie danych i chcesz przekonwertować na <br />?
— Marko,

Tak - po prostu próbuję zamienić \ n na <br /> w widoku.
— bkaid

Odpowiedzi:


681

Skorzystaj z właściwości białych znaków CSS zamiast otwierać się na luki w XSS!

<span style="white-space: pre-line">@Model.CommentText</span>

9
@Jacob Krall - Zalogowałem się, aby dać ci +1. Fantastyczna sztuczka.
— Levi Botelho,

6
quirksmode.org/css/whitespace.html ma dobre wyjaśnienie pre-line(byłem tylko świadomy nowrapi pre).
— James Skemp,

7
Nie wiedziałem o tym. Zdecydowanie lepsza odpowiedź niż moja.
— Omar,

39
faktycznie white-space: pre-wrap;jest lepszy, ponieważ pre-linebędzie bałagan z tekstem, grupując białe spacje w jednym miejscu.
— Chtiwi Malek

4
Niestety nie zadziała to w prawie żadnym kliencie poczty e-mail (w tym Office 2013).
— Roger Far

115

Spróbuj wykonać następujące czynności:

@MvcHtmlString.Create(Model.CommentText.Replace(Environment.NewLine, "<br />"))

Aktualizacja:

Według marcind'skomentarza na ten powiązane pytanie , zespół ASP.NET MVC szuka zaimplementować coś podobnego do <%:i <%=na widok silnika Razor.

Aktualizacja 2:

Możemy zamienić dowolne pytanie dotyczące kodowania HTML w dyskusję na temat szkodliwych danych wprowadzanych przez użytkowników, ale wystarczająco dużo tego już istnieje.

W każdym razie, zadbaj o potencjalnie szkodliwy wkład użytkownika.

@MvcHtmlString.Create(Html.Encode(Model.CommentText).Replace(Environment.NewLine, "<br />"))

Aktualizacja 3 (Asp.Net MVC 3):

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

13
O mój Boże, nie. Co jeśli zdecyduję się coś skomentować <script>.
— Darin Dimitrov,

4
Dzięki - działało. Był bardzo blisko, ale musiał dokonać wymiany zbyt wcześnie lub za późno. Skończyło się na tym: @ MvcHtmlString.Create (Html.Encode (Model.CommentText) .Replace ("\ n", "<br />")), ponieważ Environment.NewLine nie działał poprawnie.
— bkaid

2
Environment.NewLine tak naprawdę nie ma zastosowania do tworzenia postów, ponieważ przeglądarki zwykle zwracają się \nzamiast\r\n
— Buildstarted

20
W wydanej wersji MVC 3 sugerowana jest @ Html.Raw (Html.Encode (Model.CommentText) .Replace (Environment.NewLine, „<br />”)), zamiast używania MvcHtmlString. Przynajmniej na pokaz.
— James Skemp

2
Environment.NewLine reprezentuje „\ r \ n”. Jeśli mój użytkownik wprowadził dane przy użyciu systemu Linux lub Mac, podziały wiersza to po prostu „\ n” lub „\ r”. Czy gdzieś nie ma takiej metody?
— SandRock,

11

Podziel na nowe wiersze (bez względu na środowisko) i drukuj regularnie - nie musisz martwić się o kodowanie lub xss:

@if (!string.IsNullOrWhiteSpace(text)) 
{
    var lines = text.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
    foreach (var line in lines)
    {
        <p>@line</p>
    }
}

(remove empty entries is optional)


10

Trzecie rozwiązanie Omara jako pomocnika HTML to:

public static IHtmlString FormatNewLines(this HtmlHelper helper, string input)
{
    return helper.Raw(helper.Encode(input).Replace("\n", "<br />"));
}

5

Stosując zasadę DRY do rozwiązania Omara, oto rozszerzenie HTML Helper:

using System.Web.Mvc;
using System.Text.RegularExpressions;

namespace System.Web.Mvc.Html {
    public static class MyHtmlHelpers {
        public static MvcHtmlString EncodedReplace(this HtmlHelper helper, string input, string pattern, string replacement) {
            return new MvcHtmlString(Regex.Replace(helper.Encode(input), pattern, replacement));
        }
    }
}

Użycie (z ulepszonym wyrażeniem regularnym):

@Html.EncodedReplace(Model.CommentText, "[\n\r]+", "<br />")

Ma to również tę dodatkową zaletę, że nakłada mniej obciążenia na programistę Razor View, aby zapewnić bezpieczeństwo przed lukami w zabezpieczeniach XSS.


Obawiam się, że rozwiązanie Jacoba polega na tym, że renderowanie podziałów linii za pomocą CSS przerywa semantykę HTML .


4

Musiałem podzielić trochę tekstu na akapity (tagi „p”), więc stworzyłem prostego pomocnika, korzystając z niektórych zaleceń z poprzednich odpowiedzi (dziękuję wam).

public static MvcHtmlString ToParagraphs(this HtmlHelper html, string value) 
    { 
        value = html.Encode(value).Replace("\r", String.Empty);
        var arr = value.Split('\n').Where(a => a.Trim() != string.Empty);
        var htmlStr = "<p>" + String.Join("</p><p>", arr) + "</p>";
        return MvcHtmlString.Create(htmlStr);
    }

Stosowanie:

@Html.ToParagraphs(Model.Comments)

0

Wolę tę metodę, ponieważ nie wymaga ręcznego emitowania znaczników. Używam tego, ponieważ renderuję Strony Razor na ciągi i wysyłam je pocztą e-mail, co jest środowiskiem, w którym styl białych znaków nie zawsze działa.

public static IHtmlContent RenderNewlines<TModel>(this IHtmlHelper<TModel> html, string content)
{
    if (string.IsNullOrEmpty(content) || html is null)
    {
        return null;
    }

    TagBuilder brTag = new TagBuilder("br");
    IHtmlContent br = brTag.RenderSelfClosingTag();
    HtmlContentBuilder htmlContent = new HtmlContentBuilder();

    // JAS: On the off chance a browser is using LF instead of CRLF we strip out CR before splitting on LF.
    string lfContent = content.Replace("\r", string.Empty, StringComparison.InvariantCulture);
    string[] lines = lfContent.Split('\n', StringSplitOptions.None);
    foreach(string line in lines)
    {
        _ = htmlContent.Append(line);
        _ = htmlContent.AppendHtml(br);
    }

    return htmlContent;
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.