ASP.NET için PDF Görüntüleyici: .NET 10'da PDF'leri Görüntüleme Nasıl Yapılır
Manuel Teklif Oluşturma Sorunu
Bir satış temsilcisinin bir CRM'den bir Word şablonuna satır öğeleri kopyalarken harcadığı her saat, satış yapmadığı bir saattir. Her biri yirmi aktif fırsatı yürüten on kişilik bir ekip genelinde bu süre toplanır ve çıktı bile güvenilir değildir. Fiyatlandırma düzeyleri yanlış uygulanır, indirim alanları son çeyreğe ait oranlarda bırakılır ve eski bir şablon sürümünden olan hüküm dili, gözden geçirilmeden müşteriye gönderilen bir belge içerisine kaydırılır.
Zaman çizelgesi sorunu, doğruluk sorununu bileşikleştirir. Salı öğleden sonra teklif isteyen bir potansiyel müşteri, çarşamba akşamı aldığında, anlaşmanın gerçek olup olmadığını merak ederek bir gün harcar. PDF dosyası ulaştığında, ilgisi daha hızlı yanıt veren bir rakibe kaymış olabilir.
Mevcut CPQ araçları bunun bir kısmını çözer, ancak kurumsal fiyat noktalarına ve yalnızca mevcut fırsat verilerinden temiz bir PDF dosyası gerektiren ekiplerin uygun olmadığı uygulanma zaman çizelgelerine uymazlar. Biçimlendirilmiş bir teklif yerine elektronik tablo veya düz metin fiyat listesi göndermek, müşteriye şirketin satış sürecinin doğaçlama olduğunu işaret eder. Ve müşterinin revizyon talep ettiğinde, sürüm karışıklığı çoğalır, CRM kaydına eklenmiş tek bir doğru kaynak olmadan birçok tekrar e-posta ekleri olarak dolaşır.
Senaryolar çeşitlidir: Salesforce'dan lisans teklifleri çıkaran bir B2B yazılım şirketi, ERP satır öğelerinden parça ve fiyat teklifi üreten bir üretim firması, iç tahminlerden proje kapsam belgeleri oluşturan bir ajans, perakendeci alıcılar için hacim indirimi teklifleri oluşturan bir toptan dağıtıcı. Her durumda temel sürtünme aynıdır.
Çözüm: Fırsat Verisinden Doğrudan Teklif Oluşturma
IronPDF, .NET uygulamalarını CRM fırsat verilerinden doğrudan markalı PDF teklifleri ve önerileri oluşturmaya olanak tanıyan güçlü bir .NET PDF kütüphanesidir. Bir temsilci anlaşmayı teklif vermeye hazır işaretlediğinde veya dahili bir araçta bir düğmeye tıkladığında, uygulama CRM veya veritabanından satır öğelerini, fiyatlandırmayı, müşteri detaylarını ve koşulları çeker, bir HTML şablonunu veya HTML içerik dizesini doldurur ve ChromePdfRenderer bu HTML'den C# PDF'si oluşturur.
Teklif, müşteri adayına e-posta ile gönderilir ve gönderilen belge otomatik olarak CRM kaydına kaydedilir, manuel biçimlendirme, Word şablonları veya belge başına SaaS ücretleri yok. Rendring, var olan .NET uygulaması içinde tek bir NuGet paketinde çalışır. Şablon, ekip tarafından sahiplenilir ve sürüm numaralandırılır, tek bir yerde güncellenir ve her gelecekteki teklifte yansır, satış ekibine dosya dağıtımı yoktur.
Pratikte Nasıl Çalışır?
1. Bir Tetikleyici Teklifi Başlatır
Boru hattı, bir temsilcinin CRM arayüzünde 'Teklif Oluştur' seçeneğine tıklaması, bir fırsatın belirli bir boru hattı aşamasına otomatik olarak girmesi veya bir dış otomasyon platformunun tekliflendirme uç noktasına bir API çağrısı yapması ile başlar. Her üç giriş noktası aynı oluşturma akışını besler, tetikleme mekanizması sonrasında ne olduğunda değişiklik yapmaz.
Uygulama, teklifi gerektiren her şeyi sorgular: potansiyel müşteri şirket adı, yetkili kişinin adı ve e-posta adresi, SKU'lar ile satır öğeleri, açıklamalar, miktarlar, birim fiyatlar, uygulanan indirim yüzdeleri ve satır toplamları; ara toplam, vergi hesaplaması ve toplam toplam; ödeme koşulları, teklif geçerlilik süresi ve temsilcinin fırsata eklediği herhangi bir özel not.
2. HTML Şablonu Teklif Düzenini Tanımlar
Şablon, teklifin tam görsel yapısını idare eder: şirket logosu ve başlığı, potansiyel müşterinin detayları ile bir "Hazırlanan" bloğu, açıklama, miktar, birim fiyat, indirim ve satır toplamı için sütunlarla satır öğesi tablosu, ara toplam ve toplam toplam özeti, koşullar ve şartlar bölümü, ve temsilcinin adı, unvanı ve doğrudan iletişim bilgileri ile bir altbilgi.
Satır öğe tablosu, C# işleyicisinde fırsatın satır öğeleri üzerinde yineleme ve tamamlanmış şablon IronPDF'ye geçmeden önce HTML satırları oluşturularak oluşturulur. Bu, mantığı şablonun kendisinden ziyade uygulama katmanında tutar.
Örnek HTML Dosya Şablonu

