Как я могу использовать элемент управления reportviewer в виде бритвы asp.net mvc 3?
Я пытаюсь использовать элемент управления ReportViewer, в представлении бритвы, в рамках MVC 3. В онлайн документации рассказывается о перетаскивании. Любое предложение о том, как вставить его в представление.
8 ответов
Следующее решение работает только для одностраничных отчетов. Обратитесь к комментариям для более подробной информации.
ReportViewer - это серверный элемент управления, поэтому его нельзя использовать в виде бритвы. Однако вы можете добавить в приложение страницу просмотра ASPX, просмотреть пользовательский элемент управления или традиционную веб-форму, содержащую ReportViewer.
Вам нужно будет убедиться, что вы добавили соответствующий обработчик в ваш файл web.config.
Если вы используете страницу просмотра ASPX или просматриваете пользовательский элемент управления, вам нужно установить для параметра AsyncRendering значение false, чтобы отчет отображался правильно.
Обновить:
Добавлен еще пример кода. Обратите внимание, что в Global.asax не требуется никаких значительных изменений.
Web.Config
Мой закончился следующим образом:
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=152368
-->
<configuration>
<appSettings>
<add key="webpages:Version" value="1.0.0.0"/>
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="Microsoft.ReportViewer.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
</assemblies>
</compilation>
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
<pages>
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages"/>
</namespaces>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true"/>
<handlers>
<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>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
контроллер
Действия контроллера очень просты.
В качестве бонуса действие File() возвращает вывод "TestReport.rdlc" в виде файла PDF.
using System.Web.Mvc;
using Microsoft.Reporting.WebForms;
...
public class PDFController : Controller
{
public ActionResult Index()
{
return View();
}
public FileResult File()
{
ReportViewer rv = new Microsoft.Reporting.WebForms.ReportViewer();
rv.ProcessingMode = ProcessingMode.Local;
rv.LocalReport.ReportPath = Server.MapPath("~/Reports/TestReport.rdlc");
rv.LocalReport.Refresh();
byte[] streamBytes = null;
string mimeType = "";
string encoding = "";
string filenameExtension = "";
string[] streamids = null;
Warning[] warnings = null;
streamBytes = rv.LocalReport.Render("PDF", null, out mimeType, out encoding, out filenameExtension, out streamids, out warnings);
return File(streamBytes, mimeType, "TestReport.pdf");
}
public ActionResult ASPXView()
{
return View();
}
public ActionResult ASPXUserControl()
{
return View();
}
}
ASPXView.apsx
ASPXView выглядит следующим образом.
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>
<!DOCTYPE html>
<html>
<head runat="server">
<title>ASPXView</title>
</head>
<body>
<div>
<script runat="server">
private void Page_Load(object sender, System.EventArgs e)
{
ReportViewer1.LocalReport.ReportPath = Server.MapPath("~/Reports/TestReport.rdlc");
ReportViewer1.LocalReport.Refresh();
}
</script>
<form id="Form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<rsweb:reportviewer id="ReportViewer1" runat="server" height="500" width="500" AsyncRendering="false"></rsweb:reportviewer>
</form>
</div>
</body>
</html>
ViewUserControl1.ascx
Пользовательский элемент управления ASPX выглядит следующим образом:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>
<script runat="server">
private void Page_Load(object sender, System.EventArgs e)
{
ReportViewer1.LocalReport.ReportPath = Server.MapPath("~/Reports/TestReport.rdlc");
ReportViewer1.LocalReport.Refresh();
}
</script>
<form id="Form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<rsweb:ReportViewer ID="ReportViewer1" runat="server" AsyncRendering="false"></rsweb:ReportViewer>
</form>
ASPXUserControl.cshtml
Бритва зрения. Требуется ViewUserControl1.ascx.
@{
ViewBag.Title = "ASPXUserControl";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>ASPXUserControl</h2>
@Html.Partial("ViewUserControl1")
Рекомендации
Это простая задача. Вы можете выполнить следующие шаги.
- Создайте папку в своем решении и назовите ее " Отчеты".
- Добавьте веб-форму ASP.Net и назовите ее ReportView.aspx.
Создайте Class ReportData и добавьте его в папку " Отчеты ". Добавьте следующий код в класс.
public class ReportData { public ReportData() { this.ReportParameters = new List<Parameter>(); this.DataParameters = new List<Parameter>(); } public bool IsLocal { get; set; } public string ReportName { get; set; } public List<Parameter> ReportParameters { get; set; } public List<Parameter> DataParameters { get; set; } } public class Parameter { public string ParameterName { get; set; } public string Value { get; set; } }
Добавьте другой класс и назовите его ReportBasePage.cs. Добавьте следующий код в этот класс.
public class ReportBasePage : System.Web.UI.Page { protected ReportData ReportDataObj { get; set; } protected override void OnInit(EventArgs e) { base.OnInit(e); if (HttpContext.Current != null) if (HttpContext.Current.Session["ReportData"] != null) { ReportDataObj = HttpContext.Current.Session["ReportData"] as ReportData; return; } ReportDataObj = new ReportData(); CaptureRouteData(Page.Request); } private void CaptureRouteData(HttpRequest request) { var mode = (request.QueryString["rptmode"] + "").Trim(); ReportDataObj.IsLocal = mode == "local" ? true : false; ReportDataObj.ReportName = request.QueryString["reportname"] + ""; string dquerystr = request.QueryString["parameters"] + ""; if (!String.IsNullOrEmpty(dquerystr.Trim())) { var param1 = dquerystr.Split(','); foreach (string pm in param1) { var rp = new Parameter(); var kd = pm.Split('='); if (kd[0].Substring(0, 2) == "rp") { rp.ParameterName = kd[0].Replace("rp", ""); if (kd.Length > 1) rp.Value = kd[1]; ReportDataObj.ReportParameters.Add(rp); } else if (kd[0].Substring(0, 2) == "dp") { rp.ParameterName = kd[0].Replace("dp", ""); if (kd.Length > 1) rp.Value = kd[1]; ReportDataObj.DataParameters.Add(rp); } } } } }
Добавьте ScriptManager на страницу ReportView.aspx. Теперь добавьте средство просмотра отчетов на страницу. В средстве просмотра отчетов установите свойство AsyncRendering = "false". Код приведен ниже.
<rsweb:ReportViewer ID="ReportViewerRSFReports" runat="server" AsyncRendering="false" Width="1271px" Height="1000px" > </rsweb:ReportViewer>
Добавьте два NameSpace в ReportView.aspx.cs
using Microsoft.Reporting.WebForms; using System.IO;
Измените System.Web.UI.Page на ReportBasePage. Просто замените код, используя следующее.
public partial class ReportView : ReportBasePage { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { RenderReportModels(this.ReportDataObj); } } private void RenderReportModels(ReportData reportData) { // This is the Data Access Layer from which a method is called to fill data to the list. RASolarERPData dal = new RASolarERPData(); List<ClosingInventoryValuation> objClosingInventory = new List<ClosingInventoryValuation>(); // Reset report properties. ReportViewerRSFReports.Height = Unit.Parse("100%"); ReportViewerRSFReports.Width = Unit.Parse("100%"); ReportViewerRSFReports.CssClass = "table"; // Clear out any previous datasources. this.ReportViewerRSFReports.LocalReport.DataSources.Clear(); // Set report mode for local processing. ReportViewerRSFReports.ProcessingMode = ProcessingMode.Local; // Validate report source. var rptPath = Server.MapPath(@"./Report/" + reportData.ReportName +".rdlc"); //@"E:\RSFERP_SourceCode\RASolarERP\RASolarERP\Reports\Report\" + reportData.ReportName + ".rdlc"; //Server.MapPath(@"./Report/ClosingInventory.rdlc"); if (!File.Exists(rptPath)) return; // Set report path. this.ReportViewerRSFReports.LocalReport.ReportPath = rptPath; // Set report parameters. var rpPms = ReportViewerRSFReports.LocalReport.GetParameters(); foreach (var rpm in rpPms) { var p = reportData.ReportParameters.SingleOrDefault(o => o.ParameterName.ToLower() == rpm.Name.ToLower()); if (p != null) { ReportParameter rp = new ReportParameter(rpm.Name, p.Value); ReportViewerRSFReports.LocalReport.SetParameters(rp); } } //Set data paramater for report SP execution objClosingInventory = dal.ClosingInventoryReport(this.ReportDataObj.DataParameters[0].Value); // Load the dataSource. var dsmems = ReportViewerRSFReports.LocalReport.GetDataSourceNames(); ReportViewerRSFReports.LocalReport.DataSources.Add(new ReportDataSource(dsmems[0], objClosingInventory)); // Refresh the ReportViewer. ReportViewerRSFReports.LocalReport.Refresh(); } }
Добавьте папку в папку отчетов и назовите ее " Отчет". Теперь добавьте отчет RDLC в папку Reports/Report и назовите его ClosingInventory.rdlc.
Теперь добавьте контроллер и назовите его ReportController. В контроллере добавьте следующий метод действия.
public ActionResult ReportViewer() { ViewData["reportUrl"] = "../Reports/View/local/ClosingInventory/"; return View(); }
Чтобы добавить страницу просмотра, нажмите на контроллер Report Viewer. Назовите страницу просмотра Report Viewer.cshtml. Добавьте следующий код на страницу просмотра.
@using (Html.BeginForm("Login")) { @Html.DropDownList("ddlYearMonthFormat", new SelectList(ViewBag.YearMonthFormat, "YearMonthValue", "YearMonthName"), new { @class = "DropDown" }) Stock In Transit: @Html.TextBox("txtStockInTransit", "", new { @class = "LogInTextBox" }) <input type="submit" onclick="return ReportValidationCheck();" name="ShowReport" value="Show Report" /> }
Добавьте Iframe. Установите свойство Iframe следующим образом
frameborder="0" width="1000"; height="1000"; style="overflow:hidden;" scrolling="no"
Добавить следующий JavaScript для зрителя.
function ReportValidationCheck() { var url = $('#hdUrl').val(); var yearmonth = $('#ddlYearMonthFormat').val(); var stockInTransit = $('#txtStockInTransit').val() if (stockInTransit == "") { stockInTransit = 0; } if (yearmonth == "0") { alert("Please Select Month Correctly."); } else { //url = url + "dpSpYearMonth=" + yearmonth + ",rpYearMonth=" + yearmonth + ",rpStockInTransit=" + stockInTransit; url = "../Reports/ReportView.aspx?rptmode=local&reportname=ClosingInventory¶meters=dpSpYearMonth=" + yearmonth + ",rpYearMonth=" + yearmonth + ",rpStockInTransit=" + stockInTransit; var myframe = document.getElementById("ifrmReportViewer"); if (myframe !== null) { if (myframe.src) { myframe.src = url; } else if (myframe.contentWindow !== null && myframe.contentWindow.location !== null) { myframe.contentWindow.location = url; } else { myframe.setAttribute('src', url); } } } return false; }
В файле Web.config добавьте следующий ключ в раздел appSettings.
add key="UnobtrusiveJavaScriptEnabled" value="true"
В разделе обработчики system.web добавьте следующий ключ
add verb="*" path="Reserved.ReportViewerWebControl.axd" type = "Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
Измените свой источник данных на свой. Это решение очень простое, и я думаю, что оно понравится всем.
Вот полное решение для непосредственной интеграции элемента управления просмотра отчетов (а также любого серверного элемента управления asp.net) в представление MVC .aspx, которое также будет работать с отчетом с несколькими страницами (в отличие от ответа Адриана Томана) и с AsyncRendering установлен в true (на основе "Pro ASP.NET MVC Framework" Стива Сандерсона).
Что нужно сделать, это в основном:
Добавить форму с помощью runat = "server"
Добавьте элемент управления (для элементов управления просмотра отчетов он также может иногда работать даже с AsyncRendering="True", но не всегда, так что проверьте в вашем конкретном случае)
Добавьте сценарии на стороне сервера с помощью тегов сценария с runat = "server"
Переопределите событие Page_Init с помощью кода, показанного ниже, чтобы включить использование PostBack и Viewstate.
Вот демонстрация:
<form ID="form1" runat="server">
<rsweb:ReportViewer ID="ReportViewer1" runat="server" />
</form>
<script runat="server">
protected void Page_Init(object sender, EventArgs e)
{
Context.Handler = Page;
}
//Other code needed for the report viewer here
</script>
Конечно, рекомендуется полностью использовать подход MVC, подготовив все необходимые данные в контроллере, а затем передав их в представление через ViewModel.
Это позволит повторно использовать вид!
Однако это касается только данных, которые необходимы для каждой публикации назад, или даже если они требуются только для инициализации, если они не интенсивны, и данные также не должны зависеть от значений PostBack и ViewState.
Однако даже интенсивное использование данных иногда может быть инкапсулировано в лямбда-выражение и затем передано в представление для вызова там.
Пара замечаний, хотя:
- Делая это, представление по существу превращается в веб-форму со всеми ее недостатками (то есть Postbacks и возможностью переопределения элементов управления не Asp.NET)
- Хак переопределения Page_Init недокументирован, и он может быть изменен в любое время
Я использую ASP.NET MVC3 с SSRS 2008, и мне не удалось заставить @Adrian's работать на 100% для меня при попытке получить отчеты с удаленного сервера.
Наконец, я обнаружил, что мне нужно изменить метод Page_Load в ViewUserControl1.ascx, чтобы он выглядел так:
ReportViewer1.ProcessingMode = ProcessingMode.Remote;
ServerReport serverReport = ReportViewer1.ServerReport;
serverReport.ReportServerUrl = new Uri("http://<Server Name>/reportserver");
serverReport.ReportPath = "/My Folder/MyReport";
serverReport.Refresh();
Мне не хватало ProcessingMode.Remote.
Рекомендации:
http://msdn.microsoft.com/en-us/library/aa337091.aspx - ReportViewer
В NuGet есть помощник MvcReportViewer.
http://www.nuget.org/packages/MvcReportViewer/
И это детали:
https://github.com/ilich/MvcReportViewer
Я использую это. Работает отлично.
Вам придется не только использовать страницу asp.net, но и
Если при использовании Entity Framework или LinqToSql (если используются частичные классы) данные перемещаются в отдельный проект, дизайнер отчетов не может видеть классы.
Переместите отчеты в другой проект /dll, VS10 содержит ошибки, когда проекты asp.net не могут видеть источники данных объектов в веб-приложениях. Затем направьте отчеты из dll на страницу aspx ваших mvc проектов.
Это относится к проектам mvc и webform. Использование отчетов SQL в локальном режиме не является приятным опытом разработки. Также следите за памятью вашего веб-сервера при экспорте больших отчетов. Reportviewer/export очень плохо разработан.
Можно получить отчет SSRS для отображения на странице MVC без использования iFrames или страницы aspx.
Основная часть работы объясняется здесь:
Ссылка объясняет, как создать веб-службу и метод действия MVC, который позволит вам вызывать службу отчетов и отображать результаты веб-службы в виде файла Excel. С небольшим изменением кода в примере вы можете отобразить его как HTML.
Все, что вам нужно сделать, это использовать кнопку для вызова функции JavaScript, которая вызывает AJAX-вызов вашего действия MVC, который возвращает HTML-код отчета. Когда вызов AJAX возвращается с HTML, просто замените div этим HTML.
Мы используем AngularJS, поэтому мой пример ниже в этом формате, но это может быть любая функция JavaScript
$scope.getReport = function()
{
$http({
method: "POST",
url: "Report/ExportReport",
data:
[
{ Name: 'DateFrom', Value: $scope.dateFrom },
{ Name: 'DateTo', Value: $scope.dateTo },
{ Name: 'LocationsCSV', Value: $scope.locationCSV }
]
})
.success(function (serverData)
{
$("#ReportDiv").html(serverData);
});
};
А метод действия - в основном взят по вышеуказанной ссылке...
[System.Web.Mvc.HttpPost]
public FileContentResult ExportReport([FromBody]List<ReportParameterModel> parameters)
{
byte[] output;
string extension, mimeType, encoding;
string reportName = "/Reports/DummyReport";
ReportService.Warning[] warnings;
string[] ids;
ReportExporter.Export(
"ReportExecutionServiceSoap"
new NetworkCredential("username", "password", "domain"),
reportName,
parameters.ToArray(),
ExportFormat.HTML4,
out output,
out extension,
out mimeType,
out encoding,
out warnings,
out ids
);
//-------------------------------------------------------------
// Set HTTP Response Header to show download dialog popup
//-------------------------------------------------------------
Response.AddHeader("content-disposition", string.Format("attachment;filename=GeneratedExcelFile{0:yyyyMMdd}.{1}", DateTime.Today, extension));
return new FileContentResult(output, mimeType);
}
В результате вы получаете возможность передавать параметры на сервер отчетов SSRS, который возвращает отчет, который вы отображаете в виде HTML. Все появляется на одной странице. Это лучшее решение, которое я смог найти