Remplacer les caractères de saut de ligne par <br /> dans la vue Razor ASP.NET MVC


241

J'ai un contrôle de zone de texte qui accepte une entrée. J'essaie de rendre plus tard ce texte dans une vue en utilisant simplement:

@ Model.CommentText

Il s'agit d'encoder correctement toutes les valeurs. Cependant, je veux remplacer les caractères de saut de ligne par <br />et je ne trouve pas de moyen de m'assurer que les nouvelles balises br ne sont pas encodées. J'ai essayé d'utiliser HtmlString mais je n'ai pas encore eu de chance.


1
Je suppose que les sauts de ligne sont stockés comme \ndans la base de données et que vous souhaitez convertir en un <br />?
Marko

Oui - j'essaye simplement de remplacer \ n par <br /> dans la vue.
bkaid

Réponses:


681

Utilisez la propriété CSS white-space au lieu de vous ouvrir aux vulnérabilités XSS!

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

9
@Jacob Krall - Je me suis connecté juste pour vous donner un +1. Fantastique petit truc.
Levi Botelho

6
quirksmode.org/css/whitespace.html a une bonne explication de pre-line(je ne connaissais que nowrapet pre).
James Skemp

7
Je n'en savais rien. Réponse définitivement meilleure que la mienne.
Omar

39
en fait, white-space: pre-wrap;c'est mieux car vous pre-lineallez jouer avec votre texte en regroupant les espaces blancs en un seul espace.
Chtiwi Malek

4
Malheureusement, cela ne fonctionnera pas dans presque tous les clients de messagerie (y compris Office 2013).
Roger Far

115

Essayez ce qui suit:

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

Mettre à jour:

Selon les marcind'scommentaires sur cette question connexe , l'équipe ASP.NET MVC cherche à implémenter quelque chose de similaire au <%:et <%=pour le moteur de vue Razor.

Mise à jour 2:

Nous pouvons transformer n'importe quelle question sur le codage HTML en une discussion sur les entrées utilisateur nuisibles, mais cela existe déjà.

Quoi qu'il en soit, prenez soin des entrées utilisateur potentiellement nuisibles.

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

Mise à jour 3 (Asp.Net MVC 3):

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

13
Oh mon Dieu, non. Et si je décide de commenter certains <script>.
Darin Dimitrov

4
Merci - cela a fonctionné. Était très proche mais devait avoir fait le remplacement trop tôt ou trop tard. J'ai fini par utiliser ceci: @ MvcHtmlString.Create (Html.Encode (Model.CommentText) .Replace ("\ n", "<br />")) parce que Environment.NewLine ne fonctionnait pas correctement.
bkaid

2
Environment.NewLine ne s'applique pas vraiment aux publications de formulaire, car les navigateurs retournent généralement juste \nau lieu de\r\n
Buildstarted

20
Pour la version finale de MVC 3, la suggestion semble être @ Html.Raw (Html.Encode (Model.CommentText) .Replace (Environment.NewLine, "<br />"))), au lieu d'utiliser MvcHtmlString. Au moins pour l'affichage.
James Skemp

2
Environment.NewLine représente "\ r \ n". Si mon utilisateur a entré des données en utilisant Linux ou Mac, les sauts de ligne sont simplement "\ n" ou "\ r". N'y a-t-il pas quelque part une méthode qui en tienne compte?
SandRock

11

Fractionnez sur les nouvelles lignes (indépendant de l'environnement) et imprimez régulièrement - pas besoin de vous soucier de l'encodage ou du xss:

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

(la suppression des entrées vides est facultative)


10

La troisième solution d'Omar en tant qu'assistant HTML serait:

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

5

En appliquant le principe DRY à la solution d'Omar, voici une extension 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));
        }
    }
}

Utilisation (avec regex amélioré):

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

Cela a également l'avantage supplémentaire de mettre moins de fardeau sur le développeur Razor View pour assurer la sécurité contre les vulnérabilités XSS.


Ma préoccupation avec la solution de Jacob est que le rendu des sauts de ligne avec CSS brise la sémantique HTML .


4

J'avais besoin de briser du texte en paragraphes (balises "p"), j'ai donc créé un assistant simple en utilisant certaines des recommandations des réponses précédentes (merci les gars).

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

Usage:

@Html.ToParagraphs(Model.Comments)

0

Je préfère cette méthode car elle ne nécessite pas de balisage à émission manuelle. J'utilise cela parce que je rend les pages Razor aux chaînes et les envoie par e-mail, qui est un environnement où le style d'espace blanc ne fonctionne pas toujours.

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;
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.