Utilize a 3rd Party API in VB.NET - asp.net

I know this may be a simple answer or at least to most people but I'm not getting anywhere when attempting this on my own or through the various resources I have looked up. I'm pretty sure I'm just physically searching the wrong terminology or phrases to get my answers.
Here is my issue:
I am using ASP/VB.NET to build this integration. Visual Studio 2008. I previously had asked a question on API Integration on here and utilized that information to successfully perform the next steps. As this API is written differently I may not be grasping the appropriate functions correctly.
A company has given me several addresses for .ASMX portals. I add these into my service references. I can successfully see objects in my object browser and see all the procedures, etc., but further from here I'm unable to correctly use any objects. I attempted to replicate the integration based on my last API question and advice: Connecting to an API offered by a Company. When I'm attempting to use an object or simply relate a field to something on my script I continually get an error.
For example:
Dim A as New API.AddFunction
A.AccountNo = "123"
When running the page:
Object reference not set to an instance of an object.
Here is only one .ASMX I was given. I cannot release any more, until I receive permission to do so from the provider, I apologize.
http://cert1.tpayment.com:14935/Terminal.asmx
Anyhow, the root of my question is really how do I correctly interface with this API? What information do responders require so I can clarify this question more? Understandably you cannot guess at the problems until more information is shared. Is there a primer I can read through online?

The word you are looking for is XML web service or SOAP web service. This will help you with getting further with finding information on how to use such API. Specifically, your task is to "consume an XML web service using ASP.NET".
By having a quick look at the sample web service you provided it looks more than manageable. However, one thing you have to always remember that a web service operates on a "request - response" basis even though it is somewhat concealed when you add it as service reference to your project and it starts to look like just ordinary classes with methods and properties.
Here's a quick example to get you started. Let's assume you have a button "Button1" and a label "Label1" on your aspx page and that you added your example service as service reference with the namespace "Terminal". Here's a little server-side code for the click event of the button:
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
Dim SoapClient As New Terminal.TerminalSoapClient
Dim Credentials As New Terminal.OnBoardCredentials
Dim DataStructure As New Terminal.TerminalDataStructure
Dim ErrorMessages() As Terminal.OBAErrorMessage
Dim result As Boolean
Credentials.UserName = "username"
Credentials.PassWord = "password"
DataStructure.AccountNo = "123"
DataStructure.TerminalID = "123"
result = SoapClient.Add(Credentials, DataStructure, ErrorMessages)
Label1.Text = result.ToString & "; " & ErrorMessages(0).ErrorCode & " : " & ErrorMessages(0).ErrorMessage
End Sub
As you can see to start working with the web service you need a SOAP client. The client will expose the methods of the service such as "AddTerminal" in the example service.
Then you need to put together the arguments for that operation, which in the case of AddTerminal are "OnBoardCredentials", "terminal" (represented by the generic TerminalDataStructure class) and "ErrorMessage). Also note that this particular operation requires an array of ErrorMessages since the web service can return more than one in a single response.
Once you have specified the properties of each argument you are ready to call the operation (i.e. send the request) and use the returned value(s) (i.e. the response).
Technically, the response of this particular operation contains an overall result of the Add operation as boolean as well as error messages if any. However, only the overall result is returned by the TerminalSoapClient.Add operation whilst the error messages are added back to your array of OBAErrorMessage.
Lastly, for demo purposes I present the results back to label on the page. When I try it I get
False; 13000 : Error during Login
since I don't have valid credentials to log in to the service.
Though very crude I hope this example helps to get you started.

Related

COM Exception for client-side object called by Classic ASP page

