none
Los reportes no se muestran cuando publico mi proyecto web RRS feed

  • Pregunta

  • Saludos, estoy trabajando en un proyecto web con asp.net, c# y Crystal Reports y me muestra el siguiente error solo cuando lo publico, si lo ejecuto desde el Visual Studio todo anda perfectamente: 

    Error
    No se pudo abrir la conexión. Nombre_Reporte 10372_12704_{CFC8BA14-9714-4F2E-8B31-54C79E897437}.rpt


    He notado que cuando reinicio el IIS los numeros que muestra al lado del nombre del reporte cambian.

    Lo he intentado todo, habilite las aplicaciones de 32bits, Reinstale CRforVS 13.0.21, y el runtime de 32 y 64 bits. 13.0.21. y revise los parametros.

    A continuación mostrare los codigos:

    <%@ Page Title="" Language="C#"  MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Reportes.aspx.cs" Inherits="SisgemWeb.Paginas.Reportes" %>
    <%@ Register assembly="CrystalDecisions.Web, Version=13.0.3500.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" namespace="CrystalDecisions.Web" tagprefix="CR" %>
    
    <asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
    </asp:Content>
    <asp:Content ID="Content2" ContentPlaceHolderID="FeaturedContent" runat="server">
    </asp:Content>
    <asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
                        <asp:Button ID="BtnCerraR" runat="server" class="btn btn-warning" Text="Cerrar" Visible="true"
    					 OnClick="BtnCerraR_Click" />
                
            
       
                <CR:CrystalReportViewer ID="CrystalReportViewer1" runat="server" AutoDataBind="True" EnableParameterPrompt="False" GroupTreeImagesFolderUrl="" Height="1202px" ReportSourceID="CrystalReportSource2" ToolbarImagesFolderUrl="" ToolPanelView="None" ToolPanelWidth="200px" Width="903px" />
                <CR:CrystalReportSource ID="CrystalReportSource2" runat="server">
                    <Report FileName="Nombre_Reporte.rpt">
                    </Report>
                </CR:CrystalReportSource>
                </asp:Content>
            
    private void reporte()
            {
    
    
                try
                {
                 
    
                    ReportDocument reporte = new ReportDocument();
                    ConnectionInfo coninfo = new ConnectionInfo();
                    String strRutaArchivo = Server.MapPath("Nombre_Reporte.rpt");
    
                    reporte.Load(strRutaArchivo);
                    CrystalReportSource2.ReportDocument.SetParameterValue("vContri", Session["CodCon"]);
                    CrystalReportSource2.ReportDocument.SetParameterValue("vBD", "BD");
                    coninfo.ServerName = "Server";
                    coninfo.DatabaseName = "BD";
                    coninfo.UserID = "root";
                    coninfo.Password = "******";
    
    
    
    
                    CrystalReportViewer1.ReportSource = reporte;
                    CrystalReportViewer1.DataBind();
                }
    
                catch (Exception ex)
                {
    
                    mtvAddMessageModal(ex.Message, MessageType.error);
                }
    
    
                 
    
            }

    

    Otra cosa, uno de los reportes tiene un subinforme, que quizas con las soluciones que me den no se resuelva ya que no muestra ese error, solo muestra los controles del report viewer y mas nada, pero solo es cuando lo publico, cuando lo ejecuto desde el Visual Studio todo anda bien.

    Necesito respuesta urgente por favor. si me falto por indicar algo lo comentan.



    • Editado Handelsr jueves, 14 de diciembre de 2017 19:40
    jueves, 14 de diciembre de 2017 19:07

