如何在C#中实现JS版RetrieveEntityReq执行SSRS报表并获取Base64数据
解决C#中执行SSRS报表并转换为Base64 PDF附件的问题
我明白你现在的处境——原来在JS里用XMLHttpRequest发POST请求执行报表、转Base64当PDF附件的流程跑通了,但转到C#时踩了不少坑:RetrieveEntityRequest完全不对路子(它本来就是拿系统元数据的),HttpWebRequest返回OK却没内容,最后只能用发布报表后渲染的替代方案。下面我给你梳理正确的实现方式,顺便排查你之前的问题:
先说说你之前的坑点
RetrieveEntityRequest:这个是Dynamics 365这类平台用来检索实体元数据的API,和SSRS报表执行半毛钱关系都没有,方向完全错了HttpWebRequest返回空内容:大概率是请求端点、请求头、参数或者身份验证没配置对,SSRS的报表执行有特定的API格式,不是随便发个POST就行
1. 直接模拟JS逻辑的C#实现(调用SSRS执行API)
SSRS支持SOAP和REST两种API来执行报表,这里用SOAP方式和你JS里的POST逻辑最匹配:
using System; using System.IO; using System.Net; using System.Text; public string ExecuteReportToBase64Pdf(string reportServerUrl, string reportPath, string username, string password) { // SSRS的报表执行SOAP端点,一般是ReportExecution2005.asmx string executionEndpoint = $"{reportServerUrl.TrimEnd('/')}/ReportExecution2005.asmx"; // 构建SOAP请求体,指定报表路径、输出格式为PDF string soapBody = $@"<?xml version=""1.0"" encoding=""utf-8""?> <soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""> <soap:Body> <Render xmlns=""http://schemas.microsoft.com/sqlserver/reporting/2005/06/30/reportexecution/""> <Report>{reportPath}</Report> <Format>PDF</Format> <DeviceInfo></DeviceInfo> <Parameters></Parameters> <Credentials> <CredentialsXml><UserCredentials><UserName>{username}</UserName><Password>{password}</Password></UserCredentials></CredentialsXml> </Credentials> </Render> </soap:Body> </soap:Envelope>"; var request = (HttpWebRequest)WebRequest.Create(executionEndpoint); request.Method = "POST"; request.ContentType = "text/xml; charset=utf-8"; // 必须指定SOAPAction头,否则SSRS不认 request.Headers.Add("SOAPAction", "http://schemas.microsoft.com/sqlserver/reporting/2005/06/30/reportexecution/Render"); // 如果报表服务器用Windows身份验证,启用下面两行 // request.Credentials = new NetworkCredential(username, password); // request.PreAuthenticate = true; // 写入请求体 using (var writer = new StreamWriter(request.GetRequestStream())) { writer.Write(soapBody); } // 获取响应并处理PDF流 using (var response = (HttpWebResponse)request.GetResponse()) { if (response.StatusCode != HttpStatusCode.OK) { throw new InvalidOperationException($"请求失败:{response.StatusDescription}"); } using (var responseStream = response.GetResponseStream()) { if (responseStream == null) throw new InvalidOperationException("未获取到报表内容"); var memoryStream = new MemoryStream(); responseStream.CopyTo(memoryStream); // 转成Base64字符串 return Convert.ToBase64String(memoryStream.ToArray()); } } }
2. 解决你之前HttpWebRequest无内容的排查要点
- 端点正确性:确认用的是
ReportExecution2005.asmx而不是报表查看的页面URL - 请求头配置:SOAP请求必须加
SOAPAction头;如果用REST端点(比如/api/v2.0/reports/{reportPath}/Render),要加Accept: application/pdf - 身份验证:如果是Windows验证,一定要设置
NetworkCredential;如果是Forms验证,得先登录拿到Cookie再附在请求里 - 报表参数:如果报表需要参数,要在SOAP请求的
<Parameters>节点里添加,比如:<Parameters> <ParameterValue> <Name>StartDate</Name> <Value>2024-01-01</Value> </ParameterValue> </Parameters>
3. 关于你用的替代方案(发布报表后渲染)
这个方案其实也是可行的,而且可以用SSRS官方的客户端库简化代码,不需要自己拼SOAP请求:
using Microsoft.Reporting.WebForms; using System.IO; public string RenderPublishedReportToBase64(string reportServerUrl, string reportPath) { using var reportViewer = new ReportViewer(); reportViewer.ServerReport.ReportServerUrl = new Uri(reportServerUrl); reportViewer.ServerReport.ReportPath = reportPath; // 给报表传参数(如果需要) // reportViewer.ServerReport.SetParameters(new ReportParameter("EndDate", "2024-06-01")); // 直接渲染成PDF字节数组 byte[] pdfBytes = reportViewer.ServerReport.Render("PDF"); return Convert.ToBase64String(pdfBytes); }
注意:要使用这个方法,需要安装Microsoft.Reporting.WebForms的NuGet包,并且确保项目目标框架和库兼容。
内容的提问来源于stack exchange,提问作者AnkUser
相关产品推荐
相关产品推荐

