我该如何在ASP.Net MVC中使用ReportViewer控件和RDLC报表?

5

我对ASP.Net MVC比较陌生。我的需求是在MVC中显示一个基于RDLC的报告。

我的需求以及我已经完成的工作如下:

我创建了一个ReportController,继承自APIController,其中有一个返回DataSet的方法。这个DataSet被发送到RDLC文件中。

为此,我已经完成了以下步骤,但无法使报告正常工作。

我创建了一个名为ReportParameter的模型类,如下所示:

public class ReportParameter 
{
    public DateTime DateFrom { get; set; }
    public DateTime DateTo { get; set; }
}

我有以下控制器ReportViewController:

public class ReportViewController : Controller
{
    static readonly ReportController ctrl = new ReportController();

    public ActionResult GenerateReport()
    {
        return View();
    }

    [HttpPost]
    public ActionResult GenerateReport(ReportParameterSalesOrder param)
    {
        if (ModelState.IsValid)
        {
            Helpers.DataLayer dl = new Helpers.DataLayer();
            if (param.DateFrom != null)
            {
                DateTime DateFrom = Convert.ToDateTime(param.DateFrom);
                DateTime DateTo = Convert.ToDateTime(param.DateTo);

                string fdate = DateFrom.ToString("yyyy/MM/dd");
                string tdate = DateTo.ToString("yyyy/MM/dd");

                Session["ReportSales"] = ctrl.ReportSales(param);
            }

            return Redirect(Url.Action("ViewReport", "ReportView"));
        }
        return View();
    }
    public ActionResult ViewReport()
    {
         return View();
    }

}

我有一个API控制器ReportController,它的对象已经在上面的ReportViewerController中创建,用于生成数据集并填充RDLC报表。API控制器如下:

public class ReportController : ApiController
{

    static readonly IReportRepository repository = new ReportRepository();

    [ActionName("ReportSales")]
    public DataSet ReportSales(ReportParameterSalesOrder paramSO)
    {
        DataSet item = repository.ReportSales(paramSO);
        if (item == null)
        {
            throw new HttpResponseException(HttpStatusCode.NotFound);
        }
        return item;
    }
}

我有两个视图 GenerateReport.aspx 和 ViewReport.aspx。下面是 GenerateReport.aspx 的代码:

<table style="width: 40%;">
              <tr>
                  <td class="style1">
                      <h3>
                          <asp:Label ID="Label1" runat="server" Text="From Date"></asp:Label></h3>
                  </td>
                  <td>
                      <%=@Html.EditorFor(a=> a.DateFrom, new{id="startDate",style="width:250px;"}) %>
                      <%=@Html.ValidationMessageFor(a => a.DateFrom)%>
                  </td>
              </tr>
              <tr>
                  <td class="style1">
                      <h3>
                          <asp:Label ID="Label2" runat="server" Text="To Date"></asp:Label></h3>
                  </td>
                  <td>
                      <%=@Html.EditorFor(a => a.DateTo, new { id = "ToDate", style = "width: 250px;" })%>
                      <%=@Html.ValidationMessageFor(a => a.DateTo)%>
                  </td>
              </tr>
              <tr>
                  <td class="style1">
                      &nbsp;
                  </td>
                  <td>
                      &nbsp;
                  </td>
              </tr>
              <tr>
                  <td class="style1">
                      &nbsp;
                  </td>
                  <td>
                      <input id="btnsearch" class="button" type="submit" value="Show" />
                  </td>
              </tr>
          </table>

下面是ViewReport.aspx的代码:
 <center style="width: 974px">
      <iframe id="myReport" width="100%" height="450px" src="ReportViewer.aspx">

        </iframe></center>

我已将 Dataset.xsd、rdlc 文件和 aspx 页面添加到了 rdlc 文件中。

但是我无法使它工作。我该如何显示报表,或者如何将从控制器接收到的数据集填充到报表中?


1
iframe 中使用的 ViewReport.aspx 需要是一个具有代码后台的良好传统 Web 表单 - 例如,在 ViewReport.aspx.cs 的代码后台中设置 DataSet。您可以通过 Session[] 变量从 MVC 控制器传递数据。 - StuartLC
ViewReport.aspx没有代码后台文件。你能再解释一下吗? - Nubicus
1个回答

5

背景
(我知道您已经了解此内容,但是对于未来的读者; -)

  • Microsoft ReportViewer控件需要ViewState和WebForms ScriptManagers才能正常工作,因此不适用于直接在MVC Views中使用。
  • 然而,在MVC项目中运行WebForms页面是可能的-因为它们在同一个AppDomain中运行,Session状态在MVC和WebForms之间共享。

详细情况
用于在MVC视图上呈现iframe中的ReportViewer控件的ViewReport.aspx页面将需要成为传统的asp.Net Web表单。

对于小型数据集,您可以在MVC Controller中获取报表数据,然后通过Session传递给WebForm。

但是,对于较大的数据集,建议您将参数传递给WebForm(如果它们不敏感,则甚至可以通过QueryString进行),然后WebForm代码后端需要获取数据集并将其绑定到ReportViewer。

在MVC侧,在MyController参数发布中:

    [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();
    }

用户在视图 MyController/GenerateReport 中输入报告参数后,您可以显示IFrame:

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

接下来,在您的MVC项目中添加一个WebForms页面/OldSkoolAspx/ReportViewer.aspx。在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文件中):
    <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,同样的技术也适用于报告服务器生成的报告(即使用 RDL 报告的 ReportViewer)。但是要注意的是,RDLC 和 RDL 都可能成为真正的SessionState占用者,请小心使用。

谢谢@StuartLC,你让我开心了。我一直在苦恼如何展示报告。 - Nubicus
嗨,但问题是当我的报告加载时,其他功能被阻止了,即使我尝试将asnycrender设置为true,所有功能也只能在报告完全加载后才能工作。有什么线索吗? - rohit singh
兄弟,这真的帮了我大忙。 :) - ksg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接