Saltar al contenido

Visualización de informes de SSRS en un sitio MVC de ASP.net

Solución:

No, no en una vista MVC. Pero puede tener páginas de formularios web que tengan controles de servidor en ellas mixed en su sitio MVC.

Hmm, simplemente busqué en Google “mezclar asp.net mvc y formularios web” para encontrar algunos ejemplos, y Google preguntó si soy humano o no 🙂

De todos modos, aquí hay un enlace: http://www.packtpub.com/article/mixing-asp.net-webforms-and-asp.net-mvc; hay algunos por ahí. También hice esto en un sitio MVC por la misma razón: el control de informes.

No, el control ReportViewer no funcionará si lo coloca en una vista MVC, ya que requiere ViewState. Tendrá que crear un formulario web de la vieja escuela y colocar el ReportViewer allí en su lugar.

Una solución que utilicé en un proyecto en el que trabajé fue crear un controlador de ruta personalizado, por lo que aún podría hacer uso del enrutamiento de URL. El controlador de ruta tomaría parámetros como el nombre del informe de la colección RouteData, crearía una instancia de mi formulario web y le pasaría los parámetros a través de propiedades públicas. El formulario web los leería en Page_Load y configuraría el control 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;
    

Este código es solo un punto de partida si decide utilizar este enfoque, por supuesto. El que creé también hizo algo de autenticación de usuario y validación de parámetros antes de regresar.

Actualizar: Parece que si está utilizando ASP.NET 4.0, la mayor parte de esto se puede hacer automáticamente.

La implementación de un control SSRS ReportViewer en MVC consta de dos problemas:

  1. Como mínimo, deberá agregar las dependencias, los controladores y configuración para el control ReportViewer (independientemente del tipo de proyecto).
  2. El obstáculo más complicado está en Mezcla de WebForms y MVC. Necesitamos una forma de representar y enrutar las solicitudes entrantes para que sean manejadas por las páginas, los controles y las acciones de WebForms.

Problema 1: configuración del ReportViewer

Si ha hecho mucho con la configuración de los controles de ReportViewer en el pasado, esto podría ser obsoleto y puede pasar a la sección 2.

  1. Agregar paquete / referencia – Los ReportViewer controlar vidas en el Microsoft.ReportViewer.WebForms.dll. Puede incluir en su proyecto agregando el Microsoft.ReportViewer.WebForms paquete de nuget:

    Nuget: Microsoft.ReportViewer.WebForms

  2. Controladores Web.config – Según este artículo sobre la configuración de Web.config para ReportViewer, y esta pregunta SO, deberá agregar lo siguiente a su web.config:

    
      
        
      
    
    
      
        
        
      
    
    

    Por esta pregunta en duplicado keys, generalmente es más fácil de eliminar y luego volver a agregar las configuraciones del servidor web

  3. Corregir solicitudes de imágenes rotas – hay un defecto conocido en ReportViewer con blank.gif las imágenes no se cargan, por lo que puede agregar la siguiente corrección a su 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 – Si aún no está allí, asegúrese de permitir ScriptResources en su RouteConfig.cs:

    routes.IgnoreRoute("resource.axd/*pathInfo");
    
  5. Agregar ReportViewerPage.aspx – Agregue una página WebForm que contendrá una instancia del control ReportViewer. Para que funcione, ese control necesita encontrar un ScriptManager controlar y ser colocado dentro de un

    .
    Entonces, su nueva página .aspx debería verse así:

    <%@ 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" %>
    
    
    
    
        Report Viewer
    
    
        
            
            
        
    
    
    
  6. Conecte ReportViewer en Page_Load – Suponiendo que ya tiene un informe SSRS completamente implementado en un servidor de informes que está disponible en una dirección como esta:

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

    Entonces su código subyacente en su nueva página WebForm debería verse así:

    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([email protected]
    
    "http://reportServer/ReportServer"); serverReport.ReportPath = [email protected]"reportPathreportName"; // report input var parameters = new List(); parameters.Add(new ReportParameter("User_uid", "1")); serverReport.SetParameters(parameters); // run report serverReport.Refresh();
  7. Vista del informe – En este punto, debería poder ver su informe por sí solo seleccionando Ver en el navegador o control + Cambio + W

    Ver en el navegador

Problema 2: mezcla de WebForms y MVC

