且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何将 RDLC 报告与 ASP.Net MVC 中的 ReportViewer 控件一起使用?

更新时间:2023-11-29 23:25:22

背景
(我知道你知道这一点,但对于未来的读者;-)

Background
(I know you know this, but for future readers ;-)

  • Microsoft ReportViewer 控件需要 ViewState 和 WebForms ScriptManagers 才能正常工作,因此不适合直接在 MVC 视图中使用.
  • 然而,可以在 MVC 项目中运行 WebForms 页面 - 因为它们运行在同一个 AppDomain 中,Session 状态在 MVC 和 WebForms 之间共享.
  • The Microsoft ReportViewer Control requires ViewState and WebForms ScriptManagers to work correctly, and as such isn't suited for direct use in MVC Views.
  • It is however possible to run a WebForms page in an MVC Project - as they run in the same AppDomain, Session state is shared between MVC and WebForms.

详细
用于在 MVC 视图上的 iframe 中呈现 ReportViewer 控件的 ViewReport.aspx 页面需要是一个很好的老式 asp.Net Web 表单.

In Detail
The ViewReport.aspx page used to render the ReportViewer control in the iframe on the MVC View will need to be a good old fashioned asp.Net web form.

对于小数据集,您可以在 MVC 控制器中获取报告数据,然后在 Session 中将其传递到 WebForm.

For small data sets, you can fetch the report data in the MVC Controller and then pass this in Session across to the WebForm.

但是,对于较大的数据集,我建议您改为将参数传递到会话中的 WebForm(或者甚至通过 QueryString,如果它们不敏感),然后后面的 WebForm 代码需要获取数据集并将其绑定到 ReportViewer.

However, for larger data sets, I would recommend that you instead pass the Parameters across to the WebForm in Session (or even via the QueryString, if they aren't sensitive), and then the WebForm code behind would need to fetch the data set and bind it to the ReportViewer.

在 MVC 端,在 MyController 参数中:

On the MVC Side, in the MyController parameter post:

    [HttpPost]
    public ActionResult GenerateReport(string param1, int param2)
    {
        // Obviously you apply the parameters as predicates and hit the real database
        Session["ReportData"] = FakeDatabaseData;
        ViewBag.ShowIFrame = true;
        return View();
    }

您可以在用户输入 ReportParameters 后在视图上显示 IFrame,MyController/GenerateReport:

You can show the IFrame once the ReportParameters have been typed in by the user, on the View, MyController/GenerateReport:

<iframe src='<%= Url.Content("~/OldSkoolAspx/ReportViewer.aspx") %>' width="100%" height="450px"></iframe>

然后将 WebForms 页面 /OldSkoolAspx/ReportViewer.aspx 添加到您的 MVC 项目.在 ReportViewer.aspx.cs 后面的代码中:

Then add a WebForms page /OldSkoolAspx/ReportViewer.aspx to your MVC project. In the code behind ReportViewer.aspx.cs:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            var reportDataSource = new ReportDataSource
            {
                // Must match the DataSource in the RDLC
                Name = "SomeReportDataSet",
                Value = Session["ReportData"]
            };
            ReportViewer1.LocalReport.DataSources.Add(reportDataSource);
            ReportViewer1.DataBind();
        }
    }

然后在 WebForms ReportViewer.aspx 前端,添加控件(推荐使用工具箱,这样所有必需的引用都会添加到 web.config 中):

And in the WebForms ReportViewer.aspx front end, add the control (recommend use the toolbox, so all the requisite references get added to the web.config):

    <rsweb:ReportViewer ID="ReportViewer1" runat="server" Font-Names="Verdana" Font-Size="8pt" WaitMessageFont-Names="Verdana" WaitMessageFont-Size="14pt" Width="476px">
        <LocalReport ReportPath="MyReport.rdlc">
        </LocalReport>
    </rsweb:ReportViewer>
    <asp:ScriptManager runat="server" ID="SillyPrerequisite"></asp:ScriptManager>

这里有很多变动的部分,所以我上传了一个演示项目到这里的 GitHub

There's a lot of moving parts here, so I've uploaded a demo project to GitHub over here

请注意,相同的技术也适用于报表服务器生成的报表(即使用带有 .RDL 报表的 ReportViewer).但是请注意 RDLC 和 RDL 都可能是真实的 SessionState

Note that the same technique will also work for Report Server generated reports (i.e. using ReportViewer with .RDL reports). Do however be wary that both RDLC and RDL can be real SessionState hogs