【发布时间】:2019-08-02 00:11:27
【问题描述】:
我正在构建一个 ASP.NET MVC3 Web 应用程序,我想使用水晶报表构建一些报表并使用水晶报表查看器显示它们。 我在网上搜索,但在 MVC3 Web 应用程序中没有找到任何可靠的方法。 您对如何操作有任何提示/想法吗?
【问题讨论】:
标签: asp.net-mvc-3 crystal-reports
我正在构建一个 ASP.NET MVC3 Web 应用程序,我想使用水晶报表构建一些报表并使用水晶报表查看器显示它们。 我在网上搜索,但在 MVC3 Web 应用程序中没有找到任何可靠的方法。 您对如何操作有任何提示/想法吗?
【问题讨论】:
标签: asp.net-mvc-3 crystal-reports
如果你不介意一些黑客攻击,它实际上很容易。 (假设 CR4VS2010)
首先在您的项目中添加一个 WebForms 页面,然后向其中添加水晶报表查看器控件。
验证它添加了对以下内容的引用:
CrystalDescisions.CrystalReports.Engine,
CrystalDescisions.ReportSource,
CrystalDescisions.Shared,
和CrystalDescisions.Web。
然后将 PageRoute 添加到您的应用程序中,指向新添加的页面。
最后,这是 BLANK 最大的痛点,您需要让 Crystal 的图像处理程序正常工作。有很多假设的方法,无论是在网上还是在 SO,都没有真正适合我,所以我求助于作弊:
public class CrystalImageHandlerController : Controller
{
//
// GET: /CrystalImageHandler.aspx
public ActionResult Index()
{
return Content("");
}
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
var handler = new CrystalDecisions.Web.CrystalImageHandler();
var app = (HttpApplication)filterContext.RequestContext.HttpContext.GetService(typeof(HttpApplication));
if (app == null) return;
handler.ProcessRequest(app.Context);
}
}
将此控制器的路由添加为 /CrystalReportsImageHandler.aspx,这是 CR 期望它的处理程序所在的位置。这也可以在Areas中使用,只需根据需要更改处理程序和页面路由即可。
请记住,您将无法使用 Razor 布局。因此,您需要借助其他方式来获得视觉连续性。 (我使用了 IFrame)
【讨论】:
在我们的项目中,我们直接以 PDF 格式返回报告。我们选择不在同一个项目中同时使用 WebForms 和 MVC,主要是因为保持代码库干净。
报表是针对手动创建的“哑”数据集生成的,数据由服务类填充,该服务类通过 NHibernate 检索所需的所有信息(因为我们使用了一层 ORM 持久性和 DB 抽象,Crystal Reports 必须不直接连接到数据库)。
如果您的项目不需要在浏览器中将报表显示为“预览模式”,这是我针对这种情况编写的自定义 ActionResult:
public class PdfReportResult : ViewResult
{
/// <summary>
/// Crystal Report filename
/// </summary>
public string reportFileName { get; set; }
/// <summary>
/// DataSet used in the report
/// </summary>
public DataSet reportDataSet { get; set; }
/// <summary>
/// Report parameters
/// </summary>
IDictionary<string, object> parameters { get; set; }
public PdfReportResult(string reportFileName, DataSet reportDataSet, IDictionary<string, object> parameters)
{
if (string.IsNullOrEmpty(reportFileName))
throw new ArgumentException("Report filename not informed", "reportFileName");
if (reportDataSet == null)
throw new ArgumentException("DataSet not informed", "reportDataSet");
if (parameters == null)
this.parameters = new Dictionary<string, object>();
else
this.parameters = parameters;
this.reportDataSet = reportDataSet;
this.reportFileName = reportFileName;
}
public PdfReportResult(string reportFileName, DataSet reportDataSet)
: this(reportFileName, reportDataSet, null)
{ }
public override void ExecuteResult(ControllerContext context)
{
if ( context == null )
throw new ArgumentNullException("context");
if ( string.IsNullOrEmpty(this.ViewName) )
this.ViewName = context.RouteData.GetRequiredString("action");
// Alias to make the code more legible
HttpResponseBase response = context.HttpContext.Response;
// Generating the report
using ( ReportDocument report = new ReportDocument() )
{
// Load the report
report.Load(context.HttpContext.Server.MapPath("~/Reports/" + reportFileName));
// Set the dataset
report.SetDataSource(reportDataSet);
// Set the parameters (if any)
foreach (var parameter in parameters)
report.SetParameterValue(parameter.Key, parameter.Value);
// Send back the PDF to the user
using ( MemoryStream oStream = (MemoryStream)report.ExportToStream(ExportFormatType.PortableDocFormat) )
{
response.Clear();
response.Buffer = true;
response.AddHeader("Content-Disposition", this.ViewName + ".pdf");
response.ContentType = "application/pdf";
response.BinaryWrite(oStream.ToArray());
response.End();
}
}
}
}
【讨论】:
由于水晶报表是一个服务器控件,我们需要一个网页/用户控件来显示报表。并且永远不要把这个 webform/user 控件放在 mvc 中的 views 文件夹中,你会在 CrViewer 中得到带有 404 的坏按钮。您还可以在 razor 视图中使用 Iframe 来显示报告。以下是一个工作模型[VS2010],请通过。
第 1 步:设置水晶报表
1.在网站根目录创建顶级文件夹。
2. 将您的 Crystal report.rpt 文件放入此文件夹
3. 将网页 (.aspx) 添加到此文件夹。此页面用作报表查看器页面。在此页面中添加 CrystalReportViewer 控件。
<div align="center" style="width:100%; height:100%;">
<CR:CrystalReportViewer ID="crViewer" runat="server" AutoDataBind="true" />
</div>
以下程序集注册将添加到 aspx 页面的顶部。
<%@ Register Assembly="CrystalDecisions.Web, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" Namespace="CrystalDecisions.Web" TagPrefix="CR" %>
检查 CrystalReportViewer 的版本。为此,请从 VS 侧边栏的工具箱中选择“选择项目”。将此版本与 aspx 页面顶部的 CrystalDecisions.Web 版本进行比较。如果两者相同,则保留它,否则更改与 CRViewer 相同的程序集注册版本。
进入网站根目录下的web.config文件;检查标签下以“CrystalDecisions”开头的程序集。更改与 CrystalReportViewer 版本相同的版本(此处为 Version=13.0.2000.0)。
第 2 步:设置控制器、动作和视图
1. 在报表控制器类中添加一个新动作。
2. 编写从数据库/文件加载数据的必要步骤。
3. 将数据设置为Session。
4. 不要为此操作添加视图。而是使用 Response.Redirect 方法。
public class ReportController : Controller
{
public ActionResult reportView(string id)
{
Session["ReportSource"] = GetdataFromDb();
Response.Redirect("~/Reports/WebForm1.aspx");
return View();
}
}
将页面加载事件添加到 .aspx 页面。
protected void Page_Load(object sender, EventArgs e)
{
CrystalDecisions.CrystalReports.Engine.ReportDocument report =
new CrystalDecisions.CrystalReports.Engine.ReportDocument();
report.Load(Server.MapPath("~/Reports/CR_report.rpt"));
report.SetDataSource(Session["ReportSource"]);
crViewer.ReportSource =report;
}
第 3 步:Global.asax 中的小技巧
1. 避免“Session state has created a session id, but cannot save it because response has been flushed by the application.”错误或“blank Crystal report page output” i> 在 Global.asax 中添加以下代码。
void Session_Start(object sender, EventArgs e)
{
string sessionId = Session.SessionID;
}
现在您可以调用 ReportController 中的 reportView() 操作来显示 Crystal Report。
祝你有美好的一天!
【讨论】: