You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

跨控制器调用Action后Rotativa PDF生成出现问题

解决跨控制器调用Rotativa ViewAsPdf时ControllerContext错误的方案

这个问题我之前也碰到过,核心原因是你直接用了当前控制器的ControllerContext,但跨控制器生成PDF时,Rotativa需要目标控制器的上下文来正确定位视图、处理路由和视图引擎的查找逻辑。下面是具体的解决步骤:

方法一:手动创建目标控制器的ControllerContext

假设你的MonthlyReport Action属于ReportsController,你需要实例化这个控制器并赋予正确的上下文:

// 1. 实例化目标控制器
var reportsController = new ReportsController();

// 2. 基于当前请求上下文,创建目标控制器的ControllerContext
reportsController.ControllerContext = new ControllerContext(
    this.ControllerContext.RequestContext, 
    reportsController
);

// 3. 使用目标控制器的上下文生成PDF
var pdfBytes = new ViewAsPdf("MonthlyReport", GetOverAllSales) 
{ 
    PageWidth = 215.9, 
    PageHeight = 279.4, 
    PageMargins = new Rotativa.Options.Margins(4, 6, 4, 4) 
}.BuildFile(reportsController.ControllerContext); 

var fileName = "MonthlySalesReport_" + DateTime.Now.Ticks + ".pdf";

方法二:如果使用依赖注入(DI)

如果你的目标控制器有构造函数依赖(比如服务注入),不要直接new,而是从DI容器获取实例:

// 假设你能拿到IServiceProvider(比如在控制器中通过构造函数注入)
var reportsController = _serviceProvider.GetRequiredService<ReportsController>();

// 同样设置ControllerContext
reportsController.ControllerContext = new ControllerContext(
    this.ControllerContext.RequestContext, 
    reportsController
);

// 后续PDF生成代码同上

为什么会出错?

当你跨控制器调用Action生成PDF时,当前的ControllerContext属于发起调用的控制器(比如HomeController),而Rotativa会根据这个上下文去查找视图——它会默认在当前控制器对应的Views文件夹下找MonthlyReport.cshtml,而不是目标控制器的Views文件夹,这就导致视图查找失败或者上下文不匹配,最终抛出错误。

备选方案(不推荐但可用)

如果你不想处理控制器上下文,也可以直接指定视图的完整路径,跳过上下文的依赖:

var pdfBytes = new ViewAsPdf("~/Views/Reports/MonthlyReport.cshtml", GetOverAllSales) 
{ 
    PageWidth = 215.9, 
    PageHeight = 279.4, 
    PageMargins = new Rotativa.Options.Margins(4, 6, 4, 4) 
}.BuildFile(this.ControllerContext); 

这种方式虽然简单,但硬编码了视图路径,后续如果视图位置变动,需要手动修改代码,灵活性较差,优先推荐前两种方法。

内容的提问来源于stack exchange,提问作者R. Patel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:48:24