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('|');
The ASP.NET web application I am developing needs to support two different types of databases, namely Access and MS SQL Server 2008 Express.
I already have connection strings for each database type stored in web.config, and I have another web.config value that specifies which one to use. So I can get the proper connection string with no problem.
The big problem comes with the database objects. For Access, which I have already implemented, I am using the objects OleDbConnection, OleDbCommand and OleDbDataReader in the code to make the database calls.
It appears that for SQL Server, I can't use those objects, but rather I would need to use the objects SqlConnection, SqlCommand and SqlDataReader to do essentially the same things.
I want to reuse as much of my current code as possible and not have to create two separate blocks for each database type. (I have a lot of methods that take an OleDbDataReader as a parameter - I do not want to have to make 2 of each of those methods, for example.)
I noticed that the connection objects both inherit from DbConnection. And the same is true for the data readers (DbDataReader) and the commands (DbCommand).
Would it be possible to take my existing code for Access, replace all of the Ole objects with the Db objects, and then cast those objects as the proper type depending on the current database type?
Are there any best practices for supporting two database types in one ASP.NET application?
I can add some of my code if that would help. Thanks.
Yes, from framework 2.0 all data readers inherit from the DbDataReader class, so your methods could take a DbDataReader isntead of an OleDbDataReader, and you could use the methods with any database.
However, the databases have different dialects of SQL, so you either have to stay on a narrow path of features that work in all databases that you use, or have separate queries for some tasks.
A specific example of differences is that Access uses data literals like #2010-09-24# while SQL Server uses date literals like '2010-09-24'. Generally most that has to do with dates differs.
The link you're likely missing is the functionality of the DbProviderFactories class. Using this class (and associated helpers also in System.Data.Common), you can abstract the provider and use references to the base classes (such as DbConnection and DbCommand) to do the work. It'd look something like this:
private void DoSomething(string provider, string connectionString, string something)
{
DbProviderFactory factory = DbProviderFactories.GetFactory(provider);
DbConnection connection = factory.CreateConnection();
connection.ConnectionString = connectionString;
DbCommand command = connection.CreateCommand();
command.CommandText = something;
DbDataReader reader = command.ExecuteReader();
//etc...
}
The provider name is a bit tricky to acquire, but should be the invariant class name that matches one of those returned by DbProviderFactories.GetFactoryClasses(). Or, you can simply hard code them. They don't change much, but it is a magic string embedded in your code and may cause issues eventually.
Additional features can be accessed through factory.CreateCommandBuilder that can help you traverse the differences in how the providers handle things like parameters and such.
oXML = Server.CreateObject("Msxml2.DOMDocument.4.0")
oNode = oXML.createElement("CommonCustomerSearch")
can someone explain what the lines of code above are doing? i'm more interested in the first line as the method it is written in exits when it hits that line, so apparently the variable oXML isn't being set. i know that oXML is supposed to be set to some kind of COM object but can you explain the "Msxml2.DOMDocument.4.0" part a bit more? what is that, where is that, and what will it look like in .NET (this code is a classic asp)? i don't know what the second line of code above is either but the method never even reaches it so if you have any ideas about what that is doing would be great too. thanks
That is code using the old MSXML COM object. The XML namespace in .NET will do almost the exact same thing, using similar syntax. And bypass COM (a good thing). Convert these statements to use .Net's XML.
Msxml2.DOMDocument.4.0 is the COM object name.
If the createobject is existing the method, then something is probably wrong.
In .net you can say, like, Dim MyXMLDocument as New XML.XMLDocument, etc.
That classic ASP code is making use of the XML DOM library. The first line (if properly coded with the set keyword) creates an XML document in memory. The second line creates an XML node named CommonCustomerSearch.
.NET Framework 3.5+
If you want to move to .NET 3.5 or later, you could do the same thing with System.Linq.Xml
var xmlDoc = new XDocument(new XElement("CommonCustomerSearch"));
You can read the Getting Started Guide for LINQ to XML for more info.
.NET Framework 2.0
It sounds like you're limited to .NET 2.0, so you can use System.Xml to accomplish this in a less sexy way.
XmlDocument doc = new XmlDocument();
doc.LoadXml("<CommonCustomerSearch/>");
The Msxml2.DOMDocument.4.0 is a COM object and the line is supposed to create an instance of the class. I donĀ“t know if this is all the code but you are required to use the Set keyword when initializing an instance of an object. So it should in fact be
Set oXML = Server.CreateObject("Msxml2.DOMDocument.4.0")
Set oNode = oXML.createElement("CommonCustomerSearch")
The Msxml class is an abstraction of an xml document.
What's the ideal way of generating XML without creating and saving a file?
I'm thinking of using an ASP.NET page with code behind to generate the markup as XML.
Is this possible? Or would you have an alternative way?
I have a flash component that reads an XML file and I need to dynamically generate this file. I don't have write permission so I won't have the ability to create and save a file.
I was thinking of having an application page that grabs the data and provide property methods to generate the xml on the Settings.xml.aspx page with Settings.xml.aspx.cs codebehind.
Thanks.
The easiest way is to use System.Xml.XmlDocument or System.Xml.Linq.XDocument to build up the document. Both can be streamed out to the Response.OutputStream.
The smoothest approach (especially if you turn off buffering) is simply to create an XmlTextWriter round the Response.OutputStream. This is a forward only approach to generate XML but if the output is large it means you need less memory and content starts to arrive at the client earlier.
System.Xml.XmlDocument ?
In fact there are many ways to do it. It all depends on your needs. Maybe you could have a look at some examples of XDocument (or XmlDocument in .NET 2.0) and XmlWriter, none of these require you to save the XML to a file. You can either keep the object model in memory when using XDocument or write to a MemoryStream when using XmlWriter:
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
{
using (XmlWriter writer = XmlWriter.Create (stream, settings))
{
writer.WriteStartElement ("customer");
writer.WriteElementString ("firstname", "Jim");
writer.WriteElementString ("lastname"," Bo");
writer.WriteEndElement();
}
// do further processing with the stream
}
The difference between the two is basically that the first one gives you access to the DOM whereas the second one simply writes out XML to an underlying stream.
Unfortunately, without knowing more details this question can only be answered vaguely.
Yes, it is perfectly feasible to generate XML "on the fly". Take a look at the XmlDocument class. And more info here.
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.