【问题标题】:How do I render a remote ReportViewer aspx page in MVC4?如何在 MVC4 中呈现远程 ReportViewer aspx 页面?
【发布时间】:2013-03-03 13:27:20
【问题描述】:

我正在开发一个需要使用 ReportViewer 从 SSRS 呈现远程报告的 MVC4 应用程序。在这个论坛的帮助下,我设法让页面在 MVC 下呈现,但回调不起作用(加载初始页面)。导出报告工作正常(并提供所有页面)。当我检查页面时,我注意到更改页面后出现以下错误:

未捕获的 Sys.WebForms.PageRequestManagerParserErrorException: Sys.WebForms.PageRequestManagerParserErrorException: 无法解析从服务器接收到的消息。

我发现this article 是在结合 MVC 和 Web 表单时发现的,但它似乎已经过时,因为没有更多的主布局页面。这与How can I use a reportviewer control in an asp.net mvc 3 razor view? 相关但不重复,因为该文章仅适用于本地报告。我尝试将 AsyncRendering 更改为 true 和 false。如果为真,则根本不加载。任何建议将不胜感激。

更新:Visual Studio 早期版本之间的异步渲染行为appears to have changed

【问题讨论】:

标签: asp.net-mvc-4 reporting-services webforms reportviewer


【解决方案1】:

我仍然希望得到更好的答案,但与此同时,我的解决方案似乎满足标准。它利用了 Kendo Web Window(所以我想你理论上可以使用 jQuery 编写自己的)。我还没有修改它来传递参数,但这是一个开始。我还没有保护重定向操作,因此用户目前可以查看源,从 jQuery 加载中获取 URL,转到该地址并从那里获取基础报告 URL。我将考虑将其标记为 ChildActionOnly 或其他确保该操作仅适用于我的窗口的方法。我还发现我可以将报告呈现为 HTML4.0,在 FileResult 中填充内容并以这种方式加载内容 - 但报告是静态 HTML。

查看:

    @(Html.Kendo().Grid(Model)
    .Name("IndexGrid")
    .Columns(col => 
    {
        col.Bound(c => c.SchoolYear);
        col.Bound(c => c.SubmissionTypeDesc);
        col.Bound(c => c.EntityDesc);
        col.Bound(c => c.SubmissionDate);
        col.Bound(c => c.UserName);
        col.Bound(c => c.Certified);
        col.Command(c => 
            {
                c.Custom("Edit")
                    .Text("View")
                    .Action("Edit", "Draft");
                c.Custom("Preview")
                    .Click("windowOpen");
                c.Custom("Certify")
                    .Action("Certify", "Draft");
                c.Custom("Download")
                    .Action("DumpExcel", "Draft");
            }
            ).Title("<b>Actions</b>")
            .HtmlAttributes(new { style = "width:200px;" });
    })
    .DataSource(ds => ds.Server()
        .Model(model => model.Id(pk => pk.snapshot_id))
        )
    .Sortable(sort => sort.Enabled(true).SortMode(GridSortMode.MultipleColumn).AllowUnsort(true))
    .Reorderable(reorder => reorder.Columns(true))
    .Groupable(group => group.Enabled(true))
    )
</article>

@(Html.Kendo().Window()
      .Name("window") //The name of the window is mandatory. It specifies the "id" attribute of the widget.
      .Title("Preliminary Report") //set the title of the window
      .LoadContentFrom("Redir", "Reports") //define the Action and Controller name
      .Visible(false)
      .Iframe(true)
      .Resizable()
      .Width(750)
      .Height(500)
      .Scrollable(false)
      .Draggable()
          .Actions(a =>
          {
              a.Refresh();
              a.Minimize();
              a.Maximize();
              a.Close();
          })

)
<script>
    function windowOpen(e) {
        e.preventDefault();
        var window = $("#window").data("kendoWindow");
        window.open();
    }
</script>

ReportController sn-p:

public ActionResult Redir()
{
    return RedirectPermanent("../ASPReports/ReportForm.aspx");
}

ReportForm.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="~/ASPReports/ReportForm.aspx.cs" Inherits="MyApp.Reports.ReportForm"%>

<%@ Register assembly="Microsoft.ReportViewer.WebForms, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" namespace="Microsoft.Reporting.WebForms" tagprefix="rsweb" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
</head>
<body>
    <form id="reportForm" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <div>
        <rsweb:ReportViewer ID="mainReportViewer" runat="server"  SizeToReportContent="true">
        </rsweb:ReportViewer>
    </div>
    </form>
</body>
</html>