I have tricky problem, which I'm struggling quite a bit with.
The current solution, consists of a Classic ASP site hosted on some Win2K3 server, that calls some Client-side DLL's on XP machines coded in VB6.
These client-side DLL's then again can call some other COM objects, in this particular case it calls IBM Louts Notes (Lotus Domino Objects 1.2).
Now for different reasons these DLL's has to be converted to .NET (still x86), at this stage, this is the only change to be done. This works quite well except for one piece of code which throws an error.
COMException when calling the Lotus Notes COM object
ASP script calling the DLL
Set objLotus = CreateObject("OpenLotusNotes_FU_v2.clsMain")
sRet = objLotus.OpenLotus_mail()
Client-side DLL
Dim session As NotesSession = New NotesSession() 'works well
Dim objNotesWrkSp As Object
objNotesWrkSp = Activator.CreateInstance(Type.GetTypeFromProgID("Notes.NotesUIWorkspace")) 'crashes
Exception
Retrieving the COM class factory for component with CLSID {29131502-2EED-1069-BF5D-
00DD011186B7} failed due to the following error: 80080005
Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)).
When I try to run this code in console application on the same computer, it works. So it has to be some permissions(?), I have tried changing basically everything I can think of.
Any help would be much appreciated!
Updated 01.09.2014
What I see is when I trigger the code from ASP, is that it creates a new process of Notes everytime, but only in the background, no UI what so ever. When I trigger the code from a console application, I get the Notes UI, which asks me for password, if I don't already have notes running.
I believe that I'm getting the Exception because it eventually times out.
Have a read of this article , your dealing with an Out Of Process COM component which may not initialize properly for some reason.
Another possibility is that the COM threading model is not supported in a free threaded component which .NET is by default compiled with. You can compile you DLL with a STA attribute, but as far am I'm aware that only effects console applications. You might find some additional information in this article from MS, if you have not already read it of course. Hope something there helps you solve your problem.
Consult with your admins first, but for this scenario you can set no password for the ID the Lotus Notes uses.
I did resolve this, so if anyone else would run in to this…
First of all configure the “Notes Link” Component Service to run as a “The interactive user” and that the process owner has permissions in "Launch and Activation Permissions" and "Access permissions".
Then this should be possible
Dim objNotesWrkSp As Object
Dim objWorkspace As Type = Type.GetTypeFromProgID("Notes.NotesUIWorkspace")
objNotesWrkSp = Activator.CreateInstance(objWorkspace)
As it turned out in this particular case I could only get it to work with late-binding, when I tried to this it just opened a conhost.exe process and then never responed:
Dim session as New NotesSession
session.Initialize()
Among other similar issues... So then I only used late-binding for all communication with Notes.
Dim mailServerPath, mailFile As String
objWorkspace.InvokeMember("OpenDatabase", Reflection.BindingFlags.InvokeMethod, Nothing, objNotesWrkSp, New Object() {mailServerPath, mailFile})
And so on...

Reporting in ASP.NET

I have an SQL Database and an ASP.NET website built to put data into the database.
One of the project requirements is to build a system that would let the user upload a Crystal Report to the server and run it as needed. This way, the user could create a customized report (for then turning into management, customers) that wouldn't force them to go through a developer.
I'm looking for suggestions on how to accomplish this goal.
Currently, I'm looking for a way to redirect the database connection in the Crystal Report from the database it was developed with to the database it will eventually run on. However, There doesn't seem to be a simple way to do this.
I'm also investigating the ReportViewer object. However, all the code I have seen involves specifying the query for the report in the code, which isn't acceptable.
One option (which I don't like at all) is to let them write their own queries so they can copy the results into Excel. This would mean a blank textbox and information about the structure of the database. Not a good idea for multiple reasons.
Another option is to create one report for each table (and maybe a few extras), let the user copy the data they want into Excel, and go on their merry way.
tl;dr How do I build a flexible reporting system?
=========================================
Continuation: 08/20/2012
I have decided to go the route of b.pell's extension methods. So far, it has gotten me closer than anything else. My code to bind to the CrystalReportViewer is below:
CrystalReportSource rs = new CrystalReportSource();
rs.Report.FileName = Server.MapPath("ReportFiles/") + Request["reportname"];
string connstring = System.Web.Configuration.WebConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString;
rs.ReportDocument.ApplyCredentialsFromConnectionString(connstring);
rs.ReportDocument.ApplyNewDatabaseName("myDBName", "mySchemaName");
rs.ReportDocument.Refresh();
CrystalReportViewer1.ReportSource = rs;
This comes very close to working. It works fine on my dev machine, but when I run the code on the server, it gives the following error:
Logon failed.Error in File CrystalReport2 {5D2E82E5-783E-4DFD-A770-C8AE72A51E4E}.rpt:
Unable to connect: incorrect log on parameters. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.Runtime.InteropServices.COMException: Logon failed.Error in File CrystalReport2 {5D2E82E5-783E-4DFD-A770-C8AE72A51E4E}.rpt: Unable to connect: incorrect log on parameters. Source Error: An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
The error is in this line in the code:
crTable.Location = String.Format("{0}{1}", prefix, crTable.Location.Substring(crTable.Location.LastIndexOf(".") + 1))
When I remove the call to ApplyNewDatabaseName, I am asked to enter the Server Name, the Database name, the Username and the Password or to select Integrated Security. I can't enter the Database Name or the Server Name (those fields are disabled).
Any thoughts?
I think what you're looking for is the Reporting Services, part of Business Intelligence
Or maybe you can setup a UI that let the users pick the tables and columns they need for the report (this way you can limit the information they can access) an write a Dinamic Query Builder Function or something like that.
I answer the changing Crystal Reports connection question a lot (it's something I'd think Crystal would make easier, but I wonder if they don't because that's what their server product does). :D Anyway, you can set the database credentials at runtime. Crystal is very particular in the order it's done, but I have some code that I turned into extension methods that do the trick. This code will go through the main report and all sub reports and change the connection information. This assumes that all sub reports connect to the same database that the main report does (if not, you'll need to modify it to handle multiple connections, but this rarely comes up at least with what I do).
Extension methods to change connection info: http://www.blakepell.com/2012-05-22-crystal-reports-extension-methods
It would be used something like this (although, you're binding to a viewer probably and not exporting, so you could ignore that, this is just for example).
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")
You could use the Crystal Viewer at this point to deliver the reports and store the report in a database or on the file system (with a db meta data table) and have some predefined connections the user could select from that would be applied when it is run.
You also have the option to write your own front end. In this scenario a user would select a report from your meta data (you could put whatever security on it you wanted, I use AD). Then you can read the report parameters in and lay them out on the web form. When the user fills them in, you then sanatize them and pass them to the report via these extensions and you can output Excel, PDF, Word Doc, RTF, etc. A little more overhead and not the nice preview view, but can work well (I've done something like this in the past). Hope this helps.
About "...let them write their own queries" part of your question.
The solution can be to use some query builder component with friendly user interface which hides from users the complexity of your database and avoid any possible SQL injections.
There are few such products on the market. One of them is called EasyQuery, another one is build by Aspose if I'm not wrong. Try to search in Google for "query bulider for asp.net" or ".net query builder component".

Return values from exe in javascript

i have to call an executable in the client machine in asp.net and get the return parameters, i been looking for an example but i couldn't find it.
it this possible to recover the output parameters from one exe in JavaScript?
i know that can i write:
var WshShell = new ActiveXObject("WScript.Shell");
var oExec = WshShell.Exec("My.exe");
but the clients executable returns 0 or 1 that values are the ones i need to collect
Thanks in advance
Browser-based JavaScript can't call executable files on client machines; to do so would be a catastrophic security problem. If you have to run an executable on the client machine, consider asking the user to install a .NET application, an ActiveX control, or something like Java if you want to be platform-independent.
Depending on what you're trying to do, you may not need to run an EXE on the client machine; you can do a LOT with standard cloud-type scenarios (JS or SilverLight on the client, Web services or WCF on the server). Without more information about your situation, however, it's impossible to tell.
EDIT: Based on your comments that you're using the ActiveXObject.Exec method, you can use the StdOut property of the WshScriptExec object that method returns. From MSDN's article on the StdOut property:
if (!oExec.StdOut.AtEndOfStream)
{
input += oExec.StdOut.Read(1);
//...
}

.netCART Credit Card Decryption - IIS 7 App Pool and Decryption issue

I've got a site using .netCART. It's running fine in production with Windows Server 2003 and .NET 2.0. On the new server (Windows Server 2008) everything is working except for credit card decryption in the store admin. No errors are being sent, no exceptions thrown, just the encrypted string being output to the screen instead of a decrypted credit card number.
Dim strCCEncrypt As String
strCCEncrypt = Trim(DataRow.Item("CreditCard"))
strCCEncrypt = tools.Decrypt(strCCEncrypt) 'tools is a .netCART utility
Has anyone had experience with .netCART, or seen this issue before?
EDIT:
After much investigating yesterday, it seems as though the problem is tied to the App Pool (which is running in classic pipeline mode on .NET 2.0), and Decryption. Can anyone tell me what the processes or services are that are tied to the default app pool which help handle decryption?
Don't know where your specific problem is, but that code snippet is equivalent to this:
Dim CCEncrypt As String = tools.Decrypt(DataRow("CreditCard").ToString().Trim())
To explain the changes:
You can skip the .Item part because it's an indexer for DataRow
But you should call .ToString(), in case of other types or DbNulls
Then use the string type's .Trim() method rather than the VB Trim() function. Trim() and other old string functions exist solely for backwards compatibility. You're better off becoming accustom to the methods attached to the string type.
In .Net, it's no big deal to declare a variable and assign to it on the same line
And in .Net, Microsoft's style guidelines specifically recommend against any hungarian-notation type warts on variable names.
The end result of this problem was that I used Reflector to get the method out, provide the key manually to perform the decryption, since the decrypt method shown above just provided a call to a method that took the key.
Check the machinekey element in your web.config. Is it possible the credit cards were encrypted with a different key than you are trying to decrypt them with?

ASP.NET Connection String

I am having some trouble with one of my ASP.NET 2.0 application's connection string. There are instances that I would get a ConnectionString Property Has not Been Initialized problem which occurs randomly and intermittently and without any reason.
My Connection string is actually coming from a webservice, because different kinds of users are provided with different sets of connection string depending on their user level.
What I have done so far goes like this:
I have a master page (mstr.page) and the corresponding code behind (mstr.page.vb).
In my master page, I retrieve initially the connection string and store the same into a session variable, i.e.
Session("ConnString") = "RetrievedConnectionString"
Now in one of my pages, let us say page1.aspx.vb, I use public shared functions from a class (named MyClass.vb) and use it in my page1.aspx.vb.
Some codes for reference:
[MyClass.vb]
Imports System.Web
NameSpace ClassNameSpace
Public Class Admin
Protected Shared da as New DataAccess()
Public Shared Function MYFunction() as String
'Execute some sql statements here, using the DataAccess
stringToReturn = Ctype(da.ExecuteScalar("SQLCommand"), String)
Return stringToReturn
End Function
End Class
End NameSpace
[DataAccessClass.vb]
Public Class DataAccess()
Private m_ConStr As String = ""
Public Sub New()
m_ConStr = HttpContext.Current.Session("ConnString")
End Sub
'Some methods for SQL statement execution (ExecuteQuery, ExecuteScalar)
End Class
[Page1.aspx.vb]
Imports ClassNameSpace
Protected Sub Page_Load(....) Handles Me.Load
Dim strValue as String = Admin.MyFunction()
End Sub
I have placed the code above to show you some rough idea of how things are going.
Basically, the function Admin.MyFunction() at times fails, because in the data access class, the connection string seems to have lost it's value (either blank or Nothing).
This has troubled me for quite some time already.
I hope someone can point me in the right direction to resolve this. Basically, I want my connection string which is retrieved by each user visiting the web application be maintained across all the time and be used anywhere. Session variable does not seem to be the best fit since when the ASP.NET recycles its process, the session is lost.
By the way, I am retrieving the connectionstring initially via the master page from a web service. I tried to place the same retrieve function in the Data Access class when conditions is that the session variable is lost, but I think my application cannot connect to the Web Service during the recycle process.
Any advice would be greatly appreciated on this.
Update on this:
I tried to use Session Variable and set the mode to State Server, but apparently some DLLs which I am using cannot be serialized, thus I am back to square one.
Is there a better way to do this?
One thing to check is if your Session is getting clobbered. If your using the (default) in-memory Session, then sessions die anytime an ASP.NET worker process is recycled. If this is causing your issue, you might have to look into using the ASP.NET SessionServer in IIS, or SQL Server as your Session storage.
I'd try to limit your use of the Session for this type of thing as much as possible. If you utilize the Web.Config for storing your connection strings, you can access it at anytime and it will not expire on you like the session.
You may also consider having a static data access class if it is the same for all users for the applications instance...
This is the exact same problem I was experiencing, and it turned out to be the session variables dying so the connection string couldn't be initialized properly.
Why cant your app use just one connection string? and why does the connection string need to come in through a webservice? that adds a huge amount of latency to the entire process. I assume it probably has to do something with data security in your database.
If you have to do this, I'd say, can't you have a fall back / default connectionstring? Wrap your code that attempts to pull it out of the session with some error handeling and if it fails revert to your default?
I would place your web service and web app in different app pools. Then increase the timeout length of your web apps pool.

Resources