Crystal Report over ASP.Net runtime data source change - asp.net

Got a script to run crystal report over ASP.Net, export and send to email.
If I use the current database without applying logon everything works but if I change datasource (same database structure but different server) at runtime then the issue below.
Crystal 2008 runtime
ERROR:System.Runtime.InteropServices.COMException (0x80042018): The
table %1 does not exist in the document. at
CrystalDecisions.ReportAppServer.Controllers.DatabaseControllerClass.VerifyTableConnectivity(Object
Table) at
CrystalDecisions.CrystalReports.Engine.Table.TestConnectivity() at
ScriptCodeClass.ApplyLogon(ReportDocument cr, ConnectionInfo ci) at
ScriptCodeClass.Logon(ReportDocument cr, String server, String db,
String id, String pass) at ScriptCodeClass.FunCreatePDFView(String
lsHeader, String lsReportType, String msDatabaseUserId, String
msDatabasePassword)
this code can change authentication but not data source/server, wondering if need a reference or to import.
Imports System.Collections
Imports System.Data
Imports T1.Tb.Data
Imports System.IO
Imports System.Net
Imports System.Net.Mail
Imports T1.Tb
Imports T1.TB.Public
Imports CrystalDecisions.CrystalReports.Engine.ReportDocument
Imports CrystalDecisions.ReportSource
Imports System.Configuration
Imports System.Data.SqlClient
Imports CrystalDecisions.CrystalReports.Engine
Imports CrystalDecisions.Shared
References CrystalDecisions.CrystalReports.Engine
References CrystalDecisions.Shared
References System.Web.Services
References System.Data
References T1.Tb.dll
References T1.TB.Public
References T1.P1.dll
References T1.P1.Public
References T1.Tb.Fun
public shared function Logon(cr as ReportDocument, server as string, db as string, id as string, pass as string) as Boolean
'Use this to change the database logon info for a crystal report
dim ci as ConnectionInfo = new ConnectionInfo()
dim subObj as SubreportObject
ci.ServerName = server
ci.DatabaseName = db
ci.UserID = id
ci.Password = pass
if ApplyLogon(cr, ci) then
for each obj as ReportObject in cr.ReportDefinition.ReportObjects
If (obj.Kind = ReportObjectKind.SubreportObject) Then
// if typeof obj.Kind.GetType() is CrystalDecisions.Shared.ReportObjectKind then
subObj = ctype(obj, SubreportObject)
if not ApplyLogon(cr.OpenSubreport(subObj.SubreportName), ci) then
return(false)
end if
end if
next
Logon = True
end if
end function
private shared function ApplyLogon(cr as ReportDocument, ci as ConnectionInfo ) as Boolean
dim li as TableLogOnInfo
dim success as Boolean
for each tbl as Table in cr.Database.Tables
li = tbl.LogOnInfo
li.ConnectionInfo = ci
tbl.ApplyLogOnInfo(li)
'check if logon was successful
'if TestConnectivity returns false, check logon credentials
if tbl.TestConnectivity() then
'drop fully qualified table location
if tbl.Location.IndexOf(".") > 0 then
tbl.Location = tbl.Location.Substring(tbl.Location.LastIndexOf(".") + 1)
else
tbl.Location = tbl.Location 'THIS IS LINE LEFT OUT IN ALL SAMPLES I SAW
end if
else
success = false
exit for
end if
success = True
next
end function

try to build the query as string in code first then pass its results to crystal reports to have the report and send it by email.
steps:
1) build a query string.
2) execute that string and fill a datatable inside a dataset with the results
3) use that dataset / datatable to generate the report in crystal reports

You have several choices:
Add Key(s) in web.config as follow :
<add key="ServerName" value=""/> Name Or IP Address
<add key="DataBaseName" value=""/> Database Name
<add key="DatabaseUser" value=""/>User Name
<add key="DatabasePassword" value=""/>Password
and call these keys in your reportviewer on load or on your event as :
Dim SERVER_NAME As String = ConfigurationManager.AppSettings("ServerName").ToString()
Dim DATABASE_NAME As String = ConfigurationManager.AppSettings("DataBaseName").ToString()
Dim DatabaseUser As String = ConfigurationManager.AppSettings("DatabaseUser").ToString()
Dim DatabasePassword As String = ConfigurationManager.AppSettings("DatabasePassword").ToString()
add your code and login to DB
CrystalReportViewer.SetDatabaseLogon(DatabaseUser, DatabasePassword, SERVER_NAME, DATABASE_NAME)
then add your datasource:
CrystalReportViewer.SetDataSource
Or you can pass it directly through your viewer as follow:
CrystalReportViewer.SetDatabaseLogon("sa", "123", "Your_Server", "YourDB")

