studio - ¿Cómo puedo usar un control reportviewer en una vista de navaja asp.net mvc 3?
reports in mvc 4 (8)
Estoy tratando de usar un control de reportero, dentro de una vista de máquina de afeitar, en el marco de mvc 3. La documentación en línea habla de arrastrar y soltar. Cualquier sugerencia sobre cómo insertarlo en la vista.
Aquí está la solución completa para integrar directamente un control de visor de informes (así como cualquier control del lado del servidor asp.net) en una vista MVC .aspx, que también funcionará en un informe con varias páginas (a diferencia de la respuesta de Adrian Toman) y con AsyncRendering establecido en true, (basado en "Pro ASP.NET MVC Framework" de Steve Sanderson).
Lo que uno necesita hacer es básicamente:
Agregue un formulario con runat = "server"
Agregue el control, (para los controles del visor de informes también a veces puede funcionar incluso con AsyncRendering = "Verdadero" pero no siempre, así que controle en su caso específico)
Agregue secuencias de comandos del lado del servidor mediante el uso de etiquetas de script con runat = "server"
Reemplazar el evento Page_Init con el código que se muestra a continuación, para permitir el uso de PostBack y Viewstate
Aquí hay una demostración:
<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>
Por supuesto, se recomienda utilizar por completo el enfoque MVC, preparando todos los datos necesarios en el controlador y luego pasándolos a la vista a través del ViewModel.
¡Esto permitirá la reutilización de la Vista!
Sin embargo, esto solo se aplica a los datos que se necesitan para cada publicación posterior, o incluso si solo son necesarios para la inicialización si no son intensivos en datos, y los datos tampoco deben depender de los valores de PostBack y ViewState.
Sin embargo, incluso los datos intensivos a veces se pueden encapsular en una expresión lambda y luego se pasan a la vista para llamar allí.
Un par de notas sin embargo:
- Al hacer esto, la vista esencialmente se convierte en un formulario web con todos sus inconvenientes (es decir, los Postbacks, y la posibilidad de que los controles que no sean Asp.NET sean reemplazados)
- El hack de Over_ing Page_Init no está documentado, y está sujeto a cambios en cualquier momento
Es posible obtener un informe SSRS para que aparezca en una página MVC sin utilizar iFrames o una página aspx.
La mayor parte del trabajo se explica aquí:
El enlace explica cómo crear un servicio web y un método de acción MVC que le permitirá llamar al servicio de informes y presentar el resultado del servicio web como un archivo de Excel. Con un pequeño cambio en el código del ejemplo, puede representarlo como HTML.
Todo lo que necesita hacer entonces es usar un botón para llamar a una función de JavaScript que hace una llamada AJAX a su acción MVC que devuelve el código HTML del informe. Cuando la llamada AJAX retorna con el HTML simplemente reemplaza un div con este HTML.
Usamos AngularJS así que mi ejemplo a continuación está en ese formato, pero podría ser cualquier función de 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);
});
};
Y el Método de acción: principalmente tomado del enlace de arriba ...
[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);
}
Por lo tanto, el resultado es que puede pasar parámetros a un servidor de informes SSRS que devuelve un informe que representa como HTML. Todo aparece en una página. Esta es la mejor solución que pude encontrar
Esta es una tarea simple. Puedes seguir los siguientes pasos.
- Cree una carpeta en su solución y asígnele el nombre Informes .
- Agregue un formulario web ASP.Net y asígnele el nombre ReportView.aspx
Cree un Informe de clase y agréguelo a la carpeta Informes . Agregue el siguiente código a la clase.
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; } }
Agregue otra clase y asígnele el nombre ReportBasePage.cs . Agregue el siguiente código en esta clase.
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); } } } } }
Agregue ScriptManager a la página ReportView.aspx . Ahora agregue un Visor de informes a la página. En el visor de informes establezca la propiedad AsyncRendering = "false" . El código se da a continuación.
<rsweb:ReportViewer ID="ReportViewerRSFReports" runat="server" AsyncRendering="false" Width="1271px" Height="1000px" > </rsweb:ReportViewer>
Agregue dos NameSpace en ReportView.aspx.cs
using Microsoft.Reporting.WebForms; using System.IO;
Cambie System.Web.UI.Página a ReportBasePage . Simplemente reemplace su código usando lo siguiente.
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(); } }
Agregue una carpeta a la carpeta Informes y asígnele el nombre Informe . Ahora agregue un informe RDLC a la carpeta Reports / Report y asígnele el nombre ClosingInventory.rdlc .
Ahora agregue un controlador y asígnele el nombre ReportController . En el controlador, agregue el siguiente método de acción.
public ActionResult ReportViewer() { ViewData["reportUrl"] = "../Reports/View/local/ClosingInventory/"; return View(); }
Agregue una página de vista, haga clic en el Controlador ReportViewer . Denomine la página de vista ReportViewer.cshtml . Agregue el siguiente código a la página de visualización.
@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" /> }
Agregar un iframe Establezca la propiedad del Iframe de la siguiente manera
frameborder="0" width="1000"; height="1000"; style="overflow:hidden;" scrolling="no"
Agregue el siguiente JavaScript al visor.
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; }
Archivo Web.config agregue la siguiente clave a la sección appSettings
add key="UnobtrusiveJavaScriptEnabled" value="true"
En la sección de controladores de system.web agregue la siguiente clave
add verb="*" path="Reserved.ReportViewerWebControl.axd" type = "Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
Cambie su fuente de datos a la suya. Esta solución es muy simple y creo que todos la disfrutarán.
Estoy usando ASP.NET MVC3 con SSRS 2008 y no pude lograr que @ Adrian''s trabaje al 100% cuando trato de obtener informes de un servidor remoto.
Finalmente, descubrí que necesitaba cambiar el método Page_Load en ViewUserControl1.ascx para que se vea así:
ReportViewer1.ProcessingMode = ProcessingMode.Remote;
ServerReport serverReport = ReportViewer1.ServerReport;
serverReport.ReportServerUrl = new Uri("http://<Server Name>/reportserver");
serverReport.ReportPath = "/My Folder/MyReport";
serverReport.Refresh();
Me faltaba el ProcessingMode.Remote .
Referencias
http://msdn.microsoft.com/en-us/library/aa337091.aspx - ReportViewer
Hay un ayudante MvcReportViewer en NuGet.
http://www.nuget.org/packages/MvcReportViewer/
Y estos son los detalles:
https://github.com/ilich/MvcReportViewer
Tengo el uso de esto. Funciona muy bien.
No solo tendrá que usar una página asp.net sino
Si usa Entity Framework o LinqToSql (si usa clases parciales) mueve los datos en un proyecto separado, el diseñador del informe no puede ver las clases.
Mueva los informes a otro proyecto / dll, VS10 tiene errores. Los proyectos asp.net no pueden ver las fuentes de datos de los objetos en las aplicaciones web. A continuación, transmita los informes del dll a la página aspx de su proyecto mvc.
Esto aplica para proyectos de mvc y webform. El uso de informes sql en el modo local no es una experiencia de desarrollo agradable. También mire la memoria de su servidor web si exporta grandes informes. El reportviewer / export está muy mal diseñado.
La siguiente solución funciona solo para informes de una sola página. Consulte los comentarios para más detalles.
ReportViewer es un control de servidor y, por lo tanto, no se puede usar con una vista de afeitar. Sin embargo, puede agregar una página de vista ASPX, ver el control de usuario o el formulario web tradicional que contiene un ReportViewer en la aplicación.
Deberá asegurarse de haber agregado el controlador relevante en su web.config .
Si usa una página de vista ASPX o visualiza el control de usuario, deberá configurar AsyncRendering como falso para que el informe se muestre correctamente.
Actualizar:
Se agregó más código de muestra. Tenga en cuenta que no se requieren cambios significativos en Global.asax.
Web.Config
El mío terminó de la siguiente manera:
<?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>
Controlador
Las acciones del controlador son muy simples.
Como beneficio adicional, la acción File () devuelve el resultado de "TestReport.rdlc" como un archivo 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 es el siguiente.
<%@ 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
El control de usuario ASPX se ve así:
<%@ 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
Vista de navaja. Requiere ViewUserControl1.ascx.
@{
ViewBag.Title = "ASPXUserControl";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>ASPXUserControl</h2>
@Html.Partial("ViewUserControl1")
Referencias