Dapatkah saya menyiapkan Template HTML / Email dengan ASP.NET?

97

Saya sedang mengerjakan situs yang akan mengirimkan sejumlah besar email. Saya ingin menyiapkan teks header dan footer, atau mungkin bahkan template untuk memungkinkan pengguna mengedit email ini dengan mudah jika mereka perlu.

Jika saya menyematkan HTML di dalam literal string C #, itu jelek dan mereka harus khawatir tentang pelolosan. Menyertakan file datar untuk header dan footer mungkin berhasil, tetapi ada sesuatu yang terasa tidak benar.

Apa yang ideal untuk menggunakan .ASPXhalaman sebagai template, lalu beri tahu kode saya untuk menyajikan halaman itu, dan gunakan HTML yang dikembalikan untuk email.

Adakah cara yang bagus dan mudah untuk melakukan ini? Apakah ada cara yang lebih baik untuk menyelesaikan masalah ini?

Diperbarui:
Saya menambahkan jawaban yang memungkinkan Anda menggunakan halaman .aspx standar sebagai template email. Cukup ganti semua variabel seperti biasa, gunakan penyatuan data, dll. Kemudian tangkap saja output halaman, dan voila! Anda memiliki email HTML Anda!

DIPERBARUI DENGAN CAVEAT !!!:
Saya menggunakan kelas MailDefinition pada beberapa halaman aspx dengan baik, tetapi ketika mencoba menggunakan kelas ini selama proses server yang sedang berjalan, gagal. Saya percaya itu karena metode MailDefinition.CreateMailMessage () memerlukan kontrol yang valid untuk referensi, meskipun tidak selalu melakukan sesuatu. Karena itu, saya akan merekomendasikan pendekatan saya menggunakan halaman aspx, atau pendekatan Mun menggunakan halaman ascx, yang tampaknya sedikit lebih baik.

John Bubriski
sumber
Solusi lain adalah menggunakan AlphaMail untuk membuat dan mengirim email Anda menggunakan C # dan bahasa template Comlang .
Timothy E. Johansson
1
@JohnBubriski: pekerjaan yang saya sekitar masalah kontrol yang Anda sebutkan dalam "UPDATED dengan peringatan" menggunakan new System.Web.UI.Control()seperti di: mailDefinition.CreateMailMessage("[email protected]", iDictionaryReplacements, new System.Web.UI.Control()).
Theophilus
Ya, saya telah melakukannya juga, tetapi dengan munculnya Razor, ini menjadi ide yang kurang bagus.
John Bubriski

Jawaban:

73

Ada banyak sekali jawaban di sini, tetapi saya menemukan artikel bagus tentang cara menggunakan Razor dengan template email. Razor didorong dengan ASP.NET MVC 3, tetapi MVC tidak diperlukan untuk menggunakan Razor. Ini adalah pemrosesan yang cukup apik dalam melakukan templat email

Seperti yang diidentifikasi dalam artikel, "Hal terbaik dari Razor adalah tidak seperti pendahulunya (formulir web), ia tidak terikat dengan lingkungan web, kami dapat dengan mudah menghostingnya di luar web dan menggunakannya sebagai mesin template untuk berbagai tujuan."

Menghasilkan email HTML dengan RazorEngine - Bagian 01 - Pendahuluan

Memanfaatkan Template Razor Di Luar ASP.NET: Ini Bukan Hanya untuk HTML Lagi!

Template email yang lebih cerdas di ASP.NET dengan RazorEngine

QA Stackoverflow serupa

Membuat template menggunakan RazorEngine API baru

Menggunakan Razor tanpa MVC

Apakah mungkin menggunakan Razor View Engine di luar asp.net

Mike Barlow - BarDev
sumber
1
+1 tapi hati-hati jika pengguna menyediakan template, karena mereka dapat menjalankan kode C # dari template, memberi mereka lebih banyak kekuatan di sistem Anda daripada yang Anda inginkan.
AaronLS
Apa pendapat Anda tentang Keamanan. Menggunakan mesin templating ini memungkinkan untuk memformat seluruh sistem file. Saya suka mesinnya, tapi itu memaksa saya untuk melihat mesin lain.
der_chirurg
55

Anda mungkin juga ingin mencoba memuat kontrol, lalu merendernya ke string dan menyetelnya sebagai Badan HTML:

