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.

bkaid
quelle
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>
Jacob Krall
quelle
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 />"))
Omar
quelle
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)

drzaus
quelle
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 />"));
}
thelem
quelle
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 .

Akaoni
quelle
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)
Andrea
quelle
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;
}
James S.
quelle