viernes, 13 de julio de 2012

Descargar un informe desde Report Server en PDF

Enunciado 

Usando Visual Basic.NET, descarga un informe desde Report Server que puede ser utilizado para mandarlo por correo o generar una descarga por web.

Solución

Es tan simple como esto:
Private Function solicitaInformeSSRS(idRespuesta As Integer) As Byte()
        Dim informe As New ServerReport
        With informe
            .ReportServerUrl = New Uri(My.Settings.urlServerReport)
            .ReportPath = My.Settings.SSRSEncuestaPromocion
            .ReportServerCredentials = New MyReportServerCredentials
            .SetParameters(New ReportParameter("idRespuesta", idRespuesta))
            .Refresh()
            Return .Render("PDF")
        End With
End Function
Hay que utilizar la clase  MyReportServerCredentials que puedes encontare en mi post Autentificación Reporting Services

Usos:

Una vez descargado el array de byte, puedes utilizarlo para adjuntarlo en un email como un adjunto:

 msj.Attachments.Add(New Attachment(New System.IO.MemoryStream(informe),"informe.pdf")) 
O entregarlo en el stream de salida de una página (descarga del PDF):
Response.Clear()
Response.ContentType = "Application/PDF"
Response.AddHeader("content-disposition", String.Format("attachment; filename={0}.PDF", "archivo.PDF"))
Response.BinaryWrite(bytes)

Comentario:

Usar informes del servidor resulta mas simple, y no digamos ya si existen subinformes, ver Subinformes RDLC en Report cargado dinámicamente.

miércoles, 11 de julio de 2012

Lanzar eventos desde un control de usuario ASP.NET

Enunciado

Una forma muy cómoda de comunicar un control de usuario (.ascx) con la página u otro control de usuario que le contiene es definir un evento, lanzarlo y recogerlo.

Por ejemplo:
Un control de usuario realiza un búsqueda y la visualiza en un dataGrid.
Cuando el usuario elige un comando en una fila del datagrid el control de usuario lanza un evento informando con un texto y un identificador.

Solución:

Un pequeño truco, en el data grid usamos un comando con nombre y argumento.

   
        
           
         
         
   

En el código del control de usuario definiremos el evento y lo lanzaremos en dos casos:
  1. Con el evento RowCommand del datagrid
  2. Al hacer en click en cancelar (un botón)

Public Event eleccion As System.EventHandler

Private Sub gvActiv_RowCommand(
                        sender As Object, 
                        e As GridViewCommandEventArgs
                        ) Handles gvActiv.RowCommand
        RaiseEvent eleccion(Me, New ArgumentoObjetoElegido(e))
End Sub

Protected Sub LBCancelar_Click(
                        sender As Object,
                        e As EventArgs) Handles LBCancelar.Click
        RaiseEvent eleccion(Me, New ArgumentoObjetoElegido)
End Sub
Observar que como segundo argumento al lanzar el evento (RaiseEvent) hemos usado la clase ArgumentoObjetoElegido que hereda de EventArgs.
Esta clase puede crearse con y sin los argumentos. En caso de usar argumentos estos son del tipo GridViewCommandEventArgs.
Public Class ArgumentoObjetoElegido
    Inherits EventArgs
    Public Property Identificador As Integer = 0
    Public Property Descripcion As String = "(Nada seleccionado)"

    Public Sub New(Argumentosfila As GridViewCommandEventArgs)
        Identificador = CInt(Argumentosfila.CommandArgument)
        Descripcion = Argumentosfila.CommandName
    End Sub
    Public Sub New()
        'sin argumentos, valores iniciales arriba
    End Sub
End Class
Finalmente hay que recoger el evento en la página principal:
Private Sub EligeActiv_eleccion(sender As Object, e As ArgumentoObjetoElegido) Handles EligeActiv.eleccion
        If e.Identificador = 0 Then
            'Codigo para procesar cancelación
            If controlador.ActividadEnCurso.identificador = 0 Then
                controlador.ControlMenos()
            Else
                EstableceVista(VistaActividad)
            End If
        Else
            'codigo para procesar una elección el grid
            controlador.ActividadEnCurso.identificador = e.Identificador
            controlador.ActividadEnCurso.Descripcion = e.Descripcion
            EstableceVista(VistaActividad)
        End If
    End Sub

lunes, 9 de julio de 2012

WSUS: problema al conectarse a la base de datos el servicio de red

Sintomas

El servidor de actualizaciones (WSUS) no arranca. aparecen varios errores en el registros de eventos, el más destacado e indicativo es:

Tipo de suceso: Errores
Origen del suceso: MSSQL$MICROSOFT##SSEE
Categoría del suceso: (4)
Id. suceso: 18456
Fecha: 09/07/2012
Hora: 14:05:32
Usuario: NT AUTHORITY\Servicio de red
Equipo: W2K3R2
Descripción:
Login failed for user 'NT AUTHORITY\Servicio de red'. [CLIENT: ]

Solución:

Necesitarás las herramientas de administración de SQL Server.
Arranca el SQL Server Configuration Manager
Habillita las canalizaciones con nombre en configuración de red de SQL Server.../Protocolos de Microsoft##SSEE

De paso copiate al portapapeles el nombre de la canalización
\\.\pipe\MSSQL$MICROSOFT##SSEE\sql\query
Que encontraras en las propiedades de las canalizaciones con nombre

Ahora con SQL Server Managemente Studio
Conectate al motor de la base de datos
\\.\pipe\MSSQL$MICROSOFT##SSEE\sql\query
Si me has hecho caso, te bastarácon pegarlo.

Abre las propiedades de la base de datos SUSDB y activale la opción de multiusuario (estará en usuario único)