Related

Using Selenium to scrape from Azure web app

I have successfully used Selenium from the localhost on my PC and retrieved data from the target URL but I need to be able to do this from a web app hosted in Azure. The problem I encounter is the message that ChromeDriver.exe cannot be located. If I look at the results of my build, there is a copy located in the bin folder but I don't know if this is published to the server and how I would tell the server where it was.
If the app could find the ChromeDriver, I anticipate the next error would be 'cannot locate binary'. I have commented out the binary location because I don't know how I would make Chrome available on Azure.
I can't find any examples of anyone else employing the same environment. I include a code extract.
Imports System.Net
Imports OpenQA.Selenium
Imports OpenQA.Selenium.Chrome
Imports OpenQA.Selenium.Support.UI
Public Class Scraper
Inherits System.Web.UI.Page
Public Function ScrapeToChrome(ByVal url As String) As String
Dim LinkList As List(Of String) = New List(Of String)()
Dim options = New ChromeOptions() 'With {
' .BinaryLocation = "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
' }
options.AddArguments(New List(Of String)() From {
"headless",
"disable-gpu"
})
Dim browser = New ChromeDriver(options)
Dim wait As WebDriverWait = New WebDriverWait(browser, TimeSpan.FromSeconds(10))
browser.Navigate().GoToUrl(url)
browser.FindElement(By.Id("txtSurname")).SendKeys("Mahony")
browser.FindElement(By.Id("txtPhoenixID")).SendKeys("5258242")
browser.FindElement(By.XPath("//*[#id='divSearchBox']/div/div/div[1]/form")).Submit() 'Id("btnSearch"))
Dim elementToBeDisplayed As IWebElement
wait.Until(Function(condition)
Try
elementToBeDisplayed = browser.FindElement(By.Id("divSearchResults"))
Return elementToBeDisplayed.Displayed
Catch __unusedStaleElementReferenceException1__ As StaleElementReferenceException
Return False
Catch __unusedNoSuchElementException2__ As NoSuchElementException
Return False
End Try
End Function)
Return elementToBeDisplayed.Text
End Function
End Class

Accessing SQL Server database from multiple webpages through asp.net

I am a new developer.
I have a problem of creating a website that needs to access one user account and retrieve all his information in that database through different webpages like one page for viewing his profile data; another page to view the exams that he already created ... etc.
What I did was for each single aspx page I had to create a new object and connect to the SQL Server database from that object which I feel there's something wrong with that.
The question is there any way that I can define the database object only once and make it accessible from different webpages in the same website and execute SQL queries from that object and retrieve data?
Thanks
We use this implementation using MVC...maybe you could adapt it to your needs:
clsConnectionManager
Imports System.Collections.Generic
Imports System.Linq
Imports System.Web
Imports System.Data.SqlClient
Imports System.Web.Configuration
Imports System.Data
Public Class clsConnectionManager
Implements IDisposable
<ThreadStatic> _
Private Shared pSqlConnection As SqlConnection
Private Shared pConnectionString As String
Public Shared ReadOnly Property Connection() As SqlConnection
Get
If pSqlConnection Is Nothing Then
pConnectionString = WebConfigurationManager.ConnectionStrings("DefaultConnection").ConnectionString
pSqlConnection = New SqlConnection(pConnectionString)
pSqlConnection.Open()
End If
If pSqlConnection.State = ConnectionState.Closed Then
pSqlConnection.Open()
End If
Return pSqlConnection
End Get
End Property
Public Sub Dispose() Implements System.IDisposable.Dispose
If pSqlConnection IsNot Nothing Then
pSqlConnection.Close()
End If
End Sub
End Class
Web.config
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=localhost;Initial Catalog=yourDBName;User ID=YourDBUserName;Password=YourUserPassword" providerName="System.Data.SqlClient" />
</connectionStrings>
Use
Inside your classes you could do something like this:
Public Sub dbGetAll()
Try
Using New clsConnectionManager()
Using lObjSQLCommand = New SqlClient.SqlCommand("StoredProcedureName", clsConnectionManager.Connection)
lObjSQLCommand.CommandType = CommandType.StoredProcedure
Using lObjSqlDataReader As SqlClient.SqlDataReader = lObjSQLCommand.ExecuteReader()
Do While lObjSqlDataReader.Read()
/*Read rows...*/
Loop
End Using
End Using
End Using
Catch ex As Exception
Throw ex
End Try
End Sub
You can define the connection settings in the web.config file and access the same in your.aspx page.
Refer http://www.connectionstrings.com/store-connection-string-in-webconfig/

