Classic ASP and ASP.Net Session Bridging, passing Arrays - asp.net

I have seen many articles about session bridging between Classic ASP and ASP.Net. But, I could not find one that works not only saving primitive types to session state and but also saving reference types to the session state.
I want to know how array can be saved to classic ASP session and retrieved from ASP.Net session vice versa.
I know this is not easy as things like marshaling and serialization will be brought into the topic. But I want to make a guess about how far I need to go to achieve this.

You can always make your own serialization of plain arrays: in classic ASP convert them to a string using a delimeter then parse the string back to array in the ASP.NET code.
Both offers you simple methods out of the box: Split() and Join(), so in classic ASP:
myArray = Array("Jon", "Bob", "Don")
Session("SerializedArray") = Join(myArray, "|")
Then in the ASP.NET when reading it:
string[] myArray = (Session["SerializedArray"] + "").Split('|');

Related

Pass list of ids between forms

I have an ASP.NET c# project.
I have to pass a list of values (id numbers such as "23,4455,21,2,765,...) from one form to another. Since QueryString is not possible because the list could be long, which is the best way to do it?
Thanks in advance.
Thanks for all your answers, you are helping a lot !!!
I decided to do this:
On the first form:
List lRecipients = new List();
.....
Session["Recipients"] = lRecipients;
On the final form:
List lRecipients = (List)Session["Recipients"];
Session.Remove("Recipients");
You could use Session collection.
In the first page, use:
List<int> listOfInts = new List<int>();
...
Session["someKey"] = listOfInts
And in the second page, retrieve it like this:
List<int> listOfInts = Session["someKey"] as List<int>;
If your using asp.net webforms you can put it into a session variable to pass stuff from page to page. You've got to be concise of the potential performance issues of putting lots of stuff into session mind.
Session["ListOfStff"] = "15,25,44.etc";
There are any number of ways to pass this data. Which you choose will depend on your environment.
Session state is useful, but is constrained by the number of concurrent users on the system and the amount of available memory on the server. Consider this when deciding whether or not to use Session state. If you do choose session state for this operation, be sure to remove the data when you're done processing the request.
You could use a hidden input field, with runat="server" applied to it. This will make its data available server-side, and it will only last for the duration of the request. The pros of this technique are that it's accessible to both the server code and the client-side JavaScript. However, it also means that the size of your request is increased, and it may take more work to get the data where you want it (and back out).
Depending on how much data's involved, you could implement a web service to serialize the data to a temporary storage medium (say, a database table), and get back a "request handle." Then, you could pass the request handle on the query string to the next form and it could use the "handle" to fetch the data from your medium.
There are all kinds of different ways to deal with this scenario, but the best choice will depend on your environment, time to develop, and costs.
For Asp.NET MVC you can use ViewData.
ViewData["ID"] = "";

asp.net webcontrol caching

I'm writing a webcontrol in asp.net which has to go and fetch information from an API. It's not critical to be up-to-date, and retrieving the information is quite slow, so I'd rather cache the information and update it every 5 minutes.
It strikes me as potentially risky to use the Context.Cache as potentially someone could use the same name, but I can't find another way to do caching within a control.
Does anyone have any other ideas?
(using asp.net 2.0).
It sounds like the Context.Cache is exactly what you need to store this kind of information. The cache object is localized to your application so it would only be changeable by other code in your application.
You can always give your cache key a very long and presumably useless name etc and store that key within your class...
Private const CacheKey as String = "e92a627b-3a9f-46da-a182-d73b44fe87ad" ' A random guid
Cache.Item(CacheKey) = TheRefreshedData ' etc
As I was writing this answer I realised maybe you were talking about your conntrol being re-used within someone else's application...as in your control is redistributed or provided for download. In this case, you could always prefix the cache key with your control to be "sensibly" unique...
Private const CacheKey As String = "MyCompany.MyControl.MyData"
Cache.Item(CacheKey) = TheRefreshedData ' etc
Either way, you should be able to come up with some fairly length string that has zero chance of being reused...

Data Class in ASP.Net

I am a VB.net winforms programmer attempting to build an ASP.Net app. I use data classes(objects) through reflection in most of my vb projects and was trying to adapt it to ASP.net using the VB code behind. I have a webpage that serves as an add/edit page for contact info. I instatiate my class which grabs the contact data from the data base then I have a process that loops through the controls on the form and matches up with a property in the data class. I can display data no problem. When I edit data and click the submit button my code calls a then loops through the controls on the form again and matches the control to the property of the data class to update the property of the class. However, my data class is no longer valid. I know web programming is different then winforms but I can't seem to get over the hump on this one. Is this the wrong way to go about this? Is my data class only available on the server side? Do I just reinstantiate the initial class and then loop through the propeties and change what the user changed and then call the update method (see redundant)? How can I get data class into a session object (I made an attempt in the past but was under tight deadlines and had to abandon it, maybe I need to revisit it?)?
Thanks
If you decide to keep some of your data in Session, you owe it to yourself to look at this post. Your code will be much cleaner and easier to maintain.
Yes, you need to reload the data class from the database as one option, or use an alternative approach. The reason is web is stateless, so all local variables are destroyed then the server side page unload process occurs. This means that in between requests, you need something to store your data.
You can read/write an object via the Session colleciton, as so:
Session["A"] = myobj;
myobj = (ObjType)Session["A"];
And so session stores an object for a specific user. Alternatively, cache stores application level data, so one instance of an object is available to all users (where session is unique to each user). You can make cache unique to a user by appending a user ID to the cache string.
var o = Cache.Get("A");
if (o != null) { .. }
Cache.Add("A", o, ...);
And so these mechanisms help you temporarily retain data.
You need to save your data class somewhere, usually in a session variable, otherwise it goes away as soon as the page gets sent back the user. Or else you need to recreate the data class again upon posting.

Byte array in Classic ASP

How do I write the following code in classic ASP? I am using this code in an include file.
byte[] bytes = new byte[stream.Length]
Also it would be great if anyone can say how to create object for StreamWriter in classic ASP.
Set sw = Server.CreateObject("System.IO.StreamWriter(stream)")
I am not sure about the code inside quotes System.IO.StreamWriter(stream).
Classic ASP is just plain old VBScript. CreateObject creates a COM object using the classid/progid: CreateObject("ADODB.Connection") or CreateObject("Scripting.FileSystemObject").
Classic ASP can use COM objects that are actually .NET objects... but only if they have been built specifically supporting COM interop. Most of the internal .NET stuff was not built supporting COM interop.
See: http://msdn.microsoft.com/en-us/library/zsfww439.aspx
If you just need a stream object (not necesarily a .NET System.IO.Stream object) then I'd recommend ADODB.Stream.
Also not that in ASP/VBScript all variables are variants. This makes things like an array of bytes tricky. You can have an array of variants no big deal, and all the variants could be bytes... but you can't create an array that can only hold bytes. To make matters stranger... if a COM object returns a SAFEARRAY of bytes then ASP/VBScript is happy to use it.
I don't think there's a direct translation to StreamWriter. My classic ASP objects knowledge is limited, but IIRC the closest match would be FileSystemObject. As for the byte array:
Dim bytes(stream.Length-1) As Byte
Not sure what you want to do, but..
When I wanted to handle byte arrays from vbscript like a BLOB coming from a database I made a general VB6 COM object that could perform operations on the byte array.
http://www.di-mgt.com.au/bytearrays.html

asp consuming a web service, what do do with recordset object?

Currently I run an classic (old) ASP webpage with recordset object used directly in bad old spagethi code fasion.
I'm thinking of implementing a data layer in asp.net as web serivce to improve manageability. This is also a first step towards upgrading the website to asp.net.
The site itself remains ASP for the moment...
Can anybody recommend a good way of replacing the recordset object type with a web service compatible type (like an array or something)?
What do I replace below with?:
set objRS = oConn.execute(SQL)
while not objRS.eof
...
name = Cstr(objRS(1))
...
wend
and also mutliple recordsets can be replaced with?
I'm talking :
set objRS = objRs.nextRecordset
Anybody went through this and can recommend?
#AdditionalInfo - you asked for it :-)
Let me start at the beginning.
Existing Situation is:
I have an old ASP website with classical hierachical content (header, section, subsection, content) pulled out of database via stored procedures and content pages are in database also (a link to html file).
Now bad thing is, ASP code everywhere spread over many .asp files all doing their own database connections, reading, writing (u have to register for content). Recently we had problems with SQL injection attacks so I was called to fix it.
I could go change all the .asp pages to prevent sql injection but that would be madness. So I thought build a data layer - all pages using this layer to access database. Once place to fix and update db access code.
Coming to that decision I thought asp.net upgrade isn'f far away, why not start using asp.net for the data layer? This way it can be re-used when upgrading the site.
That brings me to the questions above!
First my favorite advice of this week: do not treat your Web Service like it if was a local object or you are going to pay a very hefty performance price. Essentially, don't do things like this in your web application:
MyDataWebService ws = new MyDataWebService();
foreach(DataItem item in myData)
{
ws.Insert(item);
}
You should always prefer to minimize calls to your Web Service (and SQL):
MyDataWebService ws = new MyDataWebService();
ws.Insert(myData); // Let the web service process the whole set at once.
Now, as far as the data type to use for your web service calls, you basically have two choices:
DataSet
Everything else (Array)
Most collections returned from a web service (like a List<MyData>) actually convert to an Array during the Web Service invocation. Remember that Web Services don't return objects (data + behavior) but just data structures (or a sequence of). Therefore, there is little distinction between a List and an Array.
DataSets are more complex classes; they use their own custom serializer and pretty much get fully recreated in the calling application. There is a cost in performance to be paid for using DataSets like that, so I don't usually recommend it for most scenarios. Using arrays to pass data back and forth tends to be more efficient, and quite frankly it's easier to do.
Your case is a bit different; because you are converting an existing site that already uses ADO, an ADO.NET DataSet might be your best updgrade path. ADO.NET and ADO are similar enough that a straight update might be easier that way. It kind of depends how your web site is built.
For the last part of your question, DataSets do support multiple recordsets similar to ADO's Recordset. They are called DataTables. Every DataSet has at least one DataTable and you can read them in any order.
Good luck.
If you wanted to stick with Classic ASP then I would suggest creating a Database handling object via ASP Classes then just use that object to do your recordset creations. This would centralize your database handling code and make it so that you only have to handle SQL Injection attacks in a single location.
A simple example.
Class clsDatabase
Private Sub Class_Initialize()
If Session("Debug") Then Response.Write "Database Initialized<br />"
End Sub
Private Sub Class_Terminate()
If Session("Debug") Then Response.Write "Database Terminated<br />"
End Sub
Public Function Run(SQL)
Set RS = CreateObject("ADODB.Recordset")
RS.CursorLocation = adUseClient
RS.Open SQLValidate(SQL), Application("Data"), adOpenKeyset, adLockReadOnly, adCmdText
Set Run = RS
Set RS = nothing
End Function
Public Function SQLValidate(SQL)
SQLValidate = SQL
SQLValidate = Replace(SQLValidate, "--", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, ";", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, "SP_", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, "##", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, " DECLARE", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, "EXEC", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, " DROP", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, " CREATE", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, " GRANT", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, " XP_", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, "CHAR(124)", "", 1, -1, 1)
End Function
End Class
Then to use this you would change your calls to:
Set oData = new clsDatabase
Set Recordset = oData.Run("SELECT field FROM table WHERE something = another")
Set oData = nothing
Of course you can expand the basic class to handle parametrized stored procedures or what not and more validations etc.
I'd suggest using the XmlHttp class in your ASP code.
Assuming you have an ASMX web service similar to this, in MyService.asmx:
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
You could call it in ASP something like this:
Dim xhr
Set xhr = server.CreateObject("MSXML2.XMLHTTP")
xhr.Open "POST", "/MyService.asmx/HelloWorld", false
xhr.SetRequestHeader "content-type", "application/x-www-form-urlencoded"
xhr.Send
Response.Write(xhr.ResponseText)
ResponseText would be an XML response of:
<string>Hello World</string>
Assuming your service returned a collection of data, you could iterate over it using XPath or any other XML processing technique/library.
Googling around about MSXML2 will probably answer any specific questions you have, since it's specific to ASP classic.
Instead of thinking in layers, why not try taking vertical slices through the application and converting those to .net. That way you will get entire features coded in .net instead of disjoint parts. What is the business value in replacing perfectly working code without improving the user experience or adding features?
You might also consider the trade-off of performance you are going to give up with a Web Service over direct ado calls. Web Services are a good solution to the problem of multiple disjoint applications/teams accessing a common schema; they do not make a single isolated application more maintainable, only slower and more complex.
Another alternative is to use COM Interop to create an assembly in .NET that is callable from classic ASP.
To create a COM Interop assembly from Visual Studio (e.g. Microsoft Visual C# 2005 Express Edition):
Create a new Class Library project
Open the project properties
Under Application select Assembly Information... and enable "Make assembly COM-Visible"
Under Signing enable Sign the assembly and create or select an existing strong name key file
Write and build the library
COM Interop classes must have a default constructor and only non-static classes and methods are published
Copy the .dll to the desired folder/machine
Register the .dll for COM using RegAsm
For example (adjust as necessary):
"C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe" "C:\path\to\assembly.dll" /tlb /codebase
Call the assembly from ASP
For example (adjust as necessary):
Dim obj, returnValue
Set obj = Server.CreateObject("MyProject.MyClass")
returnValue = obj.DoSomething(param1, param2)
Note:
the assembly must be re-registered via RegAsm when it's updated
See also:
Exposing .NET Framework Components to COM (MSDN)
CodeProject: Call a .NET component from an ASP Page
Sql injection should be handled by using parametrized sql queries. Not only will this eliminate the security risk but it will significantly speed up your database performance because it will be able to reuse an execution plan instead of recalcing it every time. The suggestion to handle it through string replacements is foolish. VB is terrible at handling strings and those "replace" statements will be extremely costly in performance and memory (also, you actually only need to handle the ' character anyway)
Moving code to .net doesn't make it better. Having db code in your pages isn't bad; especially if id you are talking about a small site with only a couple devs. Thousands of sites use that technique to process bazillions of dollars in transactions. Now, unparameterized dynamic sql is bad and you should work to eliminate that, but that doesn't require a rewrite of the app or .net to do it. I'm always curious why people see .net as a defacto improvement to their app. Most of the bad code and bad habits that existed in the COM model just propagate forward during a conversion.
You either need to make a commitment to creating a truly cohesive, minimally coupled, OO design; or just keep what you have going because it isn't all that bad.
Too bad I did not see this question in 2008.
For me it looks like your site is using Justa framework.
Simple way is to modify Justa code for submit of search and data inputs to urlencode.
I did it and work perfectly for me.
Rest of the code secure enough to prevent any type os SQL injections or other attempt to get into database.

Resources