在ASP.net MVC站点中查看SSRS报告

Dis*_*ile 51 c# asp.net-mvc reportviewer reporting-services

有没有办法在ASP.net MVC视图上放置SQL Server Reporting Services报表查看器控件?如果不是......实现这一目标的最佳方法是什么?

Mik*_*ner 16

不,不是在MVC视图中.但是,您可以拥有一个Web表单页面,其中包含与MVC站点混合的服务器控件.

嗯,只是谷歌搜索"混合asp.net mvc和网络表单"找到一些例子,谷歌质疑我是否是人类:)

无论如何,这里有一个链接 - http://www.packtpub.com/article/mixing-asp.net-webforms-and-asp.net-mvc - 那里有一些.我也是出于同样的原因在MVC网站上完成了这个 - 报告控制.

  • 是的,有 - 您使用的是什么版本的asp.net?如果是4.0,请查看ScottGu的博客 - http://weblogs.asp.net/scottgu/archive/2009/10/13/url-routing-with-asp-net-4-web-forms-vs-2010-and-净4-0-series.aspx.如果没有,我不确定 - 没有那样做. (2认同)

Bra*_*bby 14

不,如果将它放在MVC视图中,则ReportViewer控件将不起作用,因为它需要ViewState.您必须创建一个旧式Web表单并将ReportViewer放在那里.

我在一个项目中使用的解决方案是创建一个自定义路由处理程序,所以我仍然可以使用URL路由.路由处理程序将从RouteData集合中获取类似报告名称的参数,创建我的Web表单的实例,并通过公共属性将参数传递给它.Web表单将在Page_Load中读取这些内容并配置ReportViewer控件.

