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

时间:2010-11-09 19:50:15

标签: c# asp.net-mvc reportviewer reporting-services

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

8 个答案:

答案 0 :(得分:16)

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

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

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

答案 1 :(得分: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;
    }
}

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

更新:看起来如果您使用的是ASP.NET 4.0,most of this can be done automatically

答案 2 :(得分:11)

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

Project Site on GitHub

NuGet Package

答案 3 :(得分:10)

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

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

    如果您过去在设置ReportViewer控件方面做了很多工作,这可能是旧的,您可以跳到第2部分。

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

      Nuget - Microsoft.ReportViewer.WebForms

    2. Web.config处理程序 - 根据Web.config Settings for ReportViewer上的这篇文章和this SO question,您需要将以下内容添加到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>
      

      this question on duplicate keys,它通常最容易删除,然后重新添加网络服务器配置

    3. 修复损坏的图片请求 - 报告查看器中存在blank.gif images not loading已知缺陷,因此您可以将以下修复程序添加到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"));
          }
      }
      
    4. IgnoreRoute .axd - 如果还没有,请务必RouteConfig.cs中的allow ScriptResources

      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
      
    5. 添加ReportViewerPage.aspx - 添加一个包含ReportViewer控件实例的WebForm页面。为了工作,该控件需要找到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>
      
    6. Page_Load 上连接ReportViewer - 假设您已将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();
              }
          }
      }
      
    7. 查看报告 - 此时,您应该可以通过选择在浏览器中查看来查看自己的报告Ctrl + Shift + W

      View in Browser

    8. 问题2 - 混合WebForms和MVC

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

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

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

        这里是illustration of different routing formats in WebForms。这是一个简单的按钮点击事件,它会将帖子提交回父页面,并根据提交的事件数据在页面中引发相应的事件:

        ASP.NET WebForms - Postback

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

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

        从MVC 4.0+开始,您可以使用URL Routing with WebForms。通过添加MapPageRoute (请注意页面部分)将路由映射到物理文件,这与MVC很好地融为一体。请将以下内容添加到RouteConfig.cs

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

        当您导航到地址~/Reports/reportName时,报告将会运行。这可能是从控制器操作内部调用的,可能是某些用户输入的参数或web.config连接字符串。有很多ways to manage state in ASP.NETPass Values to ASP.NET Web Forms Pages。一种选择是在控制器中将会话和重定向中的信息存储起来:

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

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

        // 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];
        

        <强>赞成

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

        <强>缺点

        • 很难use an ASP Web Form with a Razor MVC Layout因此渲染会使用户脱离应用程序其余部分的流程。
        • 此外,报告值必须作为URL的一部分公开或通过会话间接传递(而不是直接在对象上保湿)。
      2. 选项2 - 在您网页上的.ascx内嵌套PartialView

        改编自How can I use a ReportViewer control with Razor?,您可以在PartialViews中使用.ascx个控件,只要它们从System.Web.Mvc.ViewUserControl继承。

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

        <%@ 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>
        
          

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

        在你背后的代码中,我需要将继承类型从System.Web.UI.UserControl替换为System.Web.Mvc.ViewUserControl

        Page_Init上,您需要将Context.Handler设置为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();
                }
            }
        }
        

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

        @Html.Partial("ReportViewerControl", Model)
        

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

        ReportSetup setup = (ReportSetup)Model;
        

        优点

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

        <强>缺点

      3. 进一步阅读

答案 4 :(得分:4)

这有点简单,需要一些修复才能将一些不错的东西传递给MVC中的视图

public ActionResult Index()
{
    /*Credentials of a user that has access to SSRS*/
    string userid = "UserId";
    string password = "MyPassword";
    string domain = "MyDomain";

    string reportURL="http://ServerName/ReportServer?/ReportsFolder/ReportName&Parameter=UserName&rs:Command=Render&rs:Format=PDF";

    NetworkCredential nwc = new NetworkCredential(userid, password, domain);

    WebClient client = new WebClient();
    client.Credentials = nwc;

    Byte[] pageData = client.DownloadData(reportURL);

    Response.ContentType = "application/pdf";
    Response.AddHeader("Content-Disposition", "attachment; filename=" + DateTime.Now);
    Response.BinaryWrite(pageData);
    Response.Flush();
    Response.End();

    //return View();
    }

答案 5 :(得分:3)

一个简单的解决方案是将一个iframe添加到您的MVC视图中,该视图可以从报表服务Web服务打开您想要的报表。 iframe将与报告服务中的组件完全一致。如果要将组件移动到MVC视图中,也可以动态控制iframe中用于url的参数(例如,使用ajax)。

虽然这有效,但您仍然需要登录网络报告服务(iframe将打开登录对话框)。对于IE,虽然使用您的Windows登录凭据,但这是“自动”完成的。

答案 6 :(得分:0)

通过使用Nuget进行安装,您可以使用ReportViewerForMvc在MVC中查看报告

Install-Package Microsoft.Report.Viewer -Version 11.0.0

Install-Package Microsoft.ReportViewer.Runtime.WebForms -Version 12.0.2402.15

Install-Package ReportViewerForMvc

如上所述安装了ReportViewer和其他必需的Nuget程序包后,在Visual Studio项目中添加一个新的Report.rdlc。

enter image description here

在上面创建的报告中添加数据集。rdlc

现在,在MVC中创建一个ActionMethod,它将从数据库中查询数据并返回报告

 SSRSInMVC.Report.Report ds = new SSRSInMVC.Report.Report();
    public ActionResult ReportStudent()
    {
        ReportViewer reportViewer = new ReportViewer();
        reportViewer.ProcessingMode = ProcessingMode.Local;
        reportViewer.SizeToReportContent = true;
        reportViewer.Width = Unit.Percentage(900);
        reportViewer.Height = Unit.Percentage(900);

        var connectionString = ConfigurationManager.ConnectionStrings["SSRSInMVC.Properties.Settings.StudentsConnectionString"].ConnectionString;


        SqlConnection conx = new SqlConnection(connectionString);
        SqlDataAdapter adp = new SqlDataAdapter("SELECT * FROM Student_details", conx);

        adp.Fill(ds, ds.Student_details.TableName);

        reportViewer.LocalReport.ReportPath = Request.MapPath(Request.ApplicationPath) + @"Report\Report1.rdlc";
        reportViewer.LocalReport.DataSources.Add(new ReportDataSource("DataSet1", ds.Tables[0]));


        ViewBag.ReportViewer = reportViewer;

        return View();
    }

在视图中,您具有以下代码

@using ReportViewerForMvc;
@{
   ViewBag.Title = "Report Student";
 }
 <br/>
<br />

   @Html.ReportViewer(ViewBag.ReportViewer as Microsoft.Reporting.WebForms.ReportViewer)

就这样,我们完成了。

参考:https://qawithexperts.com/article/asp.net/displaying-ssrs-sql-server-reporting-service-in-mvc-view/77

答案 7 :(得分:0)

只要有帮助,这些视频教程就是我发现很容易理解的内容。
您只需要容忍第一个视频中可怕的背景音乐即可。

SSRS 2019 Report in ASP Net MVC 5

How To Filter SSRS 2019 Report Using Parameter

我必须安装“ ReportViewerForMvc14 ”而不是“ ReportViewerForMvc ”(该视频中已使用),因为它不再可用。包装上的注释说与原始包装相同,只是进行了更新以与ReportViewer 14.0一起使用。