Ganti karakter pemisah baris dengan <br /> dalam tampilan ASP.NET MVC Razor

241

Saya memiliki kontrol textarea yang menerima input. Saya mencoba nanti merender teks itu ke tampilan hanya dengan menggunakan:

@ Model.CommentText

Ini dengan benar mengkodekan nilai apa pun. Namun, saya ingin mengganti karakter pemisah baris dengan <br />dan saya tidak dapat menemukan cara untuk memastikan bahwa tag br baru tidak disandikan. Saya telah mencoba menggunakan HtmlString tetapi belum beruntung.

Bkaid
sumber
1
Saya kira linebreak disimpan \ndalam database dan Anda ingin mengonversi menjadi <br />?
Marko
Ya - hanya mencoba mengganti \ n dengan <br /> dalam tampilan.
Bkaid

Jawaban:

681

Gunakan properti white-space CSS alih-alih membuka diri Anda terhadap kerentanan XSS!

<span style="white-space: pre-line">@Model.CommentText</span>
Jacob Krall
sumber
9
@ Jacob Krall - Saya masuk hanya untuk memberi Anda +1. Trik kecil yang fantastis.
Levi Botelho
6
quirksmode.org/css/whitespace.html memiliki penjelasan yang baik tentang pre-line(saya hanya mengetahui nowrapdan pre).
James Skemp
7
Tidak tahu tentang ini. Jawaban yang pasti lebih baik daripada saya.
Omar
39
sebenarnya white-space: pre-wrap;lebih baik karena pre-lineakan mengacaukan teks Anda dengan mengelompokkan spasi putih menjadi satu ruang.
Chtiwi Malek
4
Sayangnya ini tidak akan berfungsi di hampir semua klien email (termasuk Office 2013).
Roger Far
115

Coba yang berikut ini:

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

Memperbarui:

Menurut marcind'skomentar pada pertanyaan terkait ini , tim ASP.NET MVC mencari untuk mengimplementasikan sesuatu yang mirip dengan <%:dan <%=untuk mesin tampilan Razor.

Pembaruan 2:

Kami dapat mengubah pertanyaan apa pun tentang penyandian HTML menjadi diskusi tentang input pengguna yang berbahaya, tetapi sudah cukup.

Pokoknya, berhati-hatilah terhadap input pengguna potensial yang berbahaya.

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

Pembaruan 3 (Asp.Net MVC 3):

@Html.Raw(Html.Encode(Model.CommentText).Replace("\n", "<br />"))
Omar
sumber
13
Ya Tuhanku, tidak. Bagaimana jika saya memutuskan untuk berkomentar tentang beberapa <script>.
Darin Dimitrov
4
Terima kasih - itu berhasil. Sangat dekat tetapi pasti telah melakukan penggantian terlalu cepat atau terlambat. Saya akhirnya menggunakan ini: @ MvcHtmlString.Create (Html.Encode (Model.CommentText). Ganti ("\ n", "<br />")) karena Environment.NewLine tidak berfungsi dengan benar.
Bkaid
2
Environment.NewLine tidak benar-benar berlaku untuk membentuk tulisan sejak browser biasanya kembali hanya \nbukan\r\n
Buildstarted
20
Untuk versi MVC 3 yang dirilis, sarannya adalah @ Html.Raw (Html.Encode (Model.CommentText). Ganti (Environment.NewLine, "<br />")), alih-alih menggunakan MvcHtmlString. Setidaknya untuk tampilan.
James Skemp
2
Environment.NewLine mewakili "\ r \ n". Jika pengguna saya memasukkan data menggunakan linux atau mac, linebreak hanyalah "\ n" atau "\ r". Apakah tidak ada metode di suatu tempat yang memperhitungkan hal ini?
SandRock
11

Berpisah pada baris baru (agnostik lingkungan) dan mencetak secara teratur - tidak perlu khawatir tentang penyandian atau xss:

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

(menghapus entri kosong adalah opsional)

drzaus
sumber
10

Solusi ketiga Omar sebagai Helper HTML adalah:

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

Menerapkan prinsip KERING untuk solusi Omar, berikut ini adalah ekstensi 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));
        }
    }
}

Penggunaan (dengan regex yang ditingkatkan):

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

Ini juga memiliki manfaat tambahan dengan mengurangi tanggung jawab pada pengembang Razor View untuk memastikan keamanan dari kerentanan XSS.


Kekhawatiran saya dengan solusi Jacob adalah membuat rendering baris dengan CSS merusak semantik HTML .

Akaoni
sumber
4

Saya perlu memecah beberapa teks menjadi paragraf ("p" tag), jadi saya membuat pembantu sederhana menggunakan beberapa rekomendasi di jawaban sebelumnya (terima kasih kawan).

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

Pemakaian:

@Html.ToParagraphs(Model.Comments)
Andrea
sumber
0

Saya lebih suka metode ini karena tidak memerlukan markup memancarkan secara manual. Saya menggunakan ini karena saya memberikan Halaman Razor ke string dan mengirimkannya melalui email, yang merupakan lingkungan di mana penataan ruang putih tidak akan selalu berfungsi.

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.
sumber