crystal reports in asp.net - Page keeps loading - asp.net

I am new to crystal reports. I have been having this problem for quite some time and can't seem to solve it. What I am doing is running a report and sending back the generated PDF in the response.
The problem is, when I run the asp.net page (which runs the report) from the browser it works fine for the first or second time but then after that, the browser just keeps waiting and I do not get any response back from the server, not even an error! It just keeps loading for a long time. I even did a clean re-install of the server but still have the same issue. I was not having this problem during initial testing of this page.
Crystal reports is being unpredictable and I am not sure if this is because the reports are not being closed properly or the connection is not proper.
Windows Server 2003 - IIS
Here is the vb.net page -
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim connectionInfo As New ConnectionInfo
connectionInfo.ServerName = "UID=abc;PWD=abc;Driver= {SQL Server};Server=" & Page.Request.QueryString("server") & ";Database=" & Page.Request.QueryString("database")
Using report As New ReportDocument
report.Load(Server.MapPath("/report/Crystal/test.rpt"))
report.FileName = Server.MapPath("/report/Crystal/test.rpt")
SetDBLogonForReport(connectionInfo, report)
report.SetParameterValue("param1", Page.Request.QueryString("param1"))
Dim oStream As New MemoryStream()
oStream = report.ExportToStream(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat)
Response.Clear()
Response.Buffer = True
Response.ContentType = "application/pdf"
Response.BinaryWrite(oStream.ToArray())
report.Close()
End Using
Response.Flush()
Response.End()
End Sub
Private Sub SetDBLogonForReport(ByVal connectionInfo As ConnectionInfo, ByVal reportDocument As ReportDocument)
Dim tables As Tables
tables = reportDocument.Database.Tables
For Each table As CrystalDecisions.CrystalReports.Engine.Table In tables
Dim tableLogonInfo As New TableLogOnInfo
tableLogonInfo = table.LogOnInfo
tableLogonInfo.ConnectionInfo = connectionInfo
table.ApplyLogOnInfo(tableLogonInfo)
Next
End Sub
</div>
</form>

First off, put the call to report connection in the Page_Init() event, not Page_Load(). Prior to .NET 2005 it was okay to put it in Page_Load(). But now they changed how memory is managed and this can give you random errors depending upon the state of the CrystalReportViewer's memory. Putting it in Page_Init() is safe all the time.
Secondly, I would do is remove the code:
CrystalReportViewer1.DataBind();
I would also remove the RefreshReport() call b/c it refreshes itself automatically when you assign the report object to it. But it doesn't hurt to have it. Either way, definitely get rid of the .DataBind() call.
Hopefully these changes will get your application back to working.
For more detail Please check below link I face same problem year ago. Hope it's helpful
LInk

Related

dropdownlist selectedvalue doesnt change