Switching databases with LINQ to SQL with proper authentication

I'm writing an ASP.NET (VS2013) web app that uses LINQ to SQL. The datacontext is created via the graphical interface and it works great. I need to switch from DEV to INT and then to PROD programmatically.
sounds simple and after reading many, many postings I'm super frustrated.
When I switch to DEV it works because the connection already exists. when I switch to INT it fails but NOT because the authentication but because the the Store Procedure doesn't exist... that makes NO sense...
can anyone please help me with tested statements??? (i already tried lots of "I think...")
----WP_LINQ2SQLDB.DESIGNER.VB----
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Data.Linq
Imports System.Data.Linq.Mapping
Imports System.Linq
Imports System.Linq.Expressions
Imports System.Reflection
<Global.System.Data.Linq.Mapping.DatabaseAttribute(Name:="WorkOrder")> _
Partial Public NotInheritable Class WP_LinQ2SQLDataContext
Inherits System.Data.Linq.DataContext
Private Shared mappingSource As System.Data.Linq.Mapping.MappingSource = New AttributeMappingSource()
#Region "Extensibility Method Definitions"
Partial Private Sub OnCreated()
End Sub
#End Region
Public Sub New()
MyBase.New("", mappingSource)
OnCreated()
End Sub
Public Sub New(ByVal connection As String)
MyBase.New(connection, mappingSource)
OnCreated()
End Sub
etc...
----WP_LINQ2SQLDB.VB----
Inherits System.Data.Linq.DataContext
Private Sub OnCreated()
Dim connectionStr As String = Nothing
Select Case My.Settings.DB_to_Use
Case "DEV"
Case "INT"
connectionStr = "Data Source=SERVER\DBINST;Initial Catalog=CAT_Order;Integrated Security=True;"
Case "PRD"
End Select
Dim DB_TUAcct = My.Settings.DB_TUAcct
Dim DB_TUPwd = My.Settings.DB_TUPwd
connectionStr = connectionStr + "User ID=Domain\blah" + DB_TUAcct.ToUpper + ";Password=" + My.Settings.DB_TUPwd + ";"
----DEFAULT.VB----
' I've tried...
Dim dc As WP_LinQ2SQLDataContext = New WP_LinQ2SQLDataContext(temp)
Dim dc As WP_LinQ2SQLDataContext = New WP_LinQ2SQLDataContext(builder.ConnectionString)
' building a connection string from sql builder
Dim builder2 As IDbConnection = New SqlClient.SqlConnection(temp)
dc.Connection.ConnectionString = builder.ConnectionString
BUT at the end of the day, I cannot make the LINQ to fail because the connection string is bad... and I dont know to fix...

Crystal Report convert to PDF (Error The logon to the database failed. ((0x8004100f)))