Comentario:

Encontré la pista en http://steili.com/2012/06/19/wsus-3-0-sp2-will-not-run-after-installing-update-2720211/ aunque en su caso no había funcionado. El habla de que el problema estaba en una instalación fallida de la KB2720211, pero en mi caso tengo que reconocer que se llenó el disco. Y eso que es una VM y tengo suficiente espacio. Pero es un crimen.



viernes, 6 de julio de 2012

Autocompletar un cuadro de texto en jQuery Mobile

Enunciado:

Tenemos la clásica búsqueda con un cuadro de texto al que normalmente desplegaríamos un lista de sugerencias a medida que escriben. En una aplicación de escritorio ASP.NET usariamos el componente autocomplete de AJAX.NET o de jQuery UI. Pero ¿En una aplicación móvil?

Solución:

Usar jQuery y el componente jQM Autocomplete de Andy Matthews.
Si haces clic en el vínculo llegaras a una demo y te enamoraras como lo hice yo.

Desarrollo de la solución

Necesitaras un servicio JSON que te entregue las sugerencias de palabras. Si desarrollas en ASP.NET puedes consultar mi post Desarrollo de un servicio json sobre ASP.NET para consumo desde Jquery
En mi caso además estaba buscando nombres de empresa en una base de datos por lo que dispongo del identificador único de registro.
Por eso devuelvo un array de objetos con dos propiedades de texto "label" y "value" .
Esta es la respuesta JSON:

[{"label":"INCOAZUL","value":"353"},{"label":"AZULIBER","value":"18"},{"label":"AZULEJERA ALCORENSE","value":"62"},{"label":"MAYOLICA AZULEJOS, S.L.","value":"60"},{"label":"AZULEJOS ALCOR","value":"61",{"label":"AZULINDUS & MARTI, S.A.","value":"13"},{"label":"NOMAZUL, S.A.","value":"85"}}] Este un ejemplo código de página:

    Que completaríamos con esté código JavaScript
           $(document).ready( function (e) {
             $("#busqueda").autocomplete({
                 method: 'GET',
                 target: $('#sugerencias'),
                 source: "/MAC.svc/NomIdEmpresa",
                 link: 'ficha?id=',
                 minLength: 3
             });
         });
     
    
    Por supuesto en los encabezados debes incluir las referencias a las librerias y estilos jQuery, jQuery Mobile y jQM autocomplete.
    Observarás que en la parte java especifico un enlace ficha?id= que se completará al final con el campo value que me devuelve el JSON. Asi cuando clicken en INFOAZUL navegaremos hacia ficha?id=353.
    Sin embargo, esta no es la solución optima, lo mejor sería cambiar a una página móvil ya cargada y actualizarla con los datos leidos con un llamada a un servicio JSON datosEmpresa(idEmpresa). 
    Es mi próximo objetivo, así que....continuará en próximas entregas

    Desarrollo de un servicio json sobre ASP.NET para consumo desde Jquery

    Enunciado:

    Necesitamos un servicio web que responda en formato JSON para poderlo leer desde Jquery.

    En este ejemplo partiremos del resultado otro servicio web WCF "directorio", pero podríamos estar devolviendo los resultados de una consulta linq o cualquier otra fuente serializable

    Solución

    Añadir un Servicio WCF con AJAX habilitado.
    IMPORTANTE: En el Web.config sección system.servicemodel ELIMINAR o comentar las referencias a este servicio  . En mi caso que el servicio se llamaba MAC eliminé las líneas: el behavior  enablewebScript
    
    
    
          
            
                 
                
          
          
        
        
        
          
            
          
        
    

    Luego editamos el archivo de etiquetado (.svc) añadiendo el atributo Factory apundando a la clase System.ServiceModel.Activation.WebServiceHostFactory.
    <%@ ServiceHost Language="VB" Debug="true" Service="myAplication.MAC" CodeBehind="MAC.svc.vb" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>
    
    En el archivo de código MAC.svc.vb definiremos los metodos con el atributo WebInvoke especificando el método (GET o POST) y el formato de la respuesta (JSON).
    Imports System.ServiceModel
    Imports System.ServiceModel.Activation
    Imports System.ServiceModel.Web
    
    
    
    Public Class MAC
    
        
        
        Public Function NomIdEmpresa(term As String) As directorio.EmpresaIdentificada()
            'ahora llamo a la clase proxy de mi servicio WCF.
            Dim servicio = New directorio.IdirectorioClient
            Dim resultado As directorio.EmpresaIdentificada() = servicio.SugerenciasNombreIdEmpresa(term, 20) 
            servicio.Close()
            Return resultado
        End Function
    End Class
    

    jueves, 5 de julio de 2012

    Donde esta wsdl.exe

    Pregunta:

    Para generar clases proxy de servicios web necesitas usar wsdl.exe ¿Donde está?

    Solución:

    En  C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin 
    (x86 para sistemas X64)

    Comentario:

    Cada vez que tengo que usarlo no lo encuentro y es mas efectivo que el GUI.

    martes, 3 de julio de 2012

    Emulador para depurar web apps para iphone

    Situación

    Desarrollas una aplicación para móviles, la pruebas en varios teléfonos Android con varios navegadores (Dolphin, Navigator y Firefox). También en una tableta Android, y en el emulador del SDK Android.
    Por supuesto en todos los exploradores de escritorio habituales.
    Bueno pues cuando está en el aire, alguien te dice que falla en iPhone.
    ¿Te compras un iPhone o un Mac? :-(

    Solución

    Usas el emulador on-line http://www.testiphone.com/  

    Comentario

    ¡Gracias Joe!,  me sentía como Newton cuando descubrió la ley de la gravedad.