I have this dropdownlist, this one load with the data that I get from a store procedure, as you can see the load is correct, but when I change the selected value in the debug the selected value doesnt change, it stays in the first loaded value, which in this case is 1. What can I do?
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim adaptador As New SqlDataAdapter
Dim datos As New DataTable
Dim ord As SqlDataReader
Conexiones.AbrirConexion()
Conexiones.Cnn.Open()
Dim cmd As SqlCommand = New SqlCommand("sp_devolver_empresas", Conexiones.Cnn)
cmd.CommandType = CommandType.StoredProcedure
ord = cmd.ExecuteReader
datos.Load(ord)
cbEmpresas.DataSource = datos
cbEmpresas.DataTextField = "Nombre"
cbEmpresas.DataValueField = "Identificador"
cbEmpresas.DataBind()
Conexiones.Cnn.Close()
End Sub
For EVERY web page that you build and write to the end of time?
You MUST always put the load and setup code inside of a check for post back.
every button, every drop down list, and EVERY time you click on a button or do anything, the page load will ALWAYS fire and run. Thus if you change a value, you will lose that value since the page setup and loading of say control (in this case your dropdown list) will fire EACH time - thus overwriteing.
Out of the last 100's of web pages, the FIRST thing I write is the check for postback.
So, your code should look like this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadData
End If
End Sub
Sub LoadData()
Dim datos = New DataTable
Using onexiones.Cnn
Using cmd As SqlCommand = New SqlCommand("sp_devolver_empresas", onexiones.Cnn)
cmd.CommandType = CommandType.StoredProcedure
onexiones.Cnn.Open()
datos.Load(cmd.ExecuteReader())
End Using
End Using
cbEmpresas.DataTextField = "Nombre"
cbEmpresas.DataValueField = "Identificador"
cbEmpresas.DataSource = datos
cbEmpresas.DataBind()
End Sub
So, only on the "real" first page load do you want to load up your grids, dropdowns etc. Remember, even a simple button dropped on to the page, and you have a click event? (the page load event fires each time - and every time). So once again, you need the IsPostBack test - and I am quite pressed to find any of my web pages that does not have this all important code stub in the on-load event.
So, remember the above rule - always setup your setup code to run on first time - not every time a button or anything else occurs on the web page. So, page load (unlike desktop) fires each and every time you do ANY operations on that page.
Also, note how I setup the data text, and value field BEFORE we give the drop down list a data source. In fact, I would suggest you put the data text, and data value field in the markup and NOT code (since then multiple different code routines can use that setting - not hard coded in code).
eg do this:
<asp:DropDownList ID="cbEmpresas" runat="server"
DataTextField = "Nombre"
DataValueField = "Identificador" >
</asp:DropDownList>
So, now your code becomes :
cbEmpresas.DataSource = datos
cbEmpresas.DataBind()
I suppsoe some out of habt like to set the text + data settings for the dropdown list in code, but then again, in code you might want more then one palce that loads up the combo box - and thus you now have multiple places for those two settings. And better yet, you can even use the property sheet during design time to make the settings. (this is a "minor" issue, but I just perfer those settings in the markup as opposed to writing them in code for text/data settings).
At the end of the day? Just remember that golden rule: have that "test" for postback so you have a REAL first page load event code inside that if/then. In fact, you really can't even build a fnctional working web page if you break this rule. As noted, I count about 1-2 of my web pages out of 100's tht don't have that not postback code stub. It is quite much as important say compared to humans having to breathe air to function.
And why such a long post about this simple issue? Well on a near daily bases, both c# and vb.net questions are posted about how some combo box, grid view or just about anything else is "broken" and not working. And the answer 9 out of 10 times?
The developer forgot to use a Not IsPostBack code stub in their page load code.
If I was teaching asp.net, this would be the first lesson - ALWAYS use and consider the requirement for the Not IsPost back stub. You need that in 99% of your web pages. Or at the very least in ANY web page in which you have code to run on page load to setup grids, dropdowns, repeaters - don't matter what, you will NEED that code stub. So important, I often wonder if they should have create a even called first page load? It would have eliminated the daily posts and questions on SO that fail as a result of not heeding the above simple advice.
Edit: Now how to get selected value in code
Ok, now that we fixed up the code to setup the dropdown list, we now want to get in our code the value when the user makes a choice in the dropdown list.
You of course have code to fill the dropdown, BUT we also have to set autopostback = true for this dropdown.
So, say code to load:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadData
End If
End Sub
Sub LoadData()
Using conn As New SqlConnection(My.Settings.TEST4)
Dim strSQL As String =
"SELECT ID, HotelName from tblHotels ORDER BY HotelName"
Using cmdSQL As SqlCommand = New SqlCommand(strSQL, conn)
conn.Open()
Dim rstData As New DataTable
rstData.Load(cmdSQL.ExecuteReader)
cboHotels.DataSource = rstData
cboHotels.DataBind()
End Using
End Using
End Sub
And now the selected index changed event:
so, our debug output would then look like:
output:
combo selected value = 82
combo selected Text = Canadian Rocky Mountain Resorts
And as noted, make sure you set auto-post back true in the property sheet, or in the markup. The combo box for above in markup thus is this:
<asp:DropDownList ID="cboHotels" runat="server"
DataValueField="ID"
DataTextField="HotelName" AutoPostBack="True">
</asp:DropDownList>