In my application I have some code to convert to PDF. In debug mode all is good and working but when I test it on then server I keep getting the logon to the database failed. I have no idea why I get the error becase the login and password are 100% ok.
tried 2 ways for the server of sending the report
SetCrystalReportFilePath(Server.MapPath("~/MemberPages/Report.rpt"))
SetPdfDestinationFilePath(Server.MapPath("~/MemberPages/Report_" & Report & ".pdf"))
SetRecordSelectionFormula("{Report.Report_id} =" & ID)
Transfer()
SetCrystalReportFilePath("C:\inetpub\wwwroot\Werkbon.rpt")
SetPdfDestinationFilePath("C:\inetpub\wwwroot\Werkbon_" & werkbonnr & ".pdf")
SetRecordSelectionFormula("{werkbon.werkbon_id} =" & werkbonnr)
Transfer()
Dim ConInfo As New CrystalDecisions.Shared.TableLogOnInfo
Dim oRDoc As New ReportDocument
Dim expo As New ExportOptions
Dim sRecSelFormula As String
Dim oDfDopt As New DiskFileDestinationOptions
Dim strCrystalReportFilePath As String
Dim strPdfFileDestinationPath As String
Public Function SetCrystalReportFilePath(ByVal CrystalReportFileNameFullPath As String)
strCrystalReportFilePath = CrystalReportFileNameFullPath
End Function
Public Function SetPdfDestinationFilePath(ByVal pdfFileNameFullPath As String)
strPdfFileDestinationPath = pdfFileNameFullPath
End Function
Public Function SetRecordSelectionFormula(ByVal recSelFormula As String)
sRecSelFormula = recSelFormula
End Function
Public Function Transfer()
oRDoc.Load(strCrystalReportFilePath)
oRDoc.RecordSelectionFormula = sRecSelFormula
oDfDopt.DiskFileName = strPdfFileDestinationPath
expo = oRDoc.ExportOptions
expo.ExportDestinationType = ExportDestinationType.DiskFile
expo.ExportFormatType = ExportFormatType.PortableDocFormat
expo.DestinationOptions = oDfDopt
oRDoc.SetDatabaseLogon("databasename", "password")
oRDoc.Export()
End Function
Crystal is very particular when swapping in and out connection information (especially with sub-reports if you have any). It's always been a sore spot that they haven't really made any better over the years. I have a blog entry I've shared that has extension methods I created (in VB.Net) to easily load and swap in new connections (typically I use ADO for the connection in the report). The extension methods can be found in this link (and below is an example of how to use them, ignore the System.Diagnostics line if you're using this from ASP.NET). Hope this helps.
http://www.blakepell.com/Blog/?p=487
Using rd As New ReportDocument
rd.Load("C:\Temp\CrystalReports\InternalAccountReport.rpt")
rd.ApplyNewServer("serverName or DSN", "databaseUsername", "databasePassword")
rd.ApplyParameters("AccountNumber=038PQRX922;", True)
rd.ExportToDisk(ExportFormatType.PortableDocFormat, "c:\temp\test.pdf")
rd.Close()
End Using
System.Diagnostics.Process.Start("c:\temp\test.pdf")

Update SINGLE field of a table in Access db

How do you update a single field in an Access database using an asp.net website in VisualStudio08. Assuming that the connection has been established, give step to step instructions of what to do in the design view.
Here is a console app that shows you how to use ADO.NET to update an Access DB.
An alternate is to use Linq.
You could add a method to your CodeBehind that does something like this, and call it from your OnClick event handler.
Option Explicit On
Option Strict On
Imports System
Imports System.Data
Imports System.Data.OleDb
Public Class Program
Public Shared Sub Main()
Dim connectionString As String = GetConnectionString()
Dim queryString As String = _
"UPDATE Categories Set CategoryName = 'ABC' WHERE CategoryID = 1;"
Using connection As New OleDbConnection(connectionString)
Dim command As OleDbCommand = connection.CreateCommand()
command.CommandText = queryString
Try
connection.Open()
Dim rowsAffected As Integer = command.ExecuteNonQuery()
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Using
End Sub
Private Shared Function GetConnectionString() As String
' To avoid storing the connection string in your code,
' you can retrieve it from a configuration file.
' Assumes Northwind.mdb is located in c:\Data folder.
Return "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" _
& "c:\Data\Northwind.mdb;User Id=admin;Password=;"
End Function
End Class
Assuming you want this done on some postback event like a button click, you need to (this is from memory, I don't have it in front of me!):
click on the button, show its properties, then the events tab.
double-click in the OnClick space to create a new event handler (or enter a name directly)
In the event handler in the code window, invoke some SQL something like
update table set field=value where field2=identifier
(or you could use the LINQ equivalent) Where table, field, field2, value and identifier should be replaced with specific names to suit your database.
You could create a SqlCommand::ExecuteNonQuery instance to run the SQL.

Resources