Primero, analicemos rápidamente las diferencias de enrutamiento entre cómo se cargan estos controles y cómo se actualizan posteriormente

  • MVC las rutas se verán algo como esto controller/action/id donde el motor de enrutamiento encontrará automáticamente un Controller y Action con el nombre especificado y las solicitudes entrantes serán manejadas por ese método. En cualquier solicitud de página, ya sea desde la carga de la página, el envío de formularios, los clics en los botones, la navegación de anclaje o las llamadas ajax, el método exacto que se está ejecutando siempre se especifica en la URL. action.

  • WebForms enruta al código encontrando la dirección física de la página .aspx, y luego usa ViewState y PostData para conectar y disparar eventos en esa página / control.

    Aquí hay una ilustración de diferentes formatos de enrutamiento en WebForms. Y aquí hay un evento de clic de botón simple que enviará una publicación a la página principal y generará los eventos apropiados dentro de la página según los datos del evento enviados:

    ASP.NET WebForms - Postback

Esta es una limitación bastante grande para nuestras soluciones disponibles. Nada tiene de especial ReportViewer control. Es solo un conjunto sofisticado de clases UserControl que responden al clic y otros eventos de entrada al publicar la dirección actual junto con la información de ViewState y Event. Por lo tanto, las suposiciones que se incluyeron en el enrutamiento y la navegación del ReportViewer deberán persistir en nuestro contenedor MVC.

  1. Opción 1 – Agregar ruta para la página .aspx

    A partir de MVC 4.0+, puede utilizar el enrutamiento de URL con WebForms. Esto se mezcla bien con MVC agregando un MapPageRoute(nota la Página parte) para mapear una ruta a un archivo físico. Así que agregue lo siguiente a su RouteConfig.cs:

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

    El informe se ejecutará cuando navegue a la dirección ~/Reports/reportName. Esto probablemente se invocará desde dentro de una acción del controlador, quizás con algunos parámetros ingresados ​​por el usuario o cadenas de conexión web.config. Hay muchas formas de administrar el estado en ASP.NET y pasar valores a las páginas de formularios Web Forms de ASP.NET. Una opción sería guardar la información en la Sesión y Redirigir así en su controlador:

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

    Luego, dentro de la página .aspx, puede tomar el reportName de los valores de RouteData y cualquier parámetro de configuración de la sesión:

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

    Pros:

    • La mayor parte del enrutamiento parece funcionar de forma predeterminada, y los controles AJAX funcionan bien, por lo que puede configurar AyncRendering=True

    Contras:

    • Es difícil utilizar un formulario web ASP con un diseño MVC de Razor, por lo que la representación sacará a los usuarios del flujo del resto de la aplicación.
    • Además, los valores del informe deben exponerse como parte de la URL o pasarse indirectamente a través de la sesión (en lugar de hidratarse directamente en el objeto).
  2. Opción 2 – Nest .ascx dentro PartialView en tu pagina

    Adaptado de ¿Cómo puedo usar un control ReportViewer con Razor ?, puede consumir .ascx controles en PartialViews siempre que hereden de System.Web.Mvc.ViewUserControl.

    Cree un nuevo control de usuario de formularios Web Forms llamado ReportViewerControl.ascx que se ve así:

    <%@ 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" %>
    
    
    AsyncRendering="False" /> EnablePartialRendering="false" />

    Nota: Debes configurar AsyncRendering="False" y EnablePartialRendering="false"

    En el código subyacente, deberá reemplazar el tipo de herencia de System.Web.UI.UserControl para System.Web.Mvc.ViewUserControl.

    Y en Page_Init, deberá configurar el Context.Handler para Page para que los eventos se registren correctamente.

    Entonces el ReportViewerControl.ascx.cs debería verse así:

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

    Para generar el informe, agregue lo siguiente a la vista de su controlador:

    @Html.Partial("ReportViewerControl", Model)
    

    Y luego, en el evento ReportViewerControl.ascx.cs Page_Load, puede recuperar el modelo pasado del ViewUserControl.Model propiedad como esta:

    ReportSetup setup = (ReportSetup)Model;
    

    Pros:

    • Puede construir en maestro _layout.cshtml y consumir en vistas regulares
    • Puede pasar el modelo directamente

    Contras:

    • AsyncRendering debe establecerse en false, por lo que interacciones como la paginación y la clasificación provocan actualizaciones de página completa y, a veces, son inestables. Brian Hartman tiene un blog solo para ReportViewer y habla sobre AsyncRendering y todo el equipaje que viene con él.

Otras lecturas:

  • ¿Cómo puedo usar un control de visor de informes en una vista de maquinilla de afeitar ASP.NET MVC 3?
  • ¿Cómo renderizo una página aspx de ReportViewer remota en MVC 4?
  • MVC 5 y SSRS ReportViewer: ¿cómo implementarlo?

Finalizando este artículo puedes encontrar las críticas de otros gestores de proyectos, tú asimismo tienes el poder mostrar el tuyo si lo crees conveniente.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *