2013-03-14 41 views
11

Tôi đang làm việc trên ứng dụng MVC4 cần hiển thị báo cáo từ xa từ SSRS bằng ReportViewer. Với sự giúp đỡ từ diễn đàn này, tôi đã quản lý để có được trang để render theo MVC, nhưng callbacks sẽ không hoạt động (tải trang đầu tiên). Xuất báo cáo hoạt động tốt (và cung cấp cho tất cả các trang). Khi tôi kiểm tra trang, tôi nhận thấy các lỗi sau sau khi thay đổi trang:Làm cách nào để hiển thị trang aspx của ReportViewer từ xa trong MVC4?

của router Sys.WebForms.PageRequestManagerParserErrorException: Sys.WebForms.PageRequestManagerParserErrorException: Thông điệp nhận được từ máy chủ không thể được phân tích.

Tôi đã tìm thấy this article khi kết hợp MVC và biểu mẫu web nhưng đã xuất hiện lỗi thời vì không có thêm trang bố cục chính nào. Điều này liên quan đến nhưng không trùng lặp với How can I use a reportviewer control in an asp.net mvc 3 razor view? vì bài viết đó chỉ dành cho báo cáo cục bộ. Tôi đã thử thay đổi AsyncRendering thành true và false. Khi đúng, nó không tải chút nào. Bất kỳ đề xuất sẽ được đánh giá rất cao.

Cập nhật: Hành vi AsyncRendering appears to have changed giữa các phiên bản trước của Visual Studio.

+0

Nghĩ rằng giải pháp của bạn có thể được tìm thấy trong điều này có thể trùng lặp: [Làm cách nào để sử dụng điều khiển trình xem báo cáo trong chế độ xem asp.net mvc 3?] (Http: // stackoverflow.com/questions/6144513/how-can-i-sử dụng-a-reportviewer-control-in-an-asp-net-mvc-3-dao cạo-view) – Jeroen

+0

không trùng lặp - các giao dịch bài đăng khác chỉ với các báo cáo địa phương. Tôi đã sửa đổi câu hỏi một cách thích hợp – Elsimer

Trả lời

6

Cuối cùng, tôi đã phải bỏ cả câu trả lời ban đầu và tiêu chí gọi lại do những rủi ro bảo mật không được chấp nhận. Trong trường hợp của tôi, tôi đã viết mã điều khiển hiển thị báo cáo dưới dạng HTML thành một mảng byte và từ đó đến một FileContentResult mà MVC đã đủ loại để hiển thị dưới dạng một trang HTML tĩnh. Xuất dưới dạng PDF, Excel hoặc bất kỳ tùy chọn nào khác cuối cùng sẽ được triển khai theo phương pháp tương tự bằng cách thay đổi tham số Render từ HTML4.0 thành bất kỳ điều gì thích hợp (PDF, XLS) và loại MIME. Cách tiếp cận này làm việc với SQL Server 2008R2 và hơn thế nữa. Tôi đã không thử nó với các phiên bản trước của 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; 
} 
0

Tôi vẫn hy vọng có câu trả lời tốt hơn nhưng trong thời gian chờ đợi, giải pháp của tôi dường như đáp ứng các tiêu chí. Nó sử dụng Cửa sổ Web Kendo (vì vậy tôi cho rằng bạn có thể viết lý thuyết của riêng bạn bằng cách sử dụng jQuery). Tôi chưa sửa đổi nó để vượt qua các tham số, nhưng đó là một sự khởi đầu. Tôi cũng không bảo đảm hành động chuyển hướng, vì vậy hiện tại người dùng có thể xem nguồn, lấy URL từ tải jQuery, chuyển đến địa chỉ đó và nhận URL báo cáo cơ bản từ đó. Tôi sẽ xem xét đánh dấu nó như một ChildActionOnly hoặc một số phương tiện khác để bảo đảm rằng hành động chỉ có sẵn cho cửa sổ của tôi. Tôi cũng thấy rằng tôi có thể kết xuất báo cáo thành HTML4.0, nội dung trong FileResult và tải nội dung theo cách đó - nhưng sau đó báo cáo là HTML tĩnh.

Xem:

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

đoạn ReportController:

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 (code-behind):

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

Chỉ cần sử dụng IFRAME. Tạo một trang web hoặc thư mục ảo khác, tạo ứng dụng bằng cách sử dụng Biểu mẫu web và sau đó hiển thị các trang trình xem báo cáo của mình bên trong IFRAME trên ứng dụng MVC. Bạn có thể đặt tham số báo cáo bằng chuỗi truy vấn. Tôi đã nhiều lần đặt trình xem báo cáo vào các hệ thống khác nhau bằng cách này.

+0

vấn đề với phương pháp này là URL trong iframe hiển thị bằng cách xem nguồn, đây là một nguy cơ bảo mật. Nó sẽ giống như cho phép bất kỳ ai xem biên lai của mọi người với thông tin thẻ tín dụng chỉ bằng cách thay đổi URL – Elsimer

+0

Bạn có sử dụng xác thực không? Khi cả hai ứng dụng nằm trong cùng một miền, thì không có vấn đề gì. Nhưng khi ở khác nhau - để, nhìn ở đây ví dụ http://stackoverflow.com/questions/2056686/asp-net-forms-authentication-and-multiple-domains –

+0

SSRS được thiết lập để sử dụng xác thực cửa sổ (thông tin đăng nhập mạng). Ứng dụng của tôi sử dụng xác thực biểu mẫu và SimpleMembership để xác định báo cáo nào người dùng sẽ có quyền truy cập. Tuy nhiên, nếu tôi sử dụng iframe và chuyển hướng thì điều đó hoàn toàn bỏ qua bảo mật ứng dụng. Điều đó có nghĩa là tôi phải thực hiện bảo mật trên máy chủ từ xa, nằm ngoài phạm vi 'Chỉ cần sử dụng IFRAME'. – Elsimer

Các vấn đề liên quan