হ্যালো হাসিব! আজকের লেকচারটিতে আমরা শিখবো কীভাবে ASP.NET Core অ্যাপ্লিকেশনে Rotativa প্যাকেজ ব্যবহার করে ডায়নামিকভাবে HTML View-কে PDF ফাইলে কনভার্ট করা যায়।

“Chatrabash” এর মতো SaaS অ্যাপ্লিকেশনে ইনভয়েস (Invoice) বা রিপোর্ট (Report) জেনারেট করে ইউজারকে ডাউনলোড করতে দেওয়ার জন্য এই ফিচারটি খুবই কাজে লাগে।

চলো লেকচারটির একটি কুইক সামারি এবং বিস্তারিত আলোচনা শুরু করি।

📝 Lecture Summary at a Glance

  • The Goal: ক্লায়েন্টের রিকোয়ারমেন্ট অনুযায়ী C# কোড থেকে HTML View-কে PDF ফাইল হিসেবে রেন্ডার বা ডাউনলোড করানো।
  • The Tool (Rotativa): Rotativa.AspNetCore নামক একটি থার্ড-পার্টি NuGet প্যাকেজ এই কাজের জন্য ব্যবহার করা হয়।
  • Dedicated PDF View: PDF এর জন্য একটি আলাদা Razor View (PersonsPDF.cshtml) তৈরি করতে হয় যেখানে Layout (null) করা থাকে, যাতে ওয়েবসাইটের ন্যাভিগেশন বার বা ফুটার PDF-এ না চলে আসে।
  • CSS Loading Issue: PDF ভিউতে CSS লোড করার জন্য রিলেটিভ পাথ (/css/style.css) কাজ করে না। রিকোয়েস্ট থেকে ডোমেইন নেম নিয়ে (যেমন: http://localhost:5000/css/style.css) অ্যাবসোলিউট (Absolute) পাথ তৈরি করতে হয়।
  • The Engine (wkhtmltopdf): Rotativa একা কাজ করতে পারে না। ব্যাকএন্ডে PDF বানানোর জন্য এর wkhtmltopdf.exe ইঞ্জিন লাগে, যা wwwroot/Rotativa ফোল্ডারে রাখতে হয় এবং Program.cs-এ কনফিগার করতে হয়।

🧠 Comprehensive Breakdown & Deep Dive

১. Setting up the Dedicated PDF View [Importance: 9/10]

  • The “Why”: তোমার মূল ইনডেক্স পেজে সার্চ বক্স, বাটন, হেডার, ফুটার থাকে। তুমি তো চাও না সেগুলো ইনভয়েস বা পিডিএফ-এর ভেতরে প্রিন্ট হয়ে যাক! তাই PDF-এর জন্য শুধুমাত্র ডাটা টেবিল বা দরকারি অংশটুকু নিয়ে একটি ক্লিন View বানাতে হয়।

💻 Code Implementation (PersonsPDF.cshtml):

@model IEnumerable<PersonResponse>
@{
    // লেআউট বন্ধ করা হলো যাতে হেড/ফুটার না আসে
    Layout = null; 
}
 
<!DOCTYPE html>
<html>
<head>
    <title>Persons Report</title>
    <link href="http://@(Context.Request.Host.ToString())/stylesheet.css" rel="stylesheet" />
</head>
<body>
    <h2>Persons Report</h2>
    <table>
        <thead>
            <tr>
                <th>Person Name</th>
                <th>Email</th>
                <th>Age</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var person in Model)
            {
                <tr>
                    <td>@person.PersonName</td>
                    <td>@person.Email</td>
                    <td>@(person.DateOfBirth?.ToString("yyyy-MM-dd") ?? "N/A")</td>
                </tr>
            }
        </tbody>
    </table>
</body>
</html>
 

২. Generating PDF from Controller [Importance: 10/10]

  • The “Why”: ইউজার যখন “Download as PDF” বাটনে ক্লিক করবে, তখন Controller ওই ভিউটাকে HTML হিসেবে না পাঠিয়ে Rotativa-এর সাহায্যে PDF স্ট্রিম হিসেবে পাঠাবে।

💻 Code Implementation (PersonsController.cs):

using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using Rotativa.AspNetCore.Options;
 
[HttpGet]
[Route("[action]")]
public async Task<IActionResult> PersonsPDF()
{
    // ১. ডাটাবেস থেকে সব ডাটা আনা
    var persons = await _personsService.GetAllPersons();
 
    // ২. Rotativa এর ViewAsPdf অবজেক্ট রিটার্ন করা
    return new ViewAsPdf("PersonsPDF", persons, ViewData)
    {
        PageMargins = new Margins(20, 20, 20, 20), // পেজের মার্জিন
        PageOrientation = Orientation.Landscape,   // ল্যান্ডস্কেপ বা পোর্ট্রেট
        PageSize = Size.A4                       // পেজ সাইজ
    };
}
 

