如何在 ASP.NET Core MVC 中将视图转换为 PDF

This article was translated from English: Does it need improvement?
Translated
View the article in English

查克尼特·宾

视图是 ASP.NET 框架中的一个组件,用于在网络应用程序中生成 HTML 标记。它是模型-视图-控制器的一部分 (模型-视图-控制器 (MVC)) 模式,常用于 ASP.NET MVC 和 ASP.NET Core MVC 应用程序。视图负责通过动态呈现 HTML 内容向用户展示数据。

ASP.NET Core Web 应用程序 MVC (模型-视图-控制器) 是微软提供的一款网络应用程序,用于使用 ASP.NET Core 构建网络应用程序。

  • 模型:模型: 模型代表数据和业务逻辑,管理数据交互,并与数据源通信。
  • 视图:视图呈现用户界面,重点是显示数据,并向用户呈现信息。
  • 控制器:控制器处理用户输入、响应请求、与模型通信,并协调模型与视图之间的交互。

IronPdf 简化了从 ASP.NET Core MVC 项目中的视图创建 PDF 文件的过程。这使得在 ASP.NET Core MVC 中生成 PDF 变得简单而直接。

IronPDF 扩展包

IronPdf.Extensions.Mvc.Core包是主包IronPdf**的扩展。IronPdf.Extensions.Mvc.Core 和 IronPdf 包都是在 ASP.NET Core MVC 中将视图呈现为 PDF 文档所必需的。

Install-Package IronPdf.Extensions.Mvc.Core
适用于PDF的C# NuGet库

安装使用 NuGet

安装包 IronPdf.Extensions.Mvc.Core

将视图渲染为 PDF

您需要一个 ASP.NET Core Web 应用程序 (模型-视图-控制器) 项目,将视图转换为 PDF 文件。

添加一个模型类

  • 导航至 "模型 "文件夹
  • 创建一个名为 "Person "的新 C# 类文件。该类将作为表示个人数据的模型。使用以下代码片段:
:path=/static-assets/pdf/content-code-examples/how-to/cshtml-to-pdf-mvc-core-model.cs
namespace ViewToPdfMVCCoreSample.Models
{
    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
    }
}
Namespace ViewToPdfMVCCoreSample.Models
	Public Class Person
		Public Property Id() As Integer
		Public Property Name() As String
		Public Property Title() As String
		Public Property Description() As String
	End Class
End Namespace
VB   C#

编辑控制器

导航至 "控制器 "文件夹并打开 "HomeController "文件。我们将只对 HomeController 进行更改,并添加 "人员 "操作。请参阅下面的代码以获得指导:

下面的代码首先实例化了ChromePdfRenderer类,向RenderRazorViewToPdf方法传递了一个IRazorViewRenderer、"Persons.cshtml "的路径以及包含所需数据的列表。用户可利用 RenderingOptions 访问一系列功能,如添加自定义的 文本,包括 HTML 页眉和页脚 在生成的 PDF 中定义自定义页边距,并应用 页码.

请注意
可使用以下代码在浏览器中查看 PDF 文档: File(pdf.BinaryData、"application/pdf").但是,在浏览器中查看 PDF 后再下载,会导致 PDF 文档损坏。

using IronPdf.Extensions.Mvc.Core;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using ViewToPdfMVCCoreSample.Models;

namespace ViewToPdfMVCCoreSample.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;
        private readonly IRazorViewRenderer _viewRenderService;
        private readonly IHttpContextAccessor _httpContextAccessor;
        public HomeController(ILogger<HomeController> logger, IRazorViewRenderer viewRenderService, IHttpContextAccessor httpContextAccessor)
        {
            _logger = logger;
            _viewRenderService = viewRenderService;
            _httpContextAccessor = httpContextAccessor;
        }

        public IActionResult Index()
        {
            return View();
        }

        public async Task<IActionResult> Persons()
        {

            var persons = new List<Person>
            {
            new Person { Name = "Alice", Title = "Mrs.", Description = "Software Engineer" },
            new Person { Name = "Bob", Title = "Mr.", Description = "Software Engineer" },
            new Person { Name = "Charlie", Title = "Mr.", Description = "Software Engineer" }
            };

            if (_httpContextAccessor.HttpContext.Request.Method == HttpMethod.Post.Method)
            {

                ChromePdfRenderer renderer = new ChromePdfRenderer();

                // Render View to PDF document
                PdfDocument pdf = renderer.RenderRazorViewToPdf(_viewRenderService, "Views/Home/Persons.cshtml", persons);

                Response.Headers.Add("Content-Disposition", "inline");

                // Output PDF document
                return File(pdf.BinaryData, "application/pdf", "viewToPdfMVCCore.pdf");
            }
            return View(persons);
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}
using IronPdf.Extensions.Mvc.Core;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using ViewToPdfMVCCoreSample.Models;

