Замініть символи розриву рядків на <br /> у поданні ASP.NET MVC Бритви


241

У мене є текстовий елемент управління, який приймає введення. Я намагаюся пізніше повернути цей текст до перегляду, просто використовуючи:

@ Model.CommentText

Це правильно кодування будь-яких значень. Однак я хочу замінити символи розриву рядків на, <br />і я не можу знайти спосіб переконатися, що нові теги br не кодуються. Я спробував використовувати HtmlString, але поки не пощастив.


1
Я припускаю, що рядкові перерви зберігаються як \nу базі даних, і ви хочете перетворитись на <br />?
Марко

Так - просто намагаються замінити \ n на <br /> у вікні перегляду.
bkaid

Відповіді:


681

Використовуйте властивість білого простору CSS замість того, щоб відкривати себе вразливості XSS!

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

9
@Jacob Krall - я ввійшов, щоб дати вам +1. Фантастична маленька хитрість.
Леві Ботелхо

6
quirksmode.org/css/whitespace.html має гарне пояснення pre-line(я був лише в курсі nowrapта pre).
Джеймс Скемп

7
Не знав про це. Однозначно краща відповідь, ніж моя.
Омар

39
насправді white-space: pre-wrap;краще, оскільки pre-lineзіпсуєтеся з вашим текстом, групуючи пробіли в один простір.
Чтіві Малек

4
На жаль, це не працює майже в будь-якому клієнті електронної пошти (включаючи Office 2013).
Роджер Фар

115

Спробуйте наступне:

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

Оновлення:

Відповідно до marcind'sкоментаря до цього пов'язаного питання , команда ASP.NET MVC прагне реалізувати щось подібне до <%:та <%=для двигуна перегляду Razor.

Оновлення 2:

Ми можемо перетворити будь-яке питання про кодування HTML в дискусію про шкідливі введення користувача, але достатньо цього вже існує.

У будь-якому разі, подбайте про потенційне шкідливе введення користувача.

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

Оновлення 3 (Asp.Net MVC 3):

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

13
Боже мій, ні. Що робити, якщо я вирішу щось прокоментувати <script>.
Дарин Димитров

4
Спасибі - що спрацювало. Був дуже близько, але, мабуть, робив заміну занадто рано чи занадто пізно. Я в кінцевому підсумку скористався цим: @ MvcHtmlString.Create (Html.Encode (Model.CommentText).
bkaid

2
Environment.NewLine насправді не застосовується для публікації повідомлень, оскільки браузери зазвичай повертаються просто \nзамість\r\n
Buildstarted

20
Для випущеної версії MVC 3 пропозиція виглядає як @ Html.Raw (Html.Encode (Model.CommentText). Замінити (Environment.NewLine, "<br />")), а не використовувати MvcHtmlString. Принаймні для показу.
Джеймс Скемп

2
Environment.NewLine представляють "\ r \ n". Якщо мій користувач ввів дані за допомогою linux чи mac, розриви рядків - це просто "\ n" або "\ r". Чи не існує десь методу, який би врахував це?
SandRock

11

Розділяйте нові рядки (середовище агностики) та друкуйте регулярно - не потрібно турбуватися про кодування чи xss:

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

(видаляти порожні записи необов’язково)


10

Третім рішенням Омара як HTML Helper було б:

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

5

Застосовуючи принцип DRY до рішення Omar, ось розширення 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));
        }
    }
}

Використання (з покращеним регексом):

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

Це також має додаткову перевагу - менший вплив на розробника Razor View, щоб забезпечити безпеку від уразливості XSS.


Моє занепокоєння рішенням Якоба полягає в тому, що надання візуальних перерв за допомогою CSS порушує семантику HTML .


4

Мені потрібно було розбити деякий текст на абзаци (теги "p"), тому я створив просту помічницю, використовуючи деякі рекомендації в попередніх відповідях (дякую, хлопці).

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);
    }

Використання:

@Html.ToParagraphs(Model.Comments)

0

Я вважаю за краще цей метод, оскільки він не вимагає розмітки розміщення вручну. Я використовую це, тому що я рендеринга сторінок Razor виводиться на рядки і надсилаю їх по електронній пошті, що є середовищем, коли стиль пробілу не завжди працює.

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;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.