Ersetzen Sie Zeilenumbruchzeichen in der ASP.NET MVC Razor-Ansicht durch <br />


241

Ich habe ein Textbereichssteuerelement, das Eingaben akzeptiert. Ich versuche, diesen Text später in einer Ansicht zu rendern, indem ich einfach Folgendes verwende:

@ Model.CommentText

Dadurch werden alle Werte ordnungsgemäß codiert. Ich möchte jedoch die Zeilenumbruchzeichen durch ersetzen <br />und kann nicht sicherstellen, dass die neuen br-Tags nicht codiert werden. Ich habe versucht, HtmlString zu verwenden, hatte aber noch kein Glück.


1
Ich gehe davon aus, dass Zeilenumbrüche wie \nin der Datenbank gespeichert sind und Sie in eine konvertieren möchten <br />?
— Marko

Ja - ich versuche nur, \ n in der Ansicht durch <br /> zu ersetzen.
— Bkaid

Antworten:


678

Verwenden Sie die CSS-Leerraum-Eigenschaft, anstatt sich XSS-Schwachstellen auszusetzen!

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

9
@Jacob Krall - Ich habe mich angemeldet, um dir eine +1 zu geben. Fantastischer kleiner Trick.
— Levi Botelho

6
quirksmode.org/css/whitespace.html hat eine gute Erklärung von pre-line(mir war nur bewusst nowrapund pre).
— James Skemp

7
Wusste nichts davon. Auf jeden Fall bessere Antwort als meine.
— Omar

39
Eigentlich white-space: pre-wrap;ist es besser, da pre-linees Ihren Text durcheinander bringt, indem Sie Leerzeichen in einem Leerzeichen gruppieren.
— Chtiwi Malek

4
Leider funktioniert dies in fast jedem E-Mail-Client (einschließlich Office 2013) nicht.
— Roger Far

115

Versuche Folgendes:

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

Aktualisieren:

Laut einem marcind'sKommentar zu dieser verwandten Frage möchte das ASP.NET MVC-Team etwas Ähnliches wie die <%:und <%=für die Razor View Engine implementieren .

Update 2:

Wir können jede Frage zur HTML-Codierung in eine Diskussion über schädliche Benutzereingaben verwandeln, aber davon gibt es bereits genug.

Achten Sie auf jeden Fall auf potenziell schädliche Benutzereingaben.

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

Update 3 (Asp.Net MVC 3):

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

13
Oh mein Gott, nein. Was passiert , wenn ich Kommentare über einige entscheiden <script>.
— Darin Dimitrov

4
Danke - das hat funktioniert. War sehr nah dran, muss aber den Austausch zu früh oder zu spät gemacht haben. Am Ende habe ich Folgendes verwendet: @ MvcHtmlString.Create (Html.Encode (Model.CommentText) .Replace ("\ n", "<br />")), weil Environment.NewLine nicht richtig funktionierte.
— Bkaid

2
Environment.NewLine gilt nicht wirklich für Formularbeiträge, da Browser normalerweise nur \nanstelle von\r\n
— Buildstarted

20
Für die veröffentlichte Version von MVC 3 scheint der Vorschlag @ Html.Raw (Html.Encode (Model.CommentText) .Replace (Environment.NewLine, "<br />")) zu sein, anstatt MvcHtmlString zu verwenden. Zumindest zur Anzeige.
— James Skemp

2
Environment.NewLine steht für "\ r \ n". Wenn mein Benutzer Daten unter Linux oder Mac eingegeben hat, sind Zeilenumbrüche nur "\ n" oder "\ r". Gibt es nicht irgendwo eine Methode, die dies berücksichtigt?
— SandRock

11

Auf Zeilenumbrüche aufteilen (umgebungsunabhängig) und regelmäßig drucken - Sie müssen sich keine Gedanken über Codierung oder xss machen:

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

(Leere Einträge entfernen ist optional)


10

Omars dritte Lösung als HTML-Helfer wäre:

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

5

Hier ist eine HTML-Helper-Erweiterung, die das DRY-Prinzip auf Omars Lösung anwendet :

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

Verwendung (mit verbessertem Regex):

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

Dies hat auch den zusätzlichen Vorteil, dass der Razor View-Entwickler weniger belastet wird, um die Sicherheit vor XSS-Schwachstellen zu gewährleisten.


Mein Anliegen bei Jacobs Lösung ist, dass das Rendern der Zeilenumbrüche mit CSS die HTML-Semantik unterbricht .


4

Ich musste Text in Absätze ("p" -Tags) aufteilen, also habe ich einen einfachen Helfer erstellt, der einige der Empfehlungen in früheren Antworten verwendet (danke Jungs).

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

Verwendung:

@Html.ToParagraphs(Model.Comments)

0

Ich bevorzuge diese Methode, da kein manuelles Markup ausgegeben werden muss. Ich benutze dies, weil ich Razor Pages in Strings rendere und sie per E-Mail versende. In dieser Umgebung funktioniert das White-Space-Styling nicht immer.

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;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.