namespace ViewToPdfMVCCoreSample.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;
        private readonly IRazorViewRenderer _viewRenderService;
        private readonly IHttpContextAccessor _httpContextAccessor;
        public HomeController(ILogger<HomeController> logger, IRazorViewRenderer viewRenderService, IHttpContextAccessor httpContextAccessor)
        {
            _logger = logger;
            _viewRenderService = viewRenderService;
            _httpContextAccessor = httpContextAccessor;
        }

        public IActionResult Index()
        {
            return View();
        }

        public async Task<IActionResult> Persons()
        {

            var persons = new List<Person>
            {
            new Person { Name = "Alice", Title = "Mrs.", Description = "Software Engineer" },
            new Person { Name = "Bob", Title = "Mr.", Description = "Software Engineer" },
            new Person { Name = "Charlie", Title = "Mr.", Description = "Software Engineer" }
            };

            if (_httpContextAccessor.HttpContext.Request.Method == HttpMethod.Post.Method)
            {

                ChromePdfRenderer renderer = new ChromePdfRenderer();

                // Render View to PDF document
                PdfDocument pdf = renderer.RenderRazorViewToPdf(_viewRenderService, "Views/Home/Persons.cshtml", persons);

                Response.Headers.Add("Content-Disposition", "inline");

                // Output PDF document
                return File(pdf.BinaryData, "application/pdf", "viewToPdfMVCCore.pdf");
            }
            return View(persons);
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}
Imports IronPdf.Extensions.Mvc.Core
Imports Microsoft.AspNetCore.Mvc
Imports System.Diagnostics
Imports ViewToPdfMVCCoreSample.Models

Namespace ViewToPdfMVCCoreSample.Controllers
	Public Class HomeController
		Inherits Controller

		Private ReadOnly _logger As ILogger(Of HomeController)
		Private ReadOnly _viewRenderService As IRazorViewRenderer
		Private ReadOnly _httpContextAccessor As IHttpContextAccessor
		Public Sub New(ByVal logger As ILogger(Of HomeController), ByVal viewRenderService As IRazorViewRenderer, ByVal httpContextAccessor As IHttpContextAccessor)
			_logger = logger
			_viewRenderService = viewRenderService
			_httpContextAccessor = httpContextAccessor
		End Sub

		Public Function Index() As IActionResult
			Return View()
		End Function

		Public Async Function Persons() As Task(Of IActionResult)

'INSTANT VB NOTE: The local variable persons was renamed since Visual Basic will not allow local variables with the same name as their enclosing function or property:
			Dim persons_Conflict = New List(Of Person) From {
				New Person With {
					.Name = "Alice",
					.Title = "Mrs.",
					.Description = "Software Engineer"
				},
				New Person With {
					.Name = "Bob",
					.Title = "Mr.",
					.Description = "Software Engineer"
				},
				New Person With {
					.Name = "Charlie",
					.Title = "Mr.",
					.Description = "Software Engineer"
				}
			}

			If _httpContextAccessor.HttpContext.Request.Method = HttpMethod.Post.Method Then

				Dim renderer As New ChromePdfRenderer()

				' Render View to PDF document
				Dim pdf As PdfDocument = renderer.RenderRazorViewToPdf(_viewRenderService, "Views/Home/Persons.cshtml", persons_Conflict)

				Response.Headers.Add("Content-Disposition", "inline")

				' Output PDF document
				Return File(pdf.BinaryData, "application/pdf", "viewToPdfMVCCore.pdf")
			End If
			Return View(persons_Conflict)
		End Function

		Public Function Privacy() As IActionResult
			Return View()
		End Function

		<ResponseCache(Duration := 0, Location := ResponseCacheLocation.None, NoStore := True)>
		Public Function [Error]() As IActionResult
			Return View(New ErrorViewModel With {.RequestId = If(Activity.Current?.Id, HttpContext.TraceIdentifier)})
		End Function
	End Class
End Namespace
VB   C#

使用 "RenderRazorToPdf "方法后,您将收到一个PDFDocument对象,该对象可供进一步增强和修改。您可以灵活地将 PDF 转换为 PDF/APDFUA 格式,添加您的 数字签名合并和拆分 PDF 文档。此外,该库还可让你旋转页面,插入 注释书签印上独特的水印 到 PDF 文件上。

