为Crystal Reports Web API在.NET Core 6.0中搭建反向代理的方案咨询
整体架构思路
将报表相关逻辑完全隔离到独立的.NET Framework 4.8 Web API项目中,专门处理Crystal Reports的加载、参数绑定、导出等操作;原业务系统迁移到.NET Core 6 Web API,通过反向代理将报表类请求转发到4.8服务,实现两套系统的协同工作。
步骤1:搭建.NET Framework 4.8 Crystal Reports服务
1.1 创建项目
新建ASP.NET Web Application (.NET Framework),选择Web API模板,框架版本选.NET Framework 4.8。
1.2 安装Crystal Reports依赖
通过NuGet安装以下包(根据报表需求调整):
CrystalDecisions.CrystalReports.Engine CrystalDecisions.ReportSource CrystalDecisions.Shared CrystalDecisions.Web
确保服务器已安装对应版本的Crystal Reports运行时(32/64位需与项目一致)。
1.3 编写报表接口
创建ReportsController,实现报表生成/导出接口:
using System.IO; using System.Net.Http.Headers; using System.Web.Http; using CrystalDecisions.CrystalReports.Engine; namespace CrystalReportsService.Controllers { public class ReportsController : ApiController { // 示例:根据报表ID和参数生成PDF报表 [HttpGet] [Route("api/reports/generate")] public IHttpActionResult GenerateReport(string reportId, string? param1 = null) { try { // 加载报表文件(可根据实际路径调整) var reportPath = Path.Combine(System.Web.Hosting.HostingEnvironment.MapPath("~/Reports"), $"{reportId}.rpt"); var reportDocument = new ReportDocument(); reportDocument.Load(reportPath); // 设置报表参数 if (!string.IsNullOrEmpty(param1)) { reportDocument.SetParameterValue("Param1", param1); } // 导出为PDF字节流 var stream = new MemoryStream(); reportDocument.ExportToStream(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat).CopyTo(stream); stream.Position = 0; // 返回文件结果 var result = new HttpResponseMessage(System.Net.HttpStatusCode.OK) { Content = new StreamContent(stream) }; result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf"); result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = $"{reportId}_{System.DateTime.Now:yyyyMMddHHmmss}.pdf" }; return ResponseMessage(result); } catch (System.Exception ex) { return InternalServerError(ex); } } } }
1.4 测试服务
启动项目,访问http://localhost:[端口]/api/reports/generate?reportId=SampleReport,确认能正常返回PDF文件。
步骤2:在.NET Core 6中搭建反向代理
使用微软官方的YARP(Yet Another Reverse Proxy)实现转发,配置简单且功能完善。
2.1 创建.NET Core 6 Web API项目
新建ASP.NET Core Web API项目,框架选.NET 6。
2.2 安装YARP依赖
通过NuGet安装:
Microsoft.ReverseProxy
2.3 配置代理规则
在appsettings.json中添加反向代理配置:
{ "ReverseProxy": { "Routes": { "reportRoute": { "ClusterId": "crystalReportsCluster", "Match": { "Path": "/api/reports/{**catch-all}" } } }, "Clusters": { "crystalReportsCluster": { "Destinations": { "destination1": { "Address": "http://localhost:[你的4.8服务端口]" } } } } } }
2.4 启用反向代理
修改Program.cs,添加YARP服务和中间件:
var builder = WebApplication.CreateBuilder(args); // 添加反向代理服务 builder.Services.AddReverseProxy() .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy")); // 添加其他业务服务(如Swagger、身份验证等) builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // 启用Swagger(可选) if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); // 映射反向代理 app.MapReverseProxy(); app.MapControllers(); app.Run();
步骤3:关键配置与注意事项
3.1 跨域处理
如果.NET Core服务和4.8服务不在同一域名下,需在4.8服务中配置CORS:
在WebApiConfig.cs中添加:
using System.Web.Http.Cors; public static class WebApiConfig { public static void Register(HttpConfiguration config) { // 允许.NET Core服务域名跨域 var cors = new EnableCorsAttribute("http://localhost:[Core服务端口]", "*", "*"); config.EnableCors(cors); // 其他路由配置... } }
3.2 身份验证转发
如果.NET Core服务使用JWT等身份验证,需将令牌转发到4.8服务:
在YARP配置中添加请求头转发规则:
"Routes": { "reportRoute": { "ClusterId": "crystalReportsCluster", "Match": { "Path": "/api/reports/{**catch-all}" }, "Transforms": [ { "RequestHeader": "Authorization", "Set": "{RequestHeader:Authorization}" } ] } }
然后在4.8服务中实现对应的身份验证逻辑。
3.3 部署注意事项
- .NET Framework 4.8服务需部署在支持.NET Framework的IIS应用程序池中,确保Crystal Reports运行时已安装在服务器上。
- 两个服务需处于同一网络环境,确保.NET Core服务能访问到4.8服务的地址(生产环境建议使用内网地址或域名)。
- 添加日志记录:在两个服务中分别配置日志,方便排查转发过程中的错误。
内容的提问来源于stack exchange,提问作者Ledz3p