Respuestas

  • Tiene toda la pinta de ser un problema de credenciales. El Crystal intenta abrir una conexión al servidor de base de datos para traer los datos del informe, y no lo consigue porque la cuenta bajo la que se está ejecutando (la del Pool en IIS, no la del usuario que se conecta desde el navegador) no tiene permiso de acceso al servidor de base de datos. En tiempo de desarrollo no se nota porque la cuenta bajo la que se ejecuta es la del usuario que está rodando el proyecto en Visual Studio, que sí que tiene permisos en la base de datos.

    Solución: O bien cambiar la cuenta del Pool y poner una que tenga los permisos requeridos, o bien ir al servidor de base de datos y conceder permisos a la cuenta del Pool.

    jueves, 14 de diciembre de 2017 21:11
  • Primero hay que averiguar CUAL es la cuenta. Esta dentro de las opciones avanzadas en las propiedades del Pool en le herramienta de configuracion de IIS.

    Si es una cuenta normal de usuario, la puedes dar de alta haciendo clic-derecho en la rama "Logins" por debajo de la instancia de SQL Server en SQL Server management Studio. Si es una cuenta de sistema, no te aparecera en SSMS para seleccionarla, asi que tendras que darla de alta con un comando CREATE LOGIN en SQL Server. Recuerda que estas cuentas son distintas segun que el SQL Server sea local en la misma maquina que el IIS o que sea remoto, asi que si necesitas ayuda con esto recuerda dar suficientes detalles acerca de como es tu instalacion.

    En todos los casos (tanto si la cuenta es de usuario como si es de sistema), una vez que hayas creado el Login en SQL Server hay que mapearlo a un User sobre la base de datos que estes usando. Esto si que se puede hacer graficamente en SSMS aunque la cuenta sea de sistema.

    Notese que todo esto no tiene nada que ver con el hecho de que estes publicando una aplicacion web, te pasaria lo mismo si fuera cualquier otra clase de aplicacion que tuviese que acceder a un servidor de base de datos. En todos los casos seria necesario que la cuenta que ejecuta la aplicacion tuviera permisos en el servidor de base de datos, y habria que crearle el correspondiente Login y User.

    viernes, 15 de diciembre de 2017 16:34
  •   he tomado captura de la configuración avanzada en el pool application porque no estoy seguro de donde dice cual es la cuenta:

    Es donde dice "AppPoolIdentity", abajo del todo de tu captura. Si ahi haces click, te sale un botoncito a la derecha que te permite cambiar la cuenta. Esa es la cuenta que se transmite al servidor de base de datos si has configurado autenticacion integrada. Si has configurado en la cadena de conexion otro tipo de autenticacion, entonces no se usa esta cuenta, sino la que hayas puesto en la cadena.

    Todo lo que te comente de mapear el Login y el Usuario se referia a SQL Server. Si no usas SQL Server, entonces no es aplicable; tendras que sustituirlo por aquello que se use en tu base de datos para autenticar y autorizar a los usuarios.

    Si te funcionan bien los grids con los datos, quiere decir que estan bien puestas las credenciales tal como se usan en la cadena de conexion que empleas para traer esos datos. Asi pues, solo hay que arreglar la cadena de conexion que tengas embebida dentro del rpt para traer los datos del reporte.

    lunes, 18 de diciembre de 2017 16:10
  • la #2 y la #3 deberían funcionar, puesto que le pasas credenciales "fijas" al informe. La #1 no funcionará, porque construyes las credenciales pero no se las pasas al informe.

    En última instancia, la opción #4 debe de funcionar. Puesto que ya tienes comprobado que los accesos desde código te funcionan, la carga de los datasets tiene que funcionar, y al pasárselos al informe éste no tiene que usar su propia conexión. Así que aunque sea un poco más pesado de escribir, tiene la ventaja de que nos aseguramos de que funciona (y si no funciona, al estar dentro de nuestro propio código, se puede seguir con el debugger a ver qué esta pasando).

    miércoles, 20 de diciembre de 2017 7:40

