Enunciado
En ocasiones puede resultar interesante leer un informe definido en el servidor de Microsoft Reporting Services, modificar la definición y volver subirlo al servidor para visualizar en un webform Report viewer.
Redactaré mas adelante algunos ejemplos de aplicación, por el momento.
Solución
El problema se divide en tres partes:
- Leer la definición del informe.
- Modificar el XML de esta definición mediante Linq to XML
- Establecer la definición modificada en el report Viewer.
Leer la definición del informe desde el servidor
Hay que acceder a los servicios web de Reporting Services, para ello se crea una un clase proxy mediante WSDL.EXE y
una clase con las credenciales necesarias para autentificarse.
Una vez hecho esto es relativamente fácil.
Private Function CargaInforme(nombre As String) As XDocument
Dim SSRS As New ReportingService2010
SSRS.Credentials = (New MyReportServerCredentials).NetworkCredentials
Dim informe = SSRS.GetItemDefinition(My.Settings.mapas + nombre)
SSRS = Nothing
Dim stream = New System.IO.MemoryStream(informe)
Dim lector = System.Xml.XmlReader.Create(stream)
Dim doc As XDocument = XDocument.Load(lector, LoadOptions.None)
Return doc
End Function
En breve, el servicio veb me devuelve un array de bytes, que traslado a un memory stream que a su vez me permite crear un xdocument.
Modificar la definición de informe
Esto es lo mas fácil, aunque a veces engorroso. Por ejemplo vamos a cambiar la definición del Dataset "datos" en el informe.
Dim df = doc.Root.Name.Namespace
Dim xdatos = (From f In doc.Root.Element(df + "DataSets").Elements(df + "DataSet")).First(
Function(x As XElement) x.Attribute("Name") = "Datos").Element(df + "Query").Element(df + "CommandText")
xdatos.SetValue(s)
S es un string con la sentencia SQL, MDX o lo que quiera que utilices, por supuesto tiene que se coherente con el resto del informe en lo que atañe a nombres de campo, parametros,...etc
Visualizar el informe modificado en Report Viewer
Para hacerlo necesitaremos convertir nuestro Xdocument que contiene la definición en un stream:
Private Function XMLBytes(doc As XDocument) As System.IO.Stream
Dim stream As New System.IO.MemoryStream
Dim escritor = System.Xml.XmlWriter.Create(stream)
doc.Save(escritor)
escritor.Close()
stream.Position = 0
Return stream
End Function
Lo que sigue es asignar este stream al visor de informes, establecer los parámetros que hagan falta y refrescar
Visor.ServerReport.LoadReportDefinition(e.Informe)
Visor.ServerReport.SetParameters(New ReportParameter("miParametro", suValor))
Visor.ServerReport.Refresh()