Downloading files from the server

Currently I have stored on a BD files of any type in binary format. The process I do in the file upload is as follows:
Drag & Drop files and collects is sent to the server.
In the server collects the stream of each file.
Each stream is converted to byte ()
It almancena the Byte () in BD Correctly
Now, it's time to download the files, which consists of obtaining the data from the database in Byte (), and downloaded directly from the customer.
The problem is that I am using methods not throw any download window and I'm not making that mistake. Deputy code for possible help.
Protected Sub grdDocumentoByExp_RowCommand(sender As Object, e As GridViewCommandEventArgs)
If e.CommandName = "cmdDownload" Then
Dim context As System.Web.HttpContext = System.Web.HttpContext.Current
Dim lFileName As String = e.CommandName
Dim lFile() As Byte = GetImageArrayBy_docID(e.CommandArgument)
Dim ms As Stream = New MemoryStream(lFile, 0, lFile.Length)
ms.Position = 0
ms.Close()
With context
.Response.Clear()
.Response.ClearHeaders()
.Response.ClearContent()
.Response.ContentType = "image/jpeg"
.Response.AddHeader("content-disposition", "attachment;filename=" & "Fichero1.jpg")
.Response.AddHeader("content-length", lFile.Length)
.Response.BinaryWrite(lFile)
.Response.End()
End With
End If
End Sub
The idea is as follows:
A grid has a column that runs a command, run this code block.
In it, collects the byte () from the database (which appears to be correct in content), is transmitted to a Stream and sent through the current context as BinaryWrite, but never run anything in the browser .
The client used is Firefox and Chrome, but none of them anything happens. Indicate that I am going as we see, the MIME file, which in this case is jpeg, although there are many other types.
Can anyone know what is happening or I can be doing wrong?
Thank you very much.tiendo. Attach code for possible help.
Dim ms As Stream = New MemoryStream(lFile, 0, lFile.Length)
cast the length to (int)
The Problem not is the conversion of types, because lFile.Lenght it's INT. The problem has been that the method it's launched into a UpdatePanel and this don't launch corrrectly.
Make the download in other page work's fine.

SQL Server vs .Net Client - Best practice of returning Huge Data from server - Performance Improvement