// Declare stringbuilder to render control to
StringBuilder sb = new StringBuilder();

// Load the control
UserControl ctrl = (UserControl) LoadControl("~/Controls/UserControl.ascx");

// Do stuff with ctrl here

// Render the control into the stringbuilder
StringWriter sw = new StringWriter(sb);
Html32TextWriter htw = new Html32TextWriter(sw);
ctrl.RenderControl(htw);

// Get full body text
string body = sb.ToString();

Anda kemudian dapat membuat email Anda seperti biasa:

MailMessage message = new MailMessage();
message.From = new MailAddress("[email protected]", "from name");
message.Subject = "Email Subject";
message.Body = body;
message.BodyEncoding = Encoding.ASCII;
message.IsBodyHtml = true;

SmtpClient smtp = new SmtpClient("server");
smtp.Send(message);

Kontrol pengguna Anda bisa berisi kontrol lain, seperti header dan footer, dan juga memanfaatkan fungsionalitas seperti data binding.

Mun
sumber
Saya entah bagaimana melewatkan jawaban ini untuk pertama kalinya ... yang bagus. Mirip dengan solusi saya, tetapi dengan ascx, bukan aspx. Saya masih berpikir aspx akan lebih baik, karena akan menawarkan halaman yang lengkap, bukan kontrol, tapi itulah yang saya pikirkan.
John Bubriski
Ya, Anda dapat menggunakan salah satu solusi ... Mereka bekerja dengan cara yang sama. Salah satu manfaat dari pendekatan ini adalah konsistensi. Misalnya, Anda dapat menampilkan ringkasan pesanan kepada pengguna dan menyertakan hal yang persis sama di email konfirmasi dengan menggunakan kembali kontrol yang sama.
Mun
Poin kecil tetapi Anda kehilangan satu baris untuk mendeklarasikan StringBuilder di blok kode pertama.
Kirschstein
9
Contoh tidak menjelaskan di mana kode berada, apakah itu halaman ?, karena LoadControl adalah metode halaman / kontrol.
Shrage Smilowitz
@ Mun, Anda memuat kontrol pengguna ke dalam variabel yang disebut ctrl, dan Anda tidak pernah mereferensikannya lagi dalam kode Anda. Bagaimana cara kerjanya?
The Muffin Man
35

Anda dapat mencoba kelas MailDefinition

John Sheehan
sumber
4
Saya hanya ingin menunjukkan bahwa ini bagus untuk email dasar, tetapi bukan sesuatu yang rumit. Kelas MailDefinition tidak mendukung penyatuan data. Satu-satunya hal yang dilakukannya adalah menawarkan penggantian string. Meskipun, itu juga dibangun ke dalam Wisaya Pembuatan Akun Keanggotaan.
John Bubriski
4
Kelas MailDefinition harus mendapatkan Kontrol untuk merender konten template .. Tidak begitu bagus.
Yuki
17

Jika Anda ingin meneruskan parameter seperti nama pengguna, nama produk, ... dll. Anda dapat menggunakan mesin template open source NVelocity untuk menghasilkan email / HTML akhir Anda.

Contoh template NVelocity ( MailTemplate.vm ):

A sample email template by <b>$name</b>.
<br />

Foreach example :
<br />    
#foreach ($item in $itemList)

[Date: $item.Date] Name: $item.Name, Value: $itemValue.Value
<br /><br />

#end

Menghasilkan badan email dengan MailTemplate.vm di aplikasi Anda:

VelocityContext context = new VelocityContext();
context.Put("name", "ScarletGarden");
context.Put("itemList", itemList);

StringWriter writer = new StringWriter();

Velocity.MergeTemplate("MailTemplate.vm", context, writer);

string mailBody = writer.GetStringBuilder().ToString();

Badan email yang dihasilkan adalah:

Contoh template email oleh ScarletGarden .

Foreach contoh:

[Tanggal: 12.02.2009] Nama: Item 1, Nilai: 09

[Tanggal: 21.02.2009] Nama: Item 4, Nilai: 52

[Tanggal: 01.03.2009] Nama: Item 2, Nilai: 21

[Tanggal: 23.03.2009] Nama: Item 6, Nilai: 24

Untuk mengedit template, mungkin Anda bisa menggunakan FCKEditor dan menyimpan template Anda ke file.

Canavar
sumber
7

Komponen email Mail.dll termasuk mesin template email:

Berikut ringkasan sintaks:

<html>
<body>
Hi {FirstName} {LastName},

Here are your orders: 
{foreach Orders}
    Order '{Name}' sent to <strong>{Street}</strong>. 
{end}

</body>
</html>

Dan kode yang memuat template, mengisi data dari objek c # dan mengirim email:

Mail.Html(Template
              .FromFile("template.txt")
              .DataFrom(_contact)
              .Render())
    .Text("This is text version of the message.")
    .From(new MailBox("[email protected]", "Alice"))
    .To(new MailBox("[email protected]", "Bob"))
    .Subject("Your order")
    .UsingNewSmtp()
    .WithCredentials("[email protected]", "password")
    .Server("mail.com")
    .WithSSL()
    .Send();

Anda bisa mendapatkan info lebih lanjut di entri blog mesin template email .

Atau cukup unduh komponen email Mail.dll dan cobalah.

Harap dicatat bahwa ini adalah produk komersial yang saya buat.

Pawel Lesnikowski
sumber
6

Jika fleksibilitas adalah salah satu prasyarat Anda, XSLT mungkin merupakan pilihan yang baik, yang sepenuhnya didukung oleh .NET framework dan Anda bahkan dapat membiarkan pengguna mengedit file tersebut. Artikel ini ( http://www.aspfree.com/c/a/XML/XSL-Transformations-using-ASP-NET/ ) mungkin berguna sebagai permulaan (msdn memiliki info lebih lanjut tentang itu). Seperti yang dikatakan oleh ScarletGarden, NVelocity adalah pilihan bagus lainnya tetapi saya lebih suka XSLT karena dukungan kerangka kerja .NET "bawaan" dan platform agnostik.

Everton
sumber
Saya tidak pernah memikirkan ini sebelumnya, tetapi setelah mencoba banyak metode lain, saya menemukan ini bekerja dengan baik dalam kombinasi dengan menambahkan IXmlSerializableantarmuka ke kelas saya. Hanya dalam beberapa baris saya dapat meminta kelas saya menyerahkan email.
cjbarth
Urgh, aku pernah bermimpi buruk tentang XSLT. Mungkin bahasa pemrograman / markup paling non-intuitif yang pernah saya gunakan. Dan tidak mungkin untuk mempertahankan untuk orang lain dan bahkan untuk diri Anda sendiri 1 bulan setelah Anda pertama kali memberi kode XSLT Anda.
PussInBoots
5

Saya pikir Anda juga bisa melakukan sesuatu seperti ini:

Buat dan .aspx halaman, dan letakkan ini di akhir metode OnLoad, atau panggil secara manual.

    StringBuilder sb = new StringBuilder();
    StringWriter sw = new StringWriter(sb);
    HtmlTextWriter htmlTW = new HtmlTextWriter(sw);
    this.Render(htmlTW);

Saya tidak yakin apakah ada masalah potensial dengan ini, tetapi sepertinya itu akan berhasil. Dengan cara ini, Anda dapat menggunakan halaman .aspx berfitur lengkap, daripada kelas MailDefinition yang hanya mendukung penggantian Teks.

John Bubriski
sumber
Meskipun kelas MailDefinition adalah permulaan yang baik, ini sedikit belum sempurna. Metode ini seharusnya mendukung lebih banyak fitur seperti penyatuan data, dan bahkan mungkin pelacakan. Ada pemikiran tentang ini, atau potensi gotchas?
John Bubriski
Bagus! Apakah Anda memiliki masalah dengan itu?
John Bubriski
Jadi Anda akan mengizinkan pengguna mengedit file .aspx saat mereka perlu membuat perubahan pada template email? Saya akan menyebutnya masalah potensial.
Bryan
Saya tidak akan berpikir demikian, setidaknya, tidak ada lebih banyak risiko daripada templat lain yang dapat mereka edit. Memang, jika mereka tahu apa yang mereka lakukan, mereka dapat menyebabkan kerugian, tetapi setidaknya dalam kasus ini, tidak mungkin. Ini tidak akan menjadi halaman .aspx yang kompleks, lebih dari template dengan placeholder.
John Bubriski
Sudah lama, saya tahu, tetapi apakah Anda ingat solusi terakhir Anda? Saya tidak bisa mendapatkan pendekatan khusus ini untuk bekerja dengan Page, setidaknya saat menggunakan metode ekstensi generik untuk rendering. Jadi saya beralih ke UserControl; lihat jawaban saya di bawah ini. Sejauh ini tampaknya berjalan dengan baik ... Saya tertarik untuk mempelajari bagaimana Anda mengerjakannya saat itu.
InteXX
4

Tentu Anda dapat membuat template html dan saya akan merekomendasikan juga template teks. Dalam template Anda cukup meletakkan [BODY] di tempat tubuh akan ditempatkan dan kemudian Anda bisa membaca di template dan mengganti tubuh dengan konten baru. Anda dapat mengirim email menggunakan .Nets Mail Class. Anda hanya perlu mengulang pengiriman email ke semua penerima setelah Anda membuat email pada awalnya. Bekerja seperti pesona bagi saya.

using System.Net.Mail;

// Email content
string HTMLTemplatePath = @"path";
string TextTemplatePath = @"path";
string HTMLBody = "";
string TextBody = "";

HTMLBody = File.ReadAllText(HTMLTemplatePath);
TextBody = File.ReadAllText(TextTemplatePath);

HTMLBody = HTMLBody.Replace(["[BODY]", content);
TextBody = HTMLBody.Replace(["[BODY]", content);

// Create email code
MailMessage m = new MailMessage();

m.From = new MailAddress("[email protected]", "display name");
m.To.Add("[email protected]");
m.Subject = "subject";

AlternateView plain = AlternateView.CreateAlternateViewFromString(_EmailBody + text, new System.Net.Mime.ContentType("text/plain"));
AlternateView html = AlternateView.CreateAlternateViewFromString(_EmailBody + body, new System.Net.Mime.ContentType("text/html"));
mail.AlternateViews.Add(plain);
mail.AlternateViews.Add(html);

SmtpClient smtp = new SmtpClient("server");
smtp.Send(m);
Josh Mein
sumber
Anda dapat memotong hal-hal StreamReader dan mengganti dengan File.ReadAllText (jalur)
John Sheehan
Ini adalah awal yang baik, tetapi hanya menyediakan fungsionalitas untuk header dan footer. Ini tidak terlalu membantu tubuh itu sendiri.
John Bubriski
Body yang harus Anda lakukan adalah memasukkan konten body yang diinginkan ke dalam HTMLBody dan TextBody Fields atau tentunya Anda juga dapat menyimpannya dalam file
Josh Mein
4

Berikut ini satu lagi alternatif yang menggunakan transformasi XSL untuk templat email yang lebih kompleks: Mengirim email berbasis HTML dari aplikasi .NET .

Alek Davis
sumber
2
Suka tautannya. Terima kasih! Otak saya mulai berputar dan menyadari bahwa saya bisa melangkah lebih jauh, dan memiliki template XSLT yang mengambil objek XML Serializable, atau Kontrak Data WCF langsung ke format html-email. Tiba-tiba saya memiliki template email 'yang diketik kuat' melalui kelas yang dapat diserialkan yang sebenarnya!
CodingWithSpike
2

Hati-hati saat melakukan ini, filter SPAM tampaknya memblokir html yang dihasilkan ASP.net, tampaknya karena Kondisi Tampilan, jadi jika Anda akan melakukan ini pastikan Html yang dihasilkan bersih.

Saya pribadi akan mempertimbangkan penggunaan Asp.net MVC untuk mencapai hasil yang Anda inginkan. atau NVelocity cukup bagus dalam hal ini

danswain
sumber
1

Apa yang ideal untuk menggunakan halaman .ASPX sebagai template, lalu beri tahu kode saya untuk menyajikan halaman itu, dan gunakan HTML yang dikembalikan untuk email.

Anda dapat dengan mudah membuat WebRequest untuk membuka halaman ASPX dan mendapatkan HTML yang dihasilkan. Dengan sedikit lebih banyak pekerjaan, Anda mungkin bisa menyelesaikannya tanpa WebRequest. Sebuah PageParser dan Response.Filter akan memungkinkan Anda untuk menjalankan halaman dan menangkap hasilnya ... meskipun mungkin ada beberapa cara yang lebih elegan.

Tandai Brackett
sumber
1

Saya memiliki persyaratan serupa pada salah satu proyek di mana Anda harus mengirim sejumlah besar email setiap hari, dan klien menginginkan kontrol penuh atas template html untuk berbagai jenis email.

karena banyaknya email yang akan dikirim, kinerja menjadi perhatian utama.

yang kami temukan adalah konten statis di server sql tempat Anda menyimpan seluruh markup template html (bersama dengan placeholder, seperti [UserFirstName], [UserLastName] yang diganti dengan data nyata pada waktu proses) untuk berbagai jenis email

lalu kami memuat data ini di cache asp.net - jadi kami tidak membaca template html berulang kali - tetapi hanya jika template tersebut benar-benar berubah

kami memberi klien editor WYSIWYG untuk memodifikasi template ini melalui formulir web admin. setiap kali pembaruan dibuat, kami mengatur ulang cache asp.net.

dan kemudian kami memiliki tabel terpisah untuk log email - di mana setiap email yang akan dikirim telah dicatat. tabel ini memiliki bidang yang disebut emailType, emailSent dan numberOfTries.

kami hanya menjalankan pekerjaan setiap 5 menit untuk jenis email penting (seperti pendaftaran anggota baru, lupa kata sandi) yang perlu dikirim secepatnya

kami menjalankan pekerjaan lain setiap 15 menit untuk jenis email yang kurang penting (seperti email promosi, email berita, dll)

dengan cara ini Anda tidak memblokir server Anda yang mengirim email tanpa henti dan Anda memproses email secara berkelompok. setelah email terkirim, setel field emailSent ke 1.

Raj
sumber
Tapi bagaimana Anda menangani koleksi?
Riri
1
Saya telah melakukan ini juga dan berhasil dengan baik. Selain itu, Anda dapat kembali secara historis dan melihat catatan email yang dikirim, jika laporan adalah urusan Anda.
Mark Glorie
1

Perhatikan bahwa solusi aspx dan ascx memerlukan HttpContext saat ini, jadi tidak dapat digunakan secara asinkron (misalnya dalam utas) tanpa banyak pekerjaan.

Rosco
sumber
1

Saya pikir jawaban yang mudah adalah MvcMailer. Ini adalah paket NuGet yang memungkinkan Anda menggunakan mesin tampilan favorit Anda untuk menghasilkan email. Lihat paket NuGet di sini dan dokumentasi proyek

Semoga membantu!

Sohan
sumber
Hmm, anehnya jawaban ini tidak mendapat banyak perhatian ?!
PussInBoots
1

DotLiquid adalah pilihan lain. Anda menentukan nilai dari model kelas sebagai {{ user.name }}dan kemudian pada waktu proses Anda memberikan data di kelas itu, dan template dengan markup, dan itu akan menggabungkan nilai untuk Anda. Ini mirip dengan menggunakan mesin template Razor dalam banyak hal. Ini mendukung hal-hal yang lebih kompleks seperti loop dan berbagai fungsi seperti ToUpper. Yang menyenangkan adalah ini "aman" sehingga pengguna yang membuat templat tidak dapat merusak sistem Anda atau menulis kode yang tidak aman seperti yang Anda lakukan di pisau cukur: http://dotliquidmarkup.org/try-online

AaronLS
sumber
0

Jika Anda mampu untuk memungkinkan ASPNET dan pengguna terkait izin untuk membaca & menulis file, Anda dapat dengan mudah menggunakan file HTML dengan standar String.Format()placeholder ( {0}, {1:C}, dll) untuk mencapai hal ini.

Cukup baca di file, sebagai string, menggunakan kelas dari System.IOnamespace. Setelah Anda memiliki string itu, teruskan sebagai argumen pertama ke String.Format(), dan berikan parameternya.

Simpan string itu, dan gunakan sebagai badan email, dan pada dasarnya Anda sudah selesai. Kami melakukan ini di lusinan situs (yang memang kecil) hari ini, dan tidak memiliki masalah.

Saya harus mencatat bahwa ini bekerja paling baik jika (a) Anda tidak mengirim jutaan email sekaligus, (b) Anda tidak mempersonalisasi setiap email (jika tidak, Anda memakan banyak string) dan (c ) file HTML itu sendiri relatif kecil.

John Rudy
sumber
0

Setel pesan Email IsBodyHtml = true

Ambil objek Anda yang berisi konten email Anda Serialisasi objek dan gunakan xml / xslt untuk menghasilkan konten html.

Jika Anda ingin melakukan AlternateView, lakukan hal yang sama dengan jmein hanya menggunakan template xslt yang berbeda untuk membuat konten teks biasa.

salah satu keuntungan utama dari ini adalah jika Anda ingin mengubah tata letak Anda, Anda harus memperbarui template xslt.

Bob Si Petugas Kebersihan
sumber
0

Lihat SubSonic (www.subsonicproject.com). Mereka melakukan ini untuk menghasilkan kode - templatnya adalah ASPX standar, dan menghasilkan c #. Metode yang sama dapat digunakan kembali untuk skenario Anda.

jvenema
sumber
0

Saya akan menggunakan pustaka template seperti TemplateMachine . ini memungkinkan Anda sebagian besar meletakkan template email Anda bersama dengan teks normal dan kemudian menggunakan aturan untuk memasukkan / mengganti nilai yang diperlukan. Sangat mirip dengan ERB di Ruby. Hal ini memungkinkan Anda untuk memisahkan pembuatan konten email tanpa terlalu mengikat Anda ke sesuatu seperti ASPX dll. Setelah konten dibuat dengan ini, Anda dapat mengirim email.

MikeJ
sumber
0

Saya suka jawaban Raj. Program seperti ListManager & kerangka kerja seperti DNN melakukan hal serupa, dan jika pengeditan mudah oleh pengguna non-teknis diperlukan, editor WYSIWYG untuk memodifikasi HTML yang disimpan dalam SQL adalah cara yang paling mudah dan lugas untuk dilakukan dan dapat dengan mudah mengakomodasi pengeditan header secara independen dari footer, dll, serta menggunakan token untuk memasukkan nilai secara dinamis.

Satu hal yang perlu diingat jika menggunakan metode di atas (atau yang lainnya, sungguh) adalah menjadi ketat dan berhati-hati tentang jenis gaya dan tag yang Anda izinkan untuk disisipkan oleh editor. Jika menurut Anda browser itu rumit, tunggu saja sampai Anda melihat betapa berbedanya klien email membuat hal yang sama ...

Nick
sumber
0

Mirip dengan jawaban Canavar, tetapi bukannya NVelocity, saya selalu menggunakan " StringTemplate " yang memuat template dari file konfigurasi, atau memuat file eksternal menggunakan File.ReadAllText () dan menetapkan nilainya.

Ini adalah proyek Java tetapi port C # solid dan saya telah menggunakannya di beberapa proyek (hanya menggunakannya untuk template email menggunakan template di file eksternal).

Alternatif selalu bagus.

Bryan Bailliache
sumber
0

Berikut adalah cara sederhana menggunakan kelas WebClient :

public static string GetHTMLBody(string url)
{
    string htmlBody;

    using (WebClient client = new WebClient ())
    {
        htmlBody = client.DownloadString(url);
    }

    return htmlBody;
}

Kemudian sebut saja seperti ini:

string url = "http://www.yourwebsite.com";
message.Body = GetHTMLBody(url);

Tentu saja, CSS Anda perlu diratakan untuk menampilkan gaya halaman web di sebagian besar klien email (seperti Outlook). Jika email Anda menampilkan konten dinamis (mis. Nama Pelanggan), maka saya akan merekomendasikan menggunakan QueryStrings di situs web Anda untuk mengisi data. (mis. http://www.yourwebsite.com?CustomerName=Bob )

ROFLwTIME
sumber
Baik, meskipun saya pikir sebagian besar jawaban lain melakukan ini tanpa membuat permintaan web kembali ke situs, yaitu harus meng-host badan email di situs Anda.
Rup
@Rup Dapat dimengerti, tetapi perlu diingat bahwa sering kali orang ingin melihat "Versi Web" dari email tersebut. Solusi ini berfungsi sempurna untuk skenario itu.
ROFLwTIME
0

@bardev memberikan solusi yang baik, tetapi sayangnya ini tidak ideal di semua kasus. Punyaku adalah salah satunya.

Saya menggunakan WebForms di Website (saya bersumpah saya tidak akan pernah menggunakan Website lagi - what a PITA) di VS 2013.

Saya mencoba saran Razor, tetapi milik saya adalah Situs Web saya tidak mendapatkan IntelliSense yang sangat penting yang diberikan oleh IDE dalam proyek MVC. Saya juga suka menggunakan desainer untuk template saya - tempat yang sempurna untuk UserControl.

Nix on Razor lagi.

Jadi saya datang dengan kerangka kecil ini sebagai gantinya (tip topi ke @mun untuk UserControl dan @imatoria untuk Pengetikan Kuat). Satu-satunya tempat masalah potensial yang dapat saya lihat adalah Anda harus berhati-hati untuk menjaga nama file .ASCX Anda tetap sinkron dengan nama kelasnya. Jika Anda menyimpang, Anda akan mendapatkan error runtime.

FWIW: Dalam pengujian saya setidaknya panggilan RenderControl () tidak menyukai kontrol Halaman, jadi saya menggunakan UserControl.

Saya cukup yakin saya telah memasukkan semuanya di sini; beri tahu saya jika saya melewatkan sesuatu.

HTH

Pemakaian:

Partial Class Purchase
  Inherits UserControl

  Private Sub SendReceipt()
    Dim oTemplate As MailTemplates.PurchaseReceipt

    oTemplate = MailTemplates.Templates.PurchaseReceipt(Me)
    oTemplate.Name = "James Bond"
    oTemplate.OrderTotal = 3500000
    oTemplate.OrderDescription = "Q-Stuff"
    oTemplate.InjectCss("PurchaseReceipt")

    Utils.SendMail("{0} <[email protected]>".ToFormat(oTemplate.Name), "Purchase Receipt", oTemplate.ToHtml)
  End Sub
End Class

Kelas Dasar:

Namespace MailTemplates
  Public MustInherit Class BaseTemplate
    Inherits UserControl

    Public Shared Function GetTemplate(Caller As TemplateControl, Template As Type) As BaseTemplate
      Return Caller.LoadControl("~/MailTemplates/{0}.ascx".ToFormat(Template.Name))
    End Function



    Public Sub InjectCss(FileName As String)
      If Me.Styler IsNot Nothing Then
        Me.Styler.Controls.Add(New Controls.Styler(FileName))
      End If
    End Sub



    Private ReadOnly Property Styler As PlaceHolder
      Get
        If _Styler Is Nothing Then
          _Styler = Me.FindNestedControl(GetType(PlaceHolder))
        End If

        Return _Styler
      End Get
    End Property
    Private _Styler As PlaceHolder
  End Class
End Namespace

Kelas "Pabrik":

Namespace MailTemplates
  Public Class Templates
    Public Shared ReadOnly Property PurchaseReceipt(Caller As TemplateControl) As PurchaseReceipt
      Get
        Return BaseTemplate.GetTemplate(Caller, GetType(PurchaseReceipt))
      End Get
    End Property
  End Class
End Namespace

Kelas Template:

Namespace MailTemplates
  Public MustInherit Class PurchaseReceipt
    Inherits BaseTemplate

    Public MustOverride WriteOnly Property Name As String
    Public MustOverride WriteOnly Property OrderTotal As Decimal
    Public MustOverride WriteOnly Property OrderDescription As String
  End Class
End Namespace

Header ASCX:

<%@ Control Language="VB" ClassName="_Header" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<!--
  See https://www.campaignmonitor.com/blog/post/3317/ for discussion of DocType in HTML Email
-->

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title></title>
  <asp:PlaceHolder ID="plcStyler" runat="server"></asp:PlaceHolder>
</head>
<body>

ASCX Footer:

<%@ Control Language="VB" ClassName="_Footer" %>

</body>
</html>

Template ASCX:

<%@ Control Language="VB" AutoEventWireup="false" CodeFile="PurchaseReceipt.ascx.vb" Inherits="PurchaseReceipt" %>

<%@ Register Src="_Header.ascx" TagName="Header" TagPrefix="uc" %>
<%@ Register Src="_Footer.ascx" TagName="Footer" TagPrefix="uc" %>

<uc:Header ID="ctlHeader" runat="server" />

  <p>Name: <asp:Label ID="lblName" runat="server"></asp:Label></p>
  <p>Order Total: <asp:Label ID="lblOrderTotal" runat="server"></asp:Label></p>
  <p>Order Description: <asp:Label ID="lblOrderDescription" runat="server"></asp:Label></p>

<uc:Footer ID="ctlFooter" runat="server" />

File Kode Template ASCX:

Partial Class PurchaseReceipt
  Inherits MailTemplates.PurchaseReceipt

  Public Overrides WriteOnly Property Name As String
    Set(Value As String)
      lblName.Text = Value
    End Set
  End Property



  Public Overrides WriteOnly Property OrderTotal As Decimal
    Set(Value As Boolean)
      lblOrderTotal.Text = Value
    End Set
  End Property



  Public Overrides WriteOnly Property OrderDescription As Decimal
    Set(Value As Boolean)
      lblOrderDescription.Text = Value
    End Set
  End Property
End Class

Pembantu:

'
' FindNestedControl helpers based on tip by @andleer
' at http://stackoverflow.com/questions/619449/
'

Public Module Helpers
  <Extension>
  Public Function AllControls(Control As Control) As List(Of Control)
    Return Control.Controls.Flatten
  End Function



  <Extension>
  Public Function FindNestedControl(Control As Control, Id As String) As Control
    Return Control.Controls.Flatten(Function(C) C.ID = Id).SingleOrDefault
  End Function



  <Extension>
  Public Function FindNestedControl(Control As Control, Type As Type) As Control
    Return Control.Controls.Flatten(Function(C) C.GetType = Type).SingleOrDefault
  End Function



  <Extension>
  Public Function Flatten(Controls As ControlCollection) As List(Of Control)
    Flatten = New List(Of Control)

    Controls.Traverse(Sub(Control) Flatten.Add(Control))
  End Function


  <Extension>
  Public Function Flatten(Controls As ControlCollection, Predicate As Func(Of Control, Boolean)) As List(Of Control)
    Flatten = New List(Of Control)

    Controls.Traverse(Sub(Control)
                        If Predicate(Control) Then
                          Flatten.Add(Control)
                        End If
                      End Sub)
  End Function



  <Extension>
  Public Sub Traverse(Controls As ControlCollection, Action As Action(Of Control))
    Controls.Cast(Of Control).ToList.ForEach(Sub(Control As Control)
                                               Action(Control)

                                               If Control.HasControls Then
                                                 Control.Controls.Traverse(Action)
                                               End If
                                             End Sub)
  End Sub



  <Extension()>
  Public Function ToFormat(Template As String, ParamArray Values As Object()) As String
    Return String.Format(Template, Values)
  End Function



  <Extension()>
  Public Function ToHtml(Control As Control) As String
    Dim oSb As StringBuilder

    oSb = New StringBuilder

    Using oSw As New StringWriter(oSb)
      Using oTw As New HtmlTextWriter(oSw)
        Control.RenderControl(oTw)
        Return oSb.ToString
      End Using
    End Using
  End Function
End Module



Namespace Controls
  Public Class Styler
    Inherits LiteralControl

    Public Sub New(FileName As String)
      Dim _
        sFileName,
        sFilePath As String

      sFileName = Path.GetFileNameWithoutExtension(FileName)
      sFilePath = HttpContext.Current.Server.MapPath("~/Styles/{0}.css".ToFormat(sFileName))

      If File.Exists(sFilePath) Then
        Me.Text = "{0}<style type=""text/css"">{0}{1}</style>{0}".ToFormat(vbCrLf, File.ReadAllText(sFilePath))
      Else
        Me.Text = String.Empty
      End If
    End Sub
  End Class
End Namespace



Public Class Utils
  Public Shared Sub SendMail(Recipient As MailAddress, Subject As String, HtmlBody As String)
    Using oMessage As New MailMessage
      oMessage.To.Add(Recipient)
      oMessage.IsBodyHtml = True
      oMessage.Subject = Subject.Trim
      oMessage.Body = HtmlBody.Trim

      Using oClient As New SmtpClient
        oClient.Send(oMessage)
      End Using
    End Using
  End Sub
End Class
InteXX
sumber
0

Hanya membuang perpustakaan yang saya gunakan ke dalam campuran: https://github.com/lukencode/FluentEmail

Ini merender email menggunakan RazorLight , menggunakan gaya fasih untuk membuat email, dan mendukung banyak pengirim di luar kotak. Itu datang dengan metode ekstensi untuk ASP.NET DI juga. Mudah digunakan, sedikit pengaturan, dengan teks biasa dan dukungan HTML.

ahong
sumber