Todas las respuestas

  • Tiene toda la pinta de ser un problema de credenciales. El Crystal intenta abrir una conexión al servidor de base de datos para traer los datos del informe, y no lo consigue porque la cuenta bajo la que se está ejecutando (la del Pool en IIS, no la del usuario que se conecta desde el navegador) no tiene permiso de acceso al servidor de base de datos. En tiempo de desarrollo no se nota porque la cuenta bajo la que se ejecuta es la del usuario que está rodando el proyecto en Visual Studio, que sí que tiene permisos en la base de datos.

    Solución: O bien cambiar la cuenta del Pool y poner una que tenga los permisos requeridos, o bien ir al servidor de base de datos y conceder permisos a la cuenta del Pool.

    jueves, 14 de diciembre de 2017 21:11
  • Como puedo conceder permiso a la cuenta pool?
    viernes, 15 de diciembre de 2017 16:22
  • Primero hay que averiguar CUAL es la cuenta. Esta dentro de las opciones avanzadas en las propiedades del Pool en le herramienta de configuracion de IIS.

    Si es una cuenta normal de usuario, la puedes dar de alta haciendo clic-derecho en la rama "Logins" por debajo de la instancia de SQL Server en SQL Server management Studio. Si es una cuenta de sistema, no te aparecera en SSMS para seleccionarla, asi que tendras que darla de alta con un comando CREATE LOGIN en SQL Server. Recuerda que estas cuentas son distintas segun que el SQL Server sea local en la misma maquina que el IIS o que sea remoto, asi que si necesitas ayuda con esto recuerda dar suficientes detalles acerca de como es tu instalacion.

    En todos los casos (tanto si la cuenta es de usuario como si es de sistema), una vez que hayas creado el Login en SQL Server hay que mapearlo a un User sobre la base de datos que estes usando. Esto si que se puede hacer graficamente en SSMS aunque la cuenta sea de sistema.

    Notese que todo esto no tiene nada que ver con el hecho de que estes publicando una aplicacion web, te pasaria lo mismo si fuera cualquier otra clase de aplicacion que tuviese que acceder a un servidor de base de datos. En todos los casos seria necesario que la cuenta que ejecuta la aplicacion tuviera permisos en el servidor de base de datos, y habria que crearle el correspondiente Login y User.

    viernes, 15 de diciembre de 2017 16:34
  • hola

    en el codigo que muestras no veo que asignes a ninguna lado el coninfo para que defines este sino lo utilizas?

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    viernes, 15 de diciembre de 2017 18:58
  • Lo hice y no funciona, te recuerdo que los reportes solo no se presentan cuando se publica, pero cuando lo ejecuto desde el visual studio todo anda bien
    lunes, 18 de diciembre de 2017 14:51
  • Saludos y disculpa por tardar para responder pero desde la ultima respuesta hoy es que tengo acceso al servidor, no uso SSMS, uso Navicat con MySQL pero revise los privilegios de los usuarios y considero que todo esta bien

    

    También  he tomado captura de la configuración avanzada en el pool application porque no estoy seguro de donde dice cual es la cuenta:

    Para finalizar no se exactamente a que te refieres con que debo mapearlo o mejor dicho no se como hacerlo. Disculpa pero soy nuevo usando el  IIS y creando paginas web. Aun asi algo que habia pensado es que quizas no tenga que ver con la base de datos porque al publicar la pagina los grid traen los datos normalmente y el programa graba edita y hace todo sin problemas.

    De antemano gracias por su respuesta.

    lunes, 18 de diciembre de 2017 15:14
  • Otra cosa que me resulta extraño es que antes si funcionaba y de repente dejo de funcionar, ademas de eso, cuando abro el reporte con el parametro que esta por defecto la primera vez abre pero si elijo otro no abre ni el que tiene parametro por defecto
    lunes, 18 de diciembre de 2017 16:00
  •   he tomado captura de la configuración avanzada en el pool application porque no estoy seguro de donde dice cual es la cuenta:

    Es donde dice "AppPoolIdentity", abajo del todo de tu captura. Si ahi haces click, te sale un botoncito a la derecha que te permite cambiar la cuenta. Esa es la cuenta que se transmite al servidor de base de datos si has configurado autenticacion integrada. Si has configurado en la cadena de conexion otro tipo de autenticacion, entonces no se usa esta cuenta, sino la que hayas puesto en la cadena.

    Todo lo que te comente de mapear el Login y el Usuario se referia a SQL Server. Si no usas SQL Server, entonces no es aplicable; tendras que sustituirlo por aquello que se use en tu base de datos para autenticar y autorizar a los usuarios.

    Si te funcionan bien los grids con los datos, quiere decir que estan bien puestas las credenciales tal como se usan en la cadena de conexion que empleas para traer esos datos. Asi pues, solo hay que arreglar la cadena de conexion que tengas embebida dentro del rpt para traer los datos del reporte.

    lunes, 18 de diciembre de 2017 16:10
  • No deberia ser la cadena de conexion porque lo ejecuto en query y funciona bien ademas recuerda que cuando lo ejecuto del visual studio funciona bien, yo conecto el reporte internamente a través del ODBC y segun investigo esa conexion se pierde al ejecutarlo con el IIS asi que le mando la conexion por codigo como ves pero no se conecta aun asi, ahora mismo despues de algunas modificaciones me aparece otro error que dice que no se pudo conectar con la base de datos, lo he probado habilitando y deshabilitando la opcion enabledatabaselogonprompt pero si lo activo me aparece un cuadro diciendo que el informe requiere informacion adicional y me pide los datos de la conexion (server, base de datos,  usuario y contraseña)
    • Editado Handelsr martes, 19 de diciembre de 2017 14:27
    martes, 19 de diciembre de 2017 12:13
  • ... asi que le mando la conexion por codigo como ves
    No, no lo veo. En el codigo que has aportado veo que configuras los datos de conexion dentro del objeto "coninfo", pero luego no se ve que ese coninfo lo uses para nada ni se lo asignes al report.
    martes, 19 de diciembre de 2017 16:54
  • Muy bien, mostrare todas las maneras de como he intentado hacer que conecte por codigo, solo quiero que me digas cual seria la mejor solucion:

    #1

    ReportDocument reporte = new ReportDocument();
                    ConnectionInfo coninfo = new ConnectionInfo();
                    String strRutaArchivo = Server.MapPath("SW-AI-AP-002-REP01.rpt");
    
                    reporte.Load(strRutaArchivo);
    
    reporte.SetParameterValue("vContri", Session["Codcon"]);
    reporte.SetParameterValue("vBD", "Siafim2017");
    coninfo.ServerName = "Siafim";
    coninfo.DatabaseName = "siafim2017";
    coninfo.UserID = "root";
    coninfo.Password = "*010405";
    
    CrystalReportViewer1.ReportSource = reporte;
    CrystalReportViewer1.DataBind();
    


    #2

    ReportDocument reporte = new ReportDocument();
                    String strRutaArchivo = Server.MapPath("SW-AI-AP-002-REP01.rpt");
    
                    reporte.Load(strRutaArchivo);
    
    CrystalReportSource2.ReportDocument.SetParameterValue("vContri", Session["Codcon"]);
                    CrystalReportSource2.ReportDocument.SetParameterValue("vBD", "Siafim2017");
    
    reporte.DataSourceConnections[0].SetConnection("Siafim", "Siafim2017", "root", "*010405");
    
                    CrystalReportViewer1.ReportSource = reporte;
                    CrystalReportViewer1.DataBind();
    


    #3

    ReportDocument reporte = new ReportDocument();
    String strRutaArchivo = Server.MapPath("SW-AI-AP-002-REP01.rpt");
    reporte.Load(strRutaArchivo);
    reporte.SetParameterValue("vContri", Session["Codcon"]);
    reporte.SetParameterValue("vBD", "Siafim2017");
    reporte.SetDatabaseLogon("root", "*010405", "Siafim", "siafim2017");
    
    CrystalReportViewer1.ReportSource = reporte;
                    CrystalReportViewer1.DataBind();
    

    Por ultimo, esto lo comence a intentar hoy cuando estaba terminando de programar, el objetivo era olvidarme de tener que pasar parametros y conexion al reporte desde el codigo de C# pero no me dio tiempo de probar y el codigo resulta mas largo y toma mas tiempo. Lo que hice en resumen fue cargar los datos a un dataset y cargar el reporte desde el dataset

    #4

                    //abre conexion
                    MySqlConnection con = null;
                    Datos.Conexion cn = new Datos.Conexion();
                    con = cn.ConexionDa();
                    con.Open();
    
    
                    //DataTable para la primera tabla
                    DataTable dtc = new DataTable();
                    MySqlCommand cmdc = new MySqlCommand();
                    cmdc.CommandType = CommandType.Text;
                    cmdc.CommandText = "select* from siafimcxc.tblcontribuyente where codcon =" + Session["Codcon"];
                    cmdc.Connection = con;
                    cmdc.ExecuteReader();
                    
    
    
                    //Llena Datatable para la segunda tabla haciendo where en vez de INNER JOIN
                    DataTable dti = new DataTable();
                    MySqlCommand cmdi = new MySqlCommand();
                    cmdi.CommandType = CommandType.Text;
                    cmdi.CommandText = "SELECT i.CodInmueble, i.CodCon, i.Activo, i.Tipo, (case i.Tipo when 1 then 'Vivienda Familiar' when 2 then 'Vivienda Familiar y Comercio' when 3 then 'Comercio' end) as txtTipo, i.Categoria, (select t.descripcion from siafimcxc.tblinmuebles_tipo t where t.codigo = i.categoria) as txtCat, ifnull(i.Calle, '') as calle, ifnull(i.Urbanizacion, '') as Urbanizacion, ifnull(i.Manzana, '') as Manzana, ifnull(i.Edificio, '') as Edificio, ifnull(i.Numero, '') as Numero, ifnull(i.Apto, '') as Apto, ifnull(i.Direccion, '') as Direccion, i.Ruta, (select r.descripcion from siafimcxc.tblinmuebles_ruta r where r.codigo = i.ruta) as txtRuta, CodTemp FROM siafimcxc.tblinmuebles i where siafimcxc.tblinmuebles.CodCon=" + Session["Codcon"];
                    
                    cmdi.Connection = con;
                    cmdi.ExecuteReader();
                    
                    
                    //Asignar el codigo del inmueble a la variable
                    string codinmueble=Convert.ToString(dti.Rows[0][0]);
                    
                    //Llena Datatable para la tercera tabla
                    DataTable dtt = new DataTable();
                    MySqlCommand cmdt = new MySqlCommand();
                    cmdt.CommandType = CommandType.Text;
                    cmdt.CommandText = "SELECT t.codinmueble, t.activo, t.codtri,(select concat_ws(' - ',siafim2017.fcodingreso(codingreso), descripcion) from siafimcxc.tbltributos_reg r where r.codtri = t.codtri) as txtTri, t.codcon, t.calculado, t.frecuencia, (select f.descripcion from siafimcxc.tblfrecuencia f where f.frecuencia = t.frecuencia) as txtFrecu , t.unidad,(select u.descripcion from siafimcxc.tblunidadm u  where u.unidad = t.unidad) as txtUnidad, t.tarifa,t.campocal, t.monto, CodTemp, annoini, mesini, fechaini FROM siafimcxc.tblinmuebles_tri t where t.CodCon=" + codinmueble;
                    
                    cmdt.Connection = con;
                    cmdt.ExecuteReader();
    
                    //Cierra conexion
                    con.Close();
                    cmdc.Connection = con;
                    cmdi.Connection = con;
                    cmdt.Connection = con;
                    
    
    
                    MySqlDataAdapter dac = new MySqlDataAdapter(cmdc);
                    dac.Fill(dtc);
                    MySqlDataAdapter dai = new MySqlDataAdapter(cmdi);
                    dai.Fill(dti);
                    MySqlDataAdapter dat = new MySqlDataAdapter(cmdt);
                    dat.Fill(dtt);
    
                    //Crea un dataset y lo llena con los 3 datatable
                    DataSet ds = new DataSet();
                    ds.Tables.Add(dtc);
                    ds.Tables.Add(dti);
                    ds.Tables.Add(dtt);
    
    ReportDocument reporte = new ReportDocument();
    String strRutaArchivo = Server.MapPath("SW-AI-AP-002-REP01.rpt");
    
                    reporte.Load(strRutaArchivo);
                    reporte.SetDataSource(ds);
                    CrystalReportViewer1.ReportSource = reporte;
                    CrystalReportViewer1.DataBind();

    Tan solo por todo en lo que me has Ayudado hasta ahora Alberto mereces todos los puntos del mundo, funcione o no funcione tu ayuda gracias de antemano, inmediatamente resuelva el problema marcare tu comentario como respuesta.

    miércoles, 20 de diciembre de 2017 3:32
  • la #2 y la #3 deberían funcionar, puesto que le pasas credenciales "fijas" al informe. La #1 no funcionará, porque construyes las credenciales pero no se las pasas al informe.

    En última instancia, la opción #4 debe de funcionar. Puesto que ya tienes comprobado que los accesos desde código te funcionan, la carga de los datasets tiene que funcionar, y al pasárselos al informe éste no tiene que usar su propia conexión. Así que aunque sea un poco más pesado de escribir, tiene la ventaja de que nos aseguramos de que funciona (y si no funciona, al estar dentro de nuestro propio código, se puede seguir con el debugger a ver qué esta pasando).

    miércoles, 20 de diciembre de 2017 7:40
  • Perfecto, gracias, voy a probar.
    miércoles, 20 de diciembre de 2017 12:06
  • No funciona, Creo que hay que configurar bien el IIS para el Crystal Reports me canse de buscar informacion y no vi ninguna convincente o quizas se intenta conectar de la conexion interna que tiene hecha el CR y no puede. De todos modos si estas dispuesto a que hablemos de manera mas personal sobre el asunto te dare mi correo, para ver si se resuelve rapido. 

    handelsr@hotmail.es

    jueves, 21 de diciembre de 2017 18:23