I am attacking performance issues in an Enterprise application. One of my SQL Proc returning More than 2 MB of data (XML plain text). For executing that SP Its taking around 600 ms only with in the DB server. But, Its taking around 30 seconds to get response in my UI.
SQL server 2008 / .NET 4.0 (IIS hosted windows application)
Note : In previous performance iterations - Too many DB calls clubbed together and hence avioded many DB calls. But now returning data is huge and facing this issue.
Please help on to identify any standard or restrictions best practices available here to improve performance.
Based on the comments received below thought of add this here:-
But I have found this while I am executing the same Sp call from my local SQLserver Query analyser with connectivity of onsite server. 2. Its not a intranet, but communication between US/India through Internet. 3. I analysed thouroughly using dottrace tool and source too. 4. There is no bottle neck of binding this data. Previousely around 15 Db calls were there with in Loop (every call carries small # of Kbs), but now reduced in to clubbed single call but carries large Data in MB.
Regards,
Karthikeyan.G
Certainly looks like the UI binding. 2Mb over the internet is unlikely to take 30 seconds but it could depending on your connection speed.
Considering it only takes 600ms to perform the SP it is a little long so it would be preferable to cache it. 2MB isn't much to cache anyway (as long as its not per user).
Get the 2MB of data, cache it, split it. Such as get the first 100 records, then bind those rows to your UI control and implement paging.
However without the code, I can't see what type and the depth of the data you are binding to what type of control.
You can use the asynchronous programming:
Dim connectionString As String = "server=.\SQLEXPRESS; database=master; Integrated Security=true; Asynchronous Processing=true"
Private Sub btnDisplayCustomersCallback_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDisplayCustomersCallBack.Click
Dim sqlConnection As New SqlConnection(connectionString)
Dim sqlCommand As SqlCommand = sqlConnection.CreateCommand()
Dim asyncResult As IAsyncResult
'Example of Asynchronous Callback Model
sqlCommand.CommandText = "SELECT * FROM [customer]"
sqlCommand.CommandType = CommandType.Text
sqlConnection.Open()
btnDisplayCustomersCallBack.Enabled = False
Dim callback As AsyncCallback = New AsyncCallback(AddressOf DisplayCustomers)
asyncResult = sqlCommand.BeginExecuteReader(callback, sqlCommand, CommandBehavior.CloseConnection)
End Sub
Private Sub DisplayCustomers(ByVal result As IAsyncResult)
Dim dr As SqlDataReader
Dim command As SqlCommand
Dim del As DelFillGrid
Try
command = CType(result.AsyncState, SqlCommand)
dr = command.EndExecuteReader(result)
del = New DelFillGrid(AddressOf FillGrid)
Threading.Thread.Sleep(5000)
Me.Invoke(del, dr)
Finally
If (Not dr.IsClosed) Then
dr.Close()
End If
End Try
End Sub
Private Sub FillGrid(ByVal dr As SqlDataReader)
Try
Dim dt As New DataTable()
dt.Load(dr)
Me.DataGridView1.DataSource = dt
Catch ex As Exception
' Because you're guaranteed this procedure
' is running from within the form's thread,
' it can directly interact with members of the form.
Finally
btnDisplayCustomersCallBack.Enabled = True
If dr IsNot Nothing Then
dr.Close()
End If
End Try
End Sub
In this, application will generate a ExecuteReader request in asynchrnous method and when the result is got the grid is filled. Till that time application do further processing.

Creating a dynamic graphic in asp.net

I am busy creating a control in asp.net. The control consists of some text and an image. The image will be used to display a graph. The control gets the data for the graph by reading it from a database. It seems I have two options to display the graph in the image box. First, I can create a jpg from the data and save the file on the server. I can then load this file into the image box. I think this would cause a problem if various users try to access the site at the same time, so I don't think it is a good option. The other options is to create a file called output, that outputs the graph like this: objBitmap.Save(Response.OutputStream, ImageFormat.Gif)
I can then display the image like this in my control: Image1.ImageUrl = "output.aspx"
The problem that I am facing is how do I get the data from my control to the output page? As far as I know it is too much data to pass as a parameter. If there is another better method of doing it, please let me know
Thanks
You can write the image content to the response of output.aspx. Something like this (taken from one of my existing GetImage pages:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim strFilename As String
strFilename = Request.QueryString("filename")
Dim strPath As String = AppSettings("ProxyImageSavePath") & strFilename
Response.Clear()
Response.ContentType = "image/jpeg"
If Not IO.File.Exists(strPath) Then
'erm
Response.Write("file not found")
Else
Response.WriteFile(strPath)
End If
Response.End()
End Sub
Edit: I've just realised this may not be the solution you're looking for; Your webserver should be able to cache this though.
You need handlers. See in this article, Protecting Your Images, section "Creating the ImageHandler HTTP Handler", you'll find the code how to write the handler, so it outputs an image. You don't need all, it's only an example.
You also need to register the handler in the web.config.
To reference it Image1.ImageUrl = "handler.ashx?graphdata=xxxx". Use QueryString to get the data source to generate the graph.

Issue when trying to show/hide parameters in ASP.NET ReportViewer control

I have an SSRS report that is displayed to users in the ASP.NET ReportViewer control. The report has many parameters and we're using the parameter prompts that the ReportViewer control offers. Depending on a certain parameter of the report, we only need to have the user prompted for a subset of the rest of the report parameters.
We could have used linked reports and hide the appropriate parameters, but there are many possible combinations to that first parameter (it's multi-valued), so we'd rather not do that. Instead, we have an ASP.NET ListBox that controls the first parameter and when it's selection is changed, we are using the ReportViewer.ServerReport.SetParameters() function to hide/show parameters (it takes in an array of ReportParameter and the ReportParameter constructor takes in a boolean to hide/show the parameter).
Here's the issue. Everything works fine in our development environment. When we deploy the report and the ASP.NET site to the production environment, parameters never get shown when those SetParameters() calls are invoked. We know the code is called because we put some debugging output to make sure. The code to hide parameters is working fine. It's just the code that should cause certain parameters to show up again doesn't work. Not only does it not show up the parameter prompts, but the Visible property of the parameter does not get set to true (checked by using ReportViewer.ServerReport.GetParameters()).
We have SQL Server 2005 SP3 installed in both environments, and the same version of the report viewer control (Microsoft.ReportViewer.WebForms.dll). Any ideas what could be wrong? Any workaround ideas? If you have questions, leave comments.
Edit: After further investigation, we isolated the problem further. I made a simple report with just 1 parameter without any DB connection. Then I made an aspx page with 2 buttons and a ReportViewer control hooked up to that report. 1 button hides the parameter and 1 button shows the parameter (using the SetParameters() function, as mentioned above). Even with this simple scenario, the hide/show buttons work fine in the development environment, but we still have the same issue in the production environment (the show button doesn't work). We also tried this on another server on the network in the production environment, and we have the same issue. So everything seems to work fine in the development environment, but on 2 different servers outside that environment we seem to be getting the same issue.
Edit2: Below is the code behind for the test report page. The page has a ReportViewer, 2 Buttons, and a Label for debug output. When the showing of hidden parameters doesn't work, the Label even shows that the Visible property is still false after the call to ShowParameter.
Public Partial Class TestReportPage
Inherits System.Web.UI.Page
Public Sub HideParameter(ByVal parameterName As String)
Dim parameters As ReportParameterInfoCollection = ReportViewer1.ServerReport.GetParameters()
ReportViewer1.ServerReport.SetParameters(New ReportParameter() {New ReportParameter(parameterName, GetParameterDefaults(parameterName, parameters), False)})
parameters = ReportViewer1.ServerReport.GetParameters()
lblTest.Text &= "Hide param " & parameterName & "; Is Visible: " & parameters(parameterName).Visible & "<br>"
End Sub
Public Sub ShowParameter(ByVal parameterName As String)
Dim parameters As ReportParameterInfoCollection = ReportViewer1.ServerReport.GetParameters()
ReportViewer1.ServerReport.SetParameters(New ReportParameter() {New ReportParameter(parameterName, GetParameterDefaults(parameterName, parameters), True)})
parameters = ReportViewer1.ServerReport.GetParameters()
lblTest.Text &= "Show param " & parameterName & "; Is Visible: " & parameters(parameterName).Visible & "<br>"
End Sub
Public Shared Function GetParameterDefaults(ByVal parameterName As String, ByVal parameters As Microsoft.Reporting.WebForms.ReportParameterInfoCollection) As String()
Dim paramDefaults() As String = {}
Dim i As Int16 = 0
For Each paramValue As String In parameters(parameterName).Values
ReDim Preserve paramDefaults(i)
paramDefaults(i) = paramValue
i = i + 1
Next
Return paramDefaults
End Function
Protected Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
HideParameter("foo")
End Sub
Protected Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
ShowParameter("foo")
End Sub
End Class
Just for anyone else who ever has this issue, here's the reason we were having this issue:
The issue was due to a difference in the environments. Even though we had the ReportViewer DLL being copied into the bin folder of the project (and thus copied to where the project was hosted), this issue w/the params is a bug in older versions of the ReportViewer control. You need to get the Microsoft Report Viewer Redistributable 2005 SP1 to fix this issue. Apparently we had this fix installed in the development environment. For some reason the ReportViewer DLL was the same version on both sides though. This could be because the DLL was actually being accessed from a different location.

Resources