Sostituisci i caratteri di interruzione di riga con <br /> nella vista Rasoio ASP.NET MVC


241

Ho un controllo textarea che accetta input. Sto cercando di rendere successivamente quel testo in una vista semplicemente usando:

@ Model.CommentText

Questo sta codificando correttamente tutti i valori. Tuttavia, voglio sostituire i caratteri di interruzione di riga con <br />e non riesco a trovare un modo per assicurarsi che i nuovi tag br non vengano codificati. Ho provato a usare HtmlString ma non ho ancora avuto fortuna.


1
Presumo che le interruzioni di riga siano memorizzate come \nnel database e si desidera convertire in <br />?
Marko,

Sì, sto solo cercando di sostituire \ n con <br /> nella vista.
Bkaid,

Risposte:


681

Usa la proprietà CSS dello spazio bianco invece di aprirti alle vulnerabilità XSS!

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

9
@Jacob Krall - Ho effettuato l'accesso solo per darti un +1. Piccolo trucco fantastico.
Levi Botelho,

6
quirksmode.org/css/whitespace.html ha una buona spiegazione di pre-line(ero solo a conoscenza di nowrape pre).
James Skemp,

7
Non lo sapevo. Risposta decisamente migliore della mia.
Omar,

39
in realtà white-space: pre-wrap;è meglio poiché pre-linerovinerà il tuo testo raggruppando gli spazi bianchi in uno spazio.
Chtiwi Malek,

4
Purtroppo questo non funzionerà in quasi tutti i client di posta elettronica (incluso Office 2013).
Roger Far,

115

Prova quanto segue:

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

Aggiornare:

Secondo marcind'scommento su questo problema correlato , il team di ASP.NET MVC sta cercando di implementare qualcosa di simile al <%:e <%=per il motore di visualizzazione Razor.

Aggiornamento 2:

Possiamo trasformare qualsiasi domanda sulla codifica HTML in una discussione sugli input degli utenti dannosi, ma ne esiste già abbastanza.

In ogni caso, prenditi cura del potenziale input dell'utente dannoso.

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

Aggiornamento 3 (Asp.Net MVC 3):

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

13
Oh mio Dio, no. E se decidessi di commentare alcuni <script>.
Darin Dimitrov,

4
Grazie - ha funzionato. Era molto vicino ma deve aver fatto la sostituzione troppo presto o troppo tardi. Ho finito per usare questo: @ MvcHtmlString.Create (Html.Encode (Model.CommentText). Sostituisci ("\ n", "<br />")) perché Environment.NewLine non funzionava correttamente.
Bkaid,

2
Environment.NewLine in realtà non si applica ai post dei moduli poiché i browser di solito restituiscono solo \nanziché\r\n
Buildstarted

20
Per la versione rilasciata di MVC 3, il suggerimento sembra essere @ Html.Raw (Html.Encode (Model.CommentText) .Replace (Environment.NewLine, "<br />")), anziché utilizzare MvcHtmlString. Almeno per la visualizzazione.
James Skemp,

2
Environment.NewLine rappresenta "\ r \ n". Se il mio utente ha inserito i dati usando Linux o Mac, le interruzioni di riga sono solo "\ n" o "\ r". Non esiste un metodo da qualche parte che ne tenga conto?
SandRock,

11

Dividi su newline (ambiente indipendente) e stampa regolarmente - non devi preoccuparti della codifica o di xss:

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

(rimuovere voci vuote è facoltativo)


10

La terza soluzione di Omar come HTML Helper sarebbe:

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

5

Applicando il principio DRY alla soluzione di Omar, ecco un'estensione 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));
        }
    }
}

Utilizzo (con regex migliorato):

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

Ciò ha anche l'ulteriore vantaggio di mettere meno a carico dello sviluppatore Razor View per garantire la sicurezza dalle vulnerabilità XSS.


La mia preoccupazione per la soluzione di Jacob è che il rendering delle interruzioni di riga con CSS interrompe la semantica HTML .


4

Avevo bisogno di suddividere un po 'di testo in paragrafi (tag "p"), quindi ho creato un semplice aiuto usando alcuni dei consigli nelle risposte precedenti (grazie ragazzi).

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

Uso:

@Html.ToParagraphs(Model.Comments)

0

Preferisco questo metodo in quanto non richiede l'emissione manuale di markup. Lo uso perché sto eseguendo il rendering di Razor Pages in stringhe e inviandole via e-mail, che è un ambiente in cui lo stile degli spazi bianchi non funzionerà sempre.

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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.