// Configure a route in Global.asax.cs that is handled by a ReportRouteHandler
routes.Add("ReportRoute", new Route("Reports/{reportName}",
                                    new ReportRouteHandler());

public class ReportRouteHandler : IRouteHandler {
    public IHttpHandler GetHttpHandler(RequestContext requestContext) {
        var reportName = requestContext.RouteData.Values["reportName"] as string;

        var webform = BuildManager
            .CreateInstanceFromVirtualPath("~/Path/To/ReportViewerWebForm.aspx",
                                           typeof(Page)) as ReportViewerWebForm;
        webform.ReportToShow = reportName;
        return webform;
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,如果你决定使用这种方法,这个代码只是一个起点.我创建的那个也在返回之前做了一些用户身份验证和参数验证.

更新:看起来如果你使用的是ASP.NET 4.0,大部分都可以自动完成!


Hay*_*iza 11

现在有一个MvcReportViewer助手.我们可以从NuGet获得它.

GitHub上的项目站点

NuGet包


Kyl*_*Mit 10

在MVC中实现SSRS ReportViewer控件包含两个问题:

  1. 最低限度,您需要为ReportViewer控件添加正确的依赖项,处理程序和配置(无论项目类型如何).
  2. 更棘手的障碍是混合WebForms和MVC.我们需要一种呈现和路由传入请求的方法,以便WebForms页面,控件和操作处理它们.

问题1 - 配置 ReportViewer

如果你在过去设置过ReportViewer控件已经做了很多工作,这可能是旧的,你可以跳到第2部分.

  1. 添加包/引用 - ReportViewer控件存在于Microsoft.ReportViewer.WebForms.dll.您可以通过添加Microsoft.ReportViewer.WebFormsnuget中的包来包含在您的项目中:

    Nuget  -  Microsoft.ReportViewer.WebForms

  2. Web.config处理程序 - 根据Web.config上的这篇文章ReportViewer的设置,这个SO问题,您需要将以下内容添加到您的web.config:

    <system.web>
      <httpHandlers>
        <add verb="*" path="Reserved.ReportViewerWebControl.axd" 
             type="Microsoft.Reporting.WebForms.HttpHandler,
                   Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral,
                   PublicKeyToken=b03f5f7f11d50a3a" />
      </httpHandlers>
    </system.web>
    <system.webServer>
      <handlers>
        <remove name="ReportViewerWebControlHandler" />
        <add name="ReportViewerWebControlHandler" preCondition="integratedMode"
             verb="*" path="Reserved.ReportViewerWebControl.axd" 
             type="Microsoft.Reporting.WebForms.HttpHandler, 
                   Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral,
                   PublicKeyToken=b03f5f7f11d50a3a"/>
      </handlers>
    </system.webServer>
    
    Run Code Online (Sandbox Code Playgroud)

    根据重复键的这个问题,通常最容易删除然后重新添加webserver配置

  3. 修复损坏的图像请求 - ReportViewer中存在已知的缺陷,blank.gif图像未加载,因此您可以将以下修复添加到您的global.asax.cs:

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        HttpRequest req = HttpContext.Current.Request;
        if (req.Url.PathAndQuery.StartsWith("/Reserved.ReportViewerWebControl.axd") &&
            !req.Url.ToString().ToLower().Contains("iteration") &&
            !String.IsNullOrEmpty(req.QueryString["ResourceStreamID"]) &&
            req.QueryString["ResourceStreamID"].ToLower().Equals("blank.gif"))
        {
            Context.RewritePath(String.Concat(req.Url.PathAndQuery, "&IterationId=0"));
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. IgnoreRoute个.axd -如果不是已经存在,一定要允许ScriptResourcesRouteConfig.cs:

    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
    Run Code Online (Sandbox Code Playgroud)
  5. 添加ReportViewerPage.aspx - 添加一个WebForm页面,该页面将包含ReportViewer控件的实例.为了工作,该控件需要找到一个ScriptManager控件并放在一个控件内<form runat="server" >.
    所以你的新.aspx页面应该是这样的:

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ReportViewerPage.aspx.cs" Inherits="MVCAppWithReportViewer.ReportViewerPage" %>
    <%@ Register TagPrefix="rsweb" Namespace="Microsoft.Reporting.WebForms" Assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" %>
    
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>Report Viewer</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <rsweb:ReportViewer ID="ReportViewer" runat="server" 
                                Height="100%" Width="100%" 
                                SizeToReportContent="True" ProcessingMode="Remote" />
            <asp:ScriptManager ID="ScriptManager1" runat="server" />
        </form>
    </body>
    </html>
    
    Run Code Online (Sandbox Code Playgroud)
  6. 连接ReportViewerPage_Load - 假设您已经将SSRS报告完全部署到报告服务器,该服务器可在以下地址获得:

    http://ReportServerName/Reports/Pages/Report.aspx?ItemPath=%2fCompany%2fClientReport

    然后,您的新WebForm页面中的代码隐藏应如下所示:

    public partial class ReportViewerPage : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                // confirm report properties (also setable in attributes)
                ReportViewer.ProcessingMode = ProcessingMode.Remote;
    
                // config variables
                var reportServer = "ReportServerName";
                var reportPath = "/Company/";
                var reportName = "ClientReport";    
    
                // report setup
                var serverReport = new ServerReport();
                serverReport = ReportViewer.ServerReport;
                serverReport.ReportServerUrl = new Uri($@"http://{reportServer}/ReportServer");
                serverReport.ReportPath = $@"{reportPath}{reportName}";
    
                // report input
                var parameters = new List<ReportParameter>();
                parameters.Add(new ReportParameter("User_uid", "1"));
                serverReport.SetParameters(parameters);
    
                // run report
                serverReport.Refresh();
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  7. 查看报告 - 此时,您应该可以通过选择在浏览器中查看Ctrl+ Shift+ 来查看自己的报告W

    在浏览器中查看

问题2 - 混合WebForms和MVC

首先,让我们快速剖析如何加载和随后更新这些控件之间的路由差异

  • MVC路由看起来像这样{controller}/{action}/{id},路由引擎将自动找到ControllerAction具有指定名称,并且传入请求将由该方法处理.在任何页面请求中,无论是来自页面加载,表单提交,按钮单击,锚点导航还是ajax调用,都会在URL中指定正在执行的确切方法{action}.

  • WebForms通过查找物理.aspx页面地址路由到代码,然后使用ViewState和PostData连接并触发该页面/控件上的事件.

    以下是WebForms中不同路由格式说明.这是一个简单的按钮点击事件,它会将帖子提交回父页面,并根据提交的事件数据在页面中引发相应的事件:

    ASP.NET WebForms  - 回发

这对我们的解决方案来说是一个非常大的限制.ReportViewer控制没有什么特别之处.它只是一组复杂的UserControl类,它们通过回发当前地址以及ViewState和事件信息来响应点击和其他输入事件.因此,无论报告的路由和导航如何,都需要持久保存到我们的MVC包装器中.

  1. 选项1 - 为.aspx页面添加路由

    从MVC 4.0+开始,您可以将URL Routing与WebForms一起使用.通过添加(注意Page部分)将路由映射到物理文件,这与MVC混合得很好.所以将以下内容添加到您的:MapPageRoute RouteConfig.cs

    routes.MapPageRoute(
        routeName: "ReportViewer",
        routeUrl: "ReportViewer/{reportName}",
        physicalFile: "~/ReportViewerPage.aspx"
    );
    
    Run Code Online (Sandbox Code Playgroud)

    导航到该地址时将运行该报告~/Reports/reportName.这可能是从控制器操作内部调用的,可能是某些用户输入的参数或web.config连接字符串.有很多方法可以在ASP.NET中管理状态并将值传递给ASP.NET Web窗体页.一种选择是在控制器中存储会话和重定向中的信息:

    HttpContext.Session[reportSetup.ReportName] = new ReportSetup() {ReportName = "ClientReport"}; //reportSetup;}
    return RedirectToRoute("ReportViewer", new { reportName = reportSetup.ReportName});
    
    Run Code Online (Sandbox Code Playgroud)

    然后,在.aspx页面内,您可以reportName从RouteData值和会话中的任何设置参数中获取:

    // get report name from route
    string reportName = Page.RouteData.Values["reportName"].ToString();
    
    // get model from session and clear
    ReportSetup setup = (ReportSetup)HttpContext.Current.Session[reportName];
    
    Run Code Online (Sandbox Code Playgroud)

    优点:

    • 大多数路由似乎默认工作,并且AJAX控件工作正常,因此您可以设置 AyncRendering=True

    缺点:

    • 使用带有Razor MVC布局的ASP Web窗体很难,因此渲染将使用户脱离应用程序其余部分的流程.
    • 此外,报告值必须作为URL的一部分公开或通过会话间接传递(而不是直接在对象上保湿).
  2. 选项2 - 嵌入页面.ascx内部PartialView

    改编自如何使用Razor的ReportViewer控件?,.ascx只要它们继承,就可以在PartialViews中使用控件System.Web.Mvc.ViewUserControl.

    创建一个名为的新Web窗体用户控件ReportViewerControl.ascx,如下所示:

    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ReportViewerControl.ascx.cs" Inherits="MVCAppWithReportViewer.ReportViewerControl" %>
    <%@ Register TagPrefix="rsweb" Namespace="Microsoft.Reporting.WebForms" Assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" %>
    
    <form id="form1" runat="server">
        <rsweb:ReportViewer ID="ReportViewer" runat="server" 
                            Height="100%" Width="100%"  
                            SizeToReportContent="True" ProcessingMode="Remote"
                            AsyncRendering="False" />
        <asp:ScriptManager ID="ScriptManager1" runat="server" 
                           EnablePartialRendering="false"  />
    </form>
    
    Run Code Online (Sandbox Code Playgroud)

    注意:您必须设置AsyncRendering="False"EnablePartialRendering="false"

    在后面的代码中,您需要将继承类型替换System.Web.UI.UserControlSystem.Web.Mvc.ViewUserControl.

    然后Page_Init,您需要设置Context.Handlerto,Page以便正确注册事件.

    所以ReportViewerControl.ascx.cs应该看起来像这样:

    public partial class ReportViewerControl : System.Web.Mvc.ViewUserControl
    {
        protected void Page_Init(object sender, EventArgs e)
        {
            // Required for report events to be handled properly.
            Context.Handler = Page;
        }
    
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                /* ... report setup ... */ 
                serverReport.Refresh();
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    要呈现报告,请将以下内容添加到控制器视图中:

    @Html.Partial("ReportViewerControl", Model)
    
    Run Code Online (Sandbox Code Playgroud)

    然后在ReportViewerControl.ascx.cs Page_Load事件中,您可以从ViewUserControl.Model属性中检索传入的模型,如下所示:

    ReportSetup setup = (ReportSetup)Model;
    
    Run Code Online (Sandbox Code Playgroud)

    优点:

    • 可以构建为master _layout.cshtml并在常规视图中使用
    • 可以直接传递模型

    缺点:

    • AsyncRendering必须设置为false,因此像分页和排序这样的交互会导致完整的页面刷新,有时候会变得很糟糕.布莱恩·哈特曼(Brian Hartman)有一个专门针对ReportViewer的博客,并讨论了AsyncRendering和所有随附的行李.

进一步阅读:


归档时间:

查看次数:

67913 次

最近记录:

6 年,3 月 前