on 2020 May 22 4:33 PM
Hello guys
I'm having a strange problem, database logon prompt appears only on the 2nd page (Navigation next page). I am using Visual Studio 2019 community edition and Crystal Reports 13, update 27 that supports VS2019. I don't have this particular problem while reports are made against tables, but stored procedures those accept multiple parameters & the select within the procedure is referring multiple views. To make it easier to understand:
The report is being called like below
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ReportDocument reportDocument = new ReportDocument();
reportDocument.Load(Server.MapPath(@"~/CrystalReport2.rpt"));
reportDocument.SetParameterValue(0, 2020);
reportDocument.SetParameterValue(1, 1);
reportDocument.SetParameterValue(2, 3);
reportDocument.SetParameterValue(3, "1");
reportDocument.SetParameterValue(4, "1");
ConnectionInfo connectionInfo = new ConnectionInfo
{
DatabaseName = "test",
UserID = "sa",
Password = "password",
ServerName = "RAJESH-PC"
};
SetDBLogonForReport(connectionInfo, reportDocument);
CrystalReportViewer1.Visible = true;
CrystalReportViewer1.ReportSource = reportDocument;
}
}
and the SetDBLogonForReport method as below:
private void SetDBLogonForReport(ConnectionInfo connectionInfo, ReportDocument rpt)
{
foreach (ReportDocument subRpt in rpt.Subreports)
{
foreach (Table crTable in subRpt.Database.Tables)
{
Response.Write(crTable.Name);
crTable.LogOnInfo.ConnectionInfo.AllowCustomConnection = true;
TableLogOnInfo logInfo = crTable.LogOnInfo;
logInfo.ConnectionInfo = connectionInfo;
try
{
crTable.ApplyLogOnInfo(logInfo);
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}
}
foreach (Table crTable in rpt.Database.Tables)
{
Response.Write(crTable.Name);
crTable.LogOnInfo.ConnectionInfo.AllowCustomConnection = true;
TableLogOnInfo loi = crTable.LogOnInfo;
loi.ConnectionInfo = connectionInfo;
try
{
crTable.ApplyLogOnInfo(loi);
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}
}
While single page reports are executed without the database logon prompting, I am kind of totally lost after 2 days of continuous efforts to find a solution, Please help.
regards,
rajesh
Request clarification before answering.
Thanks Dell,
I fixed the link.
A better one may be this one also:
1985571 - How to use sessions in web applications using the Crystal Reports viewer (the complete code)
https://launchpad.support.sap.com/#/notes/1985571
@ Rajesh, and move your code from the Page_Load to Page_Init, Page load only gets called once. Something MS changed a long time ago so now all of the page refreshing gets called by Page Init now.
Don
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Resolving this requirement using "Session" and "page_init" as suggested. Please note, my application need to collect many inputs from the end user before generating the report & many of the text inputs have Autopostback set as true. Everytime the autopostback happens, Crystal Report refreshes, hence I recommend using as less possible Autopostback enabled input fields with your web form.
Sample ASP page
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="c4.aspx.cs" Inherits="CrystalTest.c4" %>
<%@ Register Assembly="CrystalDecisions.Web, Version=13.0.4000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" Namespace="CrystalDecisions.Web" TagPrefix="CR" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server" Text="Print Report" OnClick="Button1_Click" />
<CR:CrystalReportViewer ID="CrystalReportViewer1" runat="server" AutoDataBind="true" />
</div>
</form>
</body>
</html>
and the code behind (copied from a crude test form, please make sure that you follow the coding standards recommended). Please note, this sample doesn't have "page_load" method, hence if you have specific situations where page_load is required, you will have to adapt much tedious approaches or clicking the button to generate the report should be redirected to a page where you have only the report.
using CrystalDecisions.CrystalReports.Engine;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CrystalTest
{
public partial class c4 : System.Web.UI.Page
{
protected void Page_Init(object sender, EventArgs e)
{
if (IsPostBack)
{
CrystalReportViewer1.ReportSource = (ReportDocument)Session["Report"];
}
}
private void ShowReport1()
{
string ConnectionString = ConfigurationManager.ConnectionStrings["menass"].ToString();
using (SqlConnection con = new SqlConnection(ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("GETMONTHSALARY", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@pProcessYear", SqlDbType.Int).Value = 2020;
cmd.Parameters.Add("@pProcessMonth", SqlDbType.Int).Value = 1;
cmd.Parameters.Add("@pProcessSection", SqlDbType.VarChar).Value = "9";
cmd.Parameters.Add("@pProcessSite", SqlDbType.VarChar).Value = "1";
cmd.Parameters.Add("@pProcessCatg", SqlDbType.VarChar).Value = "1";
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
adapter.Fill(ds, "SalaryDT");
ReportDocument oRpt = new ReportDocument();
oRpt.Load(Server.MapPath(@"~/dataset/CrystalReport1.rpt"));
oRpt.DataSourceConnections.Clear();
oRpt.SetDataSource(ds);
oRpt.Subreports[0].SetDataSource(FillOverTime());
CrystalReportViewer1.Visible = true;
CrystalReportViewer1.ReportSource = oRpt;
Session["Report"] = oRpt;
}
}
}
private DataSet FillOverTime()
{
string ConnectionString = ConfigurationManager.ConnectionStrings["menass"].ToString();
using (SqlConnection con = new SqlConnection(ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("GetEmployeeOverTime", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@pEmployeeCode", SqlDbType.VarChar).Value = DBNull.Value;
cmd.Parameters.Add("@pProcessYear", SqlDbType.Int).Value = 2020;
cmd.Parameters.Add("@pProcessMonth", SqlDbType.Int).Value = 1;
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataSet ds1 = new DataSet();
adapter.Fill(ds1, "OverTimeDT");
return ds1;
}
}
}
protected void Button1_Click(object sender, EventArgs e)
{
ShowReport1();
}
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
The whole solution is posted here. It may help few others having the same situation.
regards,
Rajesh
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks dell.stinnett-christy and don.williams for your inputs. I've figured out that the postback was causing the report prompting for the database credentials & managed to provide them to the report viewer, thus stopping the behavior for good. This is the first time I am using Crystal Reports with Visual Studio/Web applications & during this lockdown, hardly getting much replies from other technical support sites.
Appreciate your time & replies.
regards,
Rajesh
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
If this is a web app, you'll need to store the report in a session variable. There used to be a link to instructions for how to do this on the Crystal for VS wiki, but the link isn't working right now.
don.williams, the link to KB article 2007224 in the Wiki isn't working - is there a new version of this?
-Dell
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello Dell
Thank you very much for the reply. Well, I figured out the issue & working towards a better approach right now.
It looks like, while a stored procedure is used, the ONLY possibility to authenticate is to use integrated authentication. Once I created a new connection with integrated security "True", the report executed without creating additional tantrums. However, I cannot deploy the same on the production environment where the integrated security cannot be implemented.
Hence I have started looking towards using datatables created using stored procedures & manipulating the database logon from code behind for the report. Looks promising.
regards,
Rajesh
In general, I use separate "reporting" credentials to the database for reports. This user has read, run stored proc, and run store function rights. Then you would update your login code to set the server, user ID, and password for this account. How you store the account information is up to you - I usually use an application config file and might have the password encrypted.
The account password is NOT stored in the report itself, so you have to set it in code.
-Dell
I was trying out what you have recommended about loading reports to Session variables. Well, I was able to attach the report to Crystal Report viewer from Session, however each Next page/Previous page navigation causes a post back, the saved session is loaded back to the viewer & cannot navigate away from the 2nd page.
It looks like I need more coding on the postback section to handle it. Would you please point me towards some sample coding?
regards,
Rajesh
Greetings dell.stinnett-christy
Sorry for the delayed reply. Well, the link shared by Don is towards the SAP documentation in general? This comment is to update the thread. Finally I figured out how the recommended "session" and page_init within the Crystal Reports works & finished my project successfully.
I will post the sample as an answer the earliest possible. Thanks once again.
regards,
rajesh
User | Count |
---|---|
71 | |
21 | |
9 | |
7 | |
6 | |
6 | |
4 | |
4 | |
4 | |
3 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.