৩. The “wkhtmltopdf” Setup Error & Solution [Importance: 10/10]

  • The “Why”: প্রথমবার কোড রান করার পর লেকচারার একটি এরর পেয়েছিলেন: “Value cannot be null. Parameter name: path1”. এর কারণ হলো Rotativa প্যাকেজটি নিজে কোনো কনভার্টার নয়, এটি মূলত wkhtmltopdf নামক একটি ওপেন-সোর্স C++ ইঞ্জিনের র‍্যাপার (Wrapper)। ইঞ্জিনটি প্রজেক্টে না থাকলে এটি কাজ করবে না।

🛠️ The Setup Process (Cross-Platform Reality Check): লেকচারার .exe ফাইল ডাউনলোডের কথা বলেছেন যা শুধুমাত্র Windows-এ কাজ করে। হাসিব, তুমি যেহেতু Fedora Linux ব্যবহার করছো, তাই তোমার সিস্টেমে .exe কাজ করবে না। তোমাকে লিনাক্সের বাইনারি ব্যবহার করতে হবে।

For Fedora Linux (Your Environment): ১. তোমার লিনাক্স টার্মিনালে নিচের কমান্ড দিয়ে ইঞ্জিনটি গ্লোবালি ইনস্টল করে নাও:

sudo dnf install wkhtmltopdf
 

২. এরপর তোমার প্রজেক্টের wwwroot এর ভেতরে Rotativa নামের একটি ফোল্ডার বানাবে (তবে লিনাক্সে গ্লোবাল ইনস্টল থাকলে অনেক সময় এটি কপি না করলেও চলে, বাট সেফটির জন্য রাখতে পারো)।

💻 Program.cs Configuration (.NET 10 Standard):

var builder = WebApplication.CreateBuilder(args);
// ... অন্যান্য কনফিগারেশন ...
var app = builder.Build();
 
// অ্যাপ্লিকেশনের এনভায়রনমেন্ট সেট হওয়ার পর Rotativa সেটআপ করা
// লিনাক্সের জন্য পাথ সেটআপ কিছুটা ট্রিকি হতে পারে, ডিফল্টভাবে নিচের লাইনটি দিয়ে দেখতে পারো
RotativaConfiguration.Setup(builder.Environment.WebRootPath, "Rotativa");
 
app.Run();
 

🚀 Modern .NET Architecture Notes & Alternatives

The Reality of Rotativa in .NET 8/10: হাসিব, প্রজেক্টে কাজ করার ক্ষেত্রে একটি বড় সতর্কবার্তা: Rotativa.AspNetCore প্যাকেজটি অনেক পুরনো এবং মেইনটেইন করা হয় না। এটি লেটেস্ট .NET ভার্সন এবং লিনাক্স কন্টেইনারে (Docker) অনেক সময় বাগ বা পারফরম্যান্স ইস্যু তৈরি করে। বিশেষ করে মাল্টি-ট্যানেন্ট (Multi-tenant) SaaS অ্যাপ্লিকেশন, যেমন তোমার “Chatrabash”-এর জন্য এটি বেস্ট চয়েস নয়।

Modern Alternatives (Highly Recommended): তুমি যখন প্রোডাকশন লেভেলের প্রজেক্ট বানাবে, তখন Rotativa-এর বদলে নিচের যেকোনো একটি মডার্ন লাইব্রেরি ব্যবহার করার চেষ্টা করবে:

১. QuestPDF (Free for small/open-source, highly recommended): এটি কোনো HTML-to-PDF কনভার্টার নয়। এটি সরাসরি C# কোড (Fluent API) দিয়ে পিক্সেল-পারফেক্ট PDF ড্র করে। এটি অবিশ্বাস্য রকমের ফাস্ট এবং এর কোনো এক্সটার্নাল ইঞ্জিন (wkhtmltopdf) লাগে না। ২. DinkToPdf: এটি Rotativa এর একটি ক্রস-প্ল্যাটফর্ম অল্টারনেটিভ। ৩. PuppeteerSharp: এটি হেডলেস ক্রোম (Headless Chrome) ব্রাউজার ব্যবহার করে HTML কে PDF-এ কনভার্ট করে। এটি মডার্ন CSS (যেমন Flexbox, Grid) ১০০% সাপোর্ট করে, যা Rotativa সাপোর্ট করে না।

Pro Tip: যদি শুধুমাত্র ডাটা এক্সপোর্ট করার দরকার হয়, তবে PDF এর চেয়ে Excel/CSV Export অনেক বেশি ইউজার-ফ্রেন্ডলি। কারণ ইউজাররা ডাটা নিয়ে কাজ করতে পারে।

পরবর্তী লেকচারে সম্ভবত CSV বা Excel জেনারেশন নিয়ে আলোচনা করা হবে। তুমি রেডি হলে সেই ট্রান্সক্রিপ্টটি দিতে পারো!