跨控制器调用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
相关产品推荐
相关产品推荐