添加查看

  • 右键单击新添加的人物操作,选择 "添加视图"。

右键单击 人员 操作

  • 为新的脚手架项目选择 "剃刀视图"。

选择脚手架

  • 选择 "列表 "模板和 "人员 "模型类。

添加查看

这将创建一个名为 "人 "的 .cshtml 文件。

  • 导航至 "Views "文件夹->"Home "文件夹->"Persons.cshtml "文件。

要添加一个调用 "Persons "操作的按钮,请使用下面的代码:

@using (Html.BeginForm("Persons", "Home", FormMethod.Post))
{
    <input type="submit" value="Print Person" />
}
@using (Html.BeginForm("Persons", "Home", FormMethod.Post))
{
    <input type="submit" value="Print Person" />
}
HTML

在顶部导航栏添加一个部分

  • 在同一 "Views "文件夹中,导航至 "Shared "文件夹 -> _Layout.cshtml。将 "人员 "导航项放在 "主页 "之后。

确保 asp-action 属性的值与我们的文件名(本例中为 "人员")完全匹配。

<header>
    <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
        <div class="container-fluid">
            <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">ViewToPdfMVCCoreSample</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                    aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                <ul class="navbar-nav flex-grow-1">
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Persons">Person</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                    </li>
                </ul>
            </div>
        </div>
    </nav>
</header>
<header>
    <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
        <div class="container-fluid">
            <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">ViewToPdfMVCCoreSample</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                    aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                <ul class="navbar-nav flex-grow-1">
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Persons">Person</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                    </li>
                </ul>
            </div>
        </div>
    </nav>
</header>
HTML

编辑 Program.cs 文件

我们将在依赖注入中注册 IHttpContextAccessor 和 IRazorViewRenderer 接口 (DI) 集装箱。请查看下面的代码,以供参考。

using IronPdf.Extensions.Mvc.Core;
using Microsoft.AspNetCore.Mvc.ViewFeatures;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();

builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
builder.Services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();

// Register IRazorViewRenderer here
builder.Services.AddSingleton<IRazorViewRenderer, RazorViewRenderer>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();
using IronPdf.Extensions.Mvc.Core;
using Microsoft.AspNetCore.Mvc.ViewFeatures;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();

builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
builder.Services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();

// Register IRazorViewRenderer here
builder.Services.AddSingleton<IRazorViewRenderer, RazorViewRenderer>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();
Imports IronPdf.Extensions.Mvc.Core
Imports Microsoft.AspNetCore.Mvc.ViewFeatures

Private builder = WebApplication.CreateBuilder(args)

' Add services to the container.
builder.Services.AddControllersWithViews()

builder.Services.AddSingleton(Of IHttpContextAccessor, HttpContextAccessor)()
builder.Services.AddSingleton(Of ITempDataProvider, CookieTempDataProvider)()

' Register IRazorViewRenderer here
builder.Services.AddSingleton(Of IRazorViewRenderer, RazorViewRenderer)()

Dim app = builder.Build()

' Configure the HTTP request pipeline.
If Not app.Environment.IsDevelopment() Then
	app.UseExceptionHandler("/Home/Error")
	' The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
	app.UseHsts()
End If

app.UseHttpsRedirection()
app.UseStaticFiles()

app.UseRouting()

app.UseAuthorization()

app.MapControllerRoute(name:= "default", pattern:= "{controller=Home}/{action=Index}/{id?}")

app.Run()
VB   C#

运行项目

向您演示如何运行项目并生成 PDF 文档。

执行 ASP.NET Core MVC 项目

下载 ASP.NET Core MVC 项目

您可以下载本指南的完整代码。它是一个压缩文件,您可以在 Visual Studio 中将其作为 ASP.NET Core Web 应用程序打开。 (模型-视图-控制器) 项目。

点击此处下载项目。

查克尼特·宾

软件工程师

Chaknith 是开发者中的福尔摩斯。他第一次意识到自己可能在软件工程方面有前途,是在他出于乐趣做代码挑战的时候。他的重点是 IronXL 和 IronBarcode,但他为能帮助客户解决每一款产品的问题而感到自豪。Chaknith 利用他从直接与客户交谈中获得的知识,帮助进一步改进产品。他的轶事反馈不仅仅局限于 Jira 票据,还支持产品开发、文档编写和市场营销,从而提升客户的整体体验。当他不在办公室时,他可能会在学习机器学习、编程或徒步旅行。