ReportForm.aspx.cs(代码隐藏):

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        // credentials - could pull from config
        var userid = ""; 
        var password = "";
        var domain = "";

        IReportServerCredentials irsc = new CustomReportCredentials(userid, password, domain);
        mainReportViewer.ServerReport.ReportServerCredentials = irsc;

        //mainReportViewer.ServerReport.ReportServerUrl =
        //    new Uri(ConfigurationManager.AppSettings["ReportServerUrl"]);
        mainReportViewer.ServerReport.ReportServerUrl =
            new Uri("http://localhost/ReportServer");
        mainReportViewer.ServerReport.ReportPath = "Path";


        mainReportViewer.ProcessingMode = ProcessingMode.Remote;
        mainReportViewer.ShowParameterPrompts = false;
        mainReportViewer.ShowRefreshButton = false;
        mainReportViewer.ShowWaitControlCancelLink = false;
        mainReportViewer.ShowBackButton = false;
        mainReportViewer.ShowCredentialPrompts = false;
        var parametersCollection = new List<ReportParameter>();
        //parametersCollection.Add(new ReportParameter("Snapshot", "##", false));
        mainReportViewer.ServerReport.SetParameters(parametersCollection);
        mainReportViewer.ServerReport.Refresh();
    }
}

【讨论】:

    【解决方案2】:

    只需使用 IFRAME。创建另一个网站或虚拟目录,使用 Web 窗体创建应用程序,然后在 MVC 应用程序的 IFRAME 中显示他的报表查看器页面。您可以使用查询字符串设置报告参数。我曾多次使用这种方式将报表查看器放入不同的系统中。

    【讨论】:

    • 这种方式的问题是查看源代码可以看到iframe中的URL,存在安全隐患。这就像允许任何人通过更改 URL 来查看每个人的信用卡信息收据
    • 您使用身份验证吗?当两个应用程序在同一个域中时,就没有问题了。但是当不同时,请看这里例如stackoverflow.com/questions/2056686/…
    • SSRS 设置为使用 Windows 身份验证(网络凭据)。我的应用程序使用表单身份验证和 SimpleMembership 来确定用户应该有权访问哪些报告。但是,如果我使用 iframe 和重定向,则完全绕过应用程序安全性。这意味着我必须在远程服务器上实现安全性,这超出了“仅使用 IFRAME”的范围。
    【解决方案3】:

    最后,由于不可接受的安全风险,我最终不得不放弃我的原始答案和回调标准。在我的例子中,我编写了控制器代码,将报告作为 HTML 呈现为一个字节数组,然后从那里到一个 FileContentResult,MVC 可以很好地呈现为一个静态 HTML 页面。导出为 PDF、Excel 或任何其他选项最终将以类似的方法实现,方法是将 Render 参数从 HTML4.0 更改为任何合适的(PDF、XLS)和 MIME 类型。此方法适用于 SQL Server 2008R2 及更高版本。我没有在以前版本的 SQL Server 上尝试过。

    [OutputCache(Duration = 120, VaryByParam = "id")]
    public ActionResult ExportHTML(int id)
    {
        // we need to add code to check the user's access to the preliminary report.
        // Also need to consolidate code between ExportHTML and ExportPDF.
        var userid = <userid>;
        var password = <password>;
        var domain = <domain>;
        IReportServerCredentials irsc = new myApp.Models.CustomReportCredentials(userid,
            password, domain);
        var parametersCollection = new List<ReportParameter>();
        parametersCollection.Add(new ReportParameter("Snapshot", id.ToString(), false));
        ReportViewer rv = new Microsoft.Reporting.WebForms.ReportViewer();
        rv.ProcessingMode = ProcessingMode.Remote;
        rv.ServerReport.ReportServerCredentials = irsc;
        rv.ServerReport.ReportPath = <reportpath>;
        rv.ServerReport.ReportServerUrl = new Uri("http://localhost/ReportServer");
        rv.ServerReport.SetParameters(parametersCollection);
    
        rv.ServerReport.Refresh();
        byte[] streamBytes = null;
        string mimeType = "";
        string encoding = "";
        string filenameExtension = "";
        string[] streamids = null;
        Warning[] warnings = null;
    
        streamBytes = rv.ServerReport.Render("HTML4.0", null, out mimeType, out encoding,
                                             out filenameExtension, out stream ids,
                                             out warnings);
        var HTMLReport = File(streamBytes, "text/html");
        return HTMLReport;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-07
      • 2010-10-13
      • 1970-01-01
      • 2011-09-20
      • 1970-01-01
      相关资源
      最近更新 更多