3. ChromePdfRenderer Teklif PDF Belgesini Üretir
IronPDF'nin güçlü işleme motoru, HTML'yi PDF'ye dönüştürmeyi basit yapar, genellikle sadece birkaç kod satırında yapılır.
using IronPdf;
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
var lineItemRows = string.Concat(opportunity.LineItems.Select(item => $@"
<tr>
<td>{item.Description}</td>
<td style='text-align:center'>{item.Quantity}</td>
<td style='text-align:right'>{item.UnitPrice:C}</td>
<td style='text-align:center'>{item.DiscountPct}%</td>
<td style='text-align:right'>{item.LineTotal:C}</td>
</tr>"));
string html = $@"
<h1>Quote — {opportunity.ProspectCompany}</h1>
<p>Prepared for: {opportunity.ContactName} <{opportunity.ContactEmail}></p>
<p>Valid until: {opportunity.QuoteExpiry:MMMM d, yyyy} | Terms: {opportunity.PaymentTerms}</p>
<table border='1' cellpadding='6' width='100%'>
<thead><tr><th>Description</th><th>Qty</th><th>Unit Price</th><th>Discount</th><th>Total</th></tr></thead>
<tbody>{lineItemRows}</tbody>
</table>
<p style='text-align:right'><strong>Subtotal:</strong> {opportunity.Subtotal:C}</p>
<p style='text-align:right'><strong>Tax ({opportunity.TaxRatePct}%):</strong> {opportunity.TaxAmount:C}</p>
<p style='text-align:right'><strong>Grand Total:</strong> {opportunity.GrandTotal:C}</p>
<hr/><p style='font-size:11px'>{opportunity.TermsAndConditions}</p>";
PdfDocument quote = renderer.RenderHtmlAsPdf(html);
using IronPdf;
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
var lineItemRows = string.Concat(opportunity.LineItems.Select(item => $@"
<tr>
<td>{item.Description}</td>
<td style='text-align:center'>{item.Quantity}</td>
<td style='text-align:right'>{item.UnitPrice:C}</td>
<td style='text-align:center'>{item.DiscountPct}%</td>
<td style='text-align:right'>{item.LineTotal:C}</td>
</tr>"));
string html = $@"
<h1>Quote — {opportunity.ProspectCompany}</h1>
<p>Prepared for: {opportunity.ContactName} <{opportunity.ContactEmail}></p>
<p>Valid until: {opportunity.QuoteExpiry:MMMM d, yyyy} | Terms: {opportunity.PaymentTerms}</p>
<table border='1' cellpadding='6' width='100%'>
<thead><tr><th>Description</th><th>Qty</th><th>Unit Price</th><th>Discount</th><th>Total</th></tr></thead>
<tbody>{lineItemRows}</tbody>
</table>
<p style='text-align:right'><strong>Subtotal:</strong> {opportunity.Subtotal:C}</p>
<p style='text-align:right'><strong>Tax ({opportunity.TaxRatePct}%):</strong> {opportunity.TaxAmount:C}</p>
<p style='text-align:right'><strong>Grand Total:</strong> {opportunity.GrandTotal:C}</p>
<hr/><p style='font-size:11px'>{opportunity.TermsAndConditions}</p>";
PdfDocument quote = renderer.RenderHtmlAsPdf(html);
Imports IronPdf
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter
renderer.RenderingOptions.MarginTop = 20
renderer.RenderingOptions.MarginBottom = 20
Dim lineItemRows As String = String.Concat(opportunity.LineItems.Select(Function(item) $"
<tr>
<td>{item.Description}</td>
<td style='text-align:center'>{item.Quantity}</td>
<td style='text-align:right'>{item.UnitPrice:C}</td>
<td style='text-align:center'>{item.DiscountPct}%</td>
<td style='text-align:right'>{item.LineTotal:C}</td>
</tr>"))
Dim html As String = $"
<h1>Quote — {opportunity.ProspectCompany}</h1>
<p>Prepared for: {opportunity.ContactName} <{opportunity.ContactEmail}></p>
<p>Valid until: {opportunity.QuoteExpiry:MMMM d, yyyy} | Terms: {opportunity.PaymentTerms}</p>
<table border='1' cellpadding='6' width='100%'>
<thead><tr><th>Description</th><th>Qty</th><th>Unit Price</th><th>Discount</th><th>Total</th></tr></thead>
<tbody>{lineItemRows}</tbody>
</table>
<p style='text-align:right'><strong>Subtotal:</strong> {opportunity.Subtotal:C}</p>
<p style='text-align:right'><strong>Tax ({opportunity.TaxRatePct}%):</strong> {opportunity.TaxAmount:C}</p>
<p style='text-align:right'><strong>Grand Total:</strong> {opportunity.GrandTotal:C}</p>
<hr/><p style='font-size:11px'>{opportunity.TermsAndConditions}</p>"
Dim quote As PdfDocument = renderer.RenderHtmlAsPdf(html)
Oluşturulan PDF Belgesi
4. Teklif Teslim Edilir ve Kaydedilir
using System.Net.Mail;
using System.IO;
// Save versioned copy to document storage
string outputPath = $"quotes/{opportunity.Id}/v{opportunity.QuoteVersion}.pdf";
quote.SaveAs(outputPath);
// Email to prospect
using var stream = new MemoryStream(quote.BinaryData);
using var attachment = new Attachment(stream,
$"Quote-{opportunity.ProspectCompany}-v{opportunity.QuoteVersion}.pdf",
"application/pdf");
var message = new MailMessage("sales@yourcompany.com", opportunity.ContactEmail)
{
Subject = $"Your Quote from {opportunity.RepName} — {opportunity.ProspectCompany}",
Body = $"Hi {opportunity.ContactName},\n\nPlease find your quote attached. It is valid until {opportunity.QuoteExpiry:MMMM d, yyyy}.\n\n{opportunity.RepName}"
};
message.Attachments.Add(attachment);
using var smtp = new SmtpClient("smtp.yourprovider.com");
await smtp.SendMailAsync(message);
// Log reference back to CRM
await _crmService.LogQuoteSentAsync(opportunity.Id, outputPath, DateTime.UtcNow);
using System.Net.Mail;
using System.IO;
// Save versioned copy to document storage
string outputPath = $"quotes/{opportunity.Id}/v{opportunity.QuoteVersion}.pdf";
quote.SaveAs(outputPath);
// Email to prospect
using var stream = new MemoryStream(quote.BinaryData);
using var attachment = new Attachment(stream,
$"Quote-{opportunity.ProspectCompany}-v{opportunity.QuoteVersion}.pdf",
"application/pdf");
var message = new MailMessage("sales@yourcompany.com", opportunity.ContactEmail)
{
Subject = $"Your Quote from {opportunity.RepName} — {opportunity.ProspectCompany}",
Body = $"Hi {opportunity.ContactName},\n\nPlease find your quote attached. It is valid until {opportunity.QuoteExpiry:MMMM d, yyyy}.\n\n{opportunity.RepName}"
};
message.Attachments.Add(attachment);
using var smtp = new SmtpClient("smtp.yourprovider.com");
await smtp.SendMailAsync(message);
// Log reference back to CRM
await _crmService.LogQuoteSentAsync(opportunity.Id, outputPath, DateTime.UtcNow);
Imports System.Net.Mail
Imports System.IO
' Save versioned copy to document storage
Dim outputPath As String = $"quotes/{opportunity.Id}/v{opportunity.QuoteVersion}.pdf"
quote.SaveAs(outputPath)
' Email to prospect
Using stream As New MemoryStream(quote.BinaryData)
Using attachment As New Attachment(stream, $"Quote-{opportunity.ProspectCompany}-v{opportunity.QuoteVersion}.pdf", "application/pdf")
Dim message As New MailMessage("sales@yourcompany.com", opportunity.ContactEmail) With {
.Subject = $"Your Quote from {opportunity.RepName} — {opportunity.ProspectCompany}",
.Body = $"Hi {opportunity.ContactName}," & vbCrLf & vbCrLf & $"Please find your quote attached. It is valid until {opportunity.QuoteExpiry:MMMM d, yyyy}." & vbCrLf & vbCrLf & $"{opportunity.RepName}"
}
message.Attachments.Add(attachment)
Using smtp As New SmtpClient("smtp.yourprovider.com")
Await smtp.SendMailAsync(message)
End Using
End Using
End Using
' Log reference back to CRM
Await _crmService.LogQuoteSentAsync(opportunity.Id, outputPath, DateTime.UtcNow)
Gönderilen E-posta Örneği ile Eklenmiş PDF
Dosya yolu ve dosya adında bir sürüm numarası, her revizyon için kalıcı bir kayıt verir. Potansiyel müşteri değişiklik talep ettiğinde, temsilci CRM'de fırsatı günceller, uygulama artırılmış bir sürümle yeniden üretir ve yeni teklif gönderilir, tüm geçmiş belgede saklanmış ve CRM kaydına kaydedilir.
Gerçek Dünya Faydaları
Potansiyel müşteriye hız. Teklif, temsilci başlattıktan sonra saniyeler içinde oluşturulup e-posta ile gönderilir. Biçimlendirme gecikmesi, taslaklar klasöründe oturan bir belge ve temsilcinin teklifte bulunma kararı ile müşteri adayının alışı arasında bir gecikme yoktur.
Fiyat doğruluğu. Satır öğeleri, indirim seviyeleri ve toplam toplarlar, CRM fırsatından doğrudan alınır. Elle aktarma adımı yoktur ve bir temsilcinin geçen çeyreğin fiyatlandırmasını veya yanlış indirim planını uygulama riski yoktur.
Marka tutarlılığı. Şirketin gönderdiği her teklif aynı logoyu, düzeni, hüküm dilini ve altbilgiyi taşır, hangi temsilci tarafından oluşturulmuş veya hangi boru hattı aşamasından gelmiş olursa olsun. Bireysel dizüstü bilgisayarlarda dolaşan asi Word şablonları yoktur.
Sürüm takibi. Her oluşturulan teklif, fırsat ID'si, sürüm numarası ve ne zaman gönderildiğine dair bir zaman damgası ile saklanır. CRM günlüğü, satış müdürlerine hangi teklifin kime ve ne zaman verildiğine dair tam bir görünürlük sağlar, e-posta türleri arasında kazmaya gerek kalmadan.
Şablon yeniden kullanımı. Hukuk ekibi hüküm dilini veya marka ekibi logoyu yenilediğinde, bir HTML dosyasından değişiklik yapılır ve her gelecekteki teklif buna gölge düşürülür. Satış ekibine Word şablonları dağıtımı yoktur.
Belge başı maliyet yoktur. İşleme, .NET uygulaması içinde süreç içerisinde çalışır. Herhangi bir CPQ aboneliği, belge üretim API ölçümü yoktur ve anlaşma hacmine karşı ölçeklenen bir maliyet modeli yoktur.
Kapanış
CRM fırsat verisiyle profesyonel bir PDF arasındaki boşluk, göründüğünden daha küçüktür, bir şablon, bir render çağrısı ve bir e-posta gönderme, tümü satış iş akışındaki tek bir eylem tarafından tetiklenir. Elle biçimlendirme adımını kaldırmak, sadece zaman kazandırmakla kalmaz; anlaşmalara mal olabilecek bir hata kategorisini de ortadan kaldırır.
Bu boru hattı, mevcut bir .NET uygulaması içinde oluşturulması ve korunması kolaydır. IronPDF, HTML şablonlarının işlenmesinden belgelerin kaydedilmesi, akıtılması ve işlenmesine ironpdf.com adresinde C#'ta tam PDF üretim döngüsünü idare eder. Ücretsiz 30 günlük deneme, kendi CRM verileriniz ve satış iş akışınıza karşı tam bir teklif oluşturma hattı kurup test etmeniz için yeterli süre verir.




