I am currently tasked with moving one of our older bits of software to a new server. The old server is running 2008 and the new server is on 2019. The code is a mixture of ASP and ASP.NET, both using VB. Unfortunately, I'm a C# developer and my VB knowledge is slight.
The main bit of the code is the older and is all in ASP and works fine on the new server. For a particular set of customers there is an add-on that is more recent and uses ASP.NET. For the new section of code to get the details of the logged in user it uses the code given in this answer. Unfortunately it seems like it is this bit of code that is failing.
We have this bit of code in our site.master.vb
ctx1 = ctx.Request.Url.Scheme
ctx2 = ctx.Request.Url.Host
dom = ctx1 + "://" + ctx2
Dim ASPRequest As HttpWebRequest = WebRequest.Create(New Uri(dom + "/arc/asp2netbridge.asp?sessVar=" + sessionValue))
ASPRequest.ContentType = "text/html"
ASPRequest.Credentials = CredentialCache.DefaultCredentials
If (ASPRequest.CookieContainer Is Nothing) Then
ASPRequest.CookieContainer = New CookieContainer()
End If
The asp2netbridge.asp file is stored in the directory one up from the directory that contains the code and the directory structure looks the same on both servers. The contents of the as2netbridge file are the the same as in the example code linked above with the addition of some extra comments.
It then calls a Stored Procedure on our database with the customer ID from session that should return the customer details as XML, but instead we get a 'Root Element is missing' Error. If I change the Stored Procedure to hard code the customer ID in it, rather than as a parameter then it works as expected.
Is there anything that I need to install on our server to get the system working correctly? Or is there anything else I need to do to get it to work?
Related
So, as I figured out, when I have a form with enctype="multipart/form-data" and I upload a file, I can no longer access the object request. The following error is shown:
Cannot use the generic Request collection after calling BinaryRead.
After checking some resources, I stumpled upon a statement, which says: "This is by design". Well, okay, not here to judge about design-decisions.
To give you a quick overview, let me walk you through the code:
if request("todo") = "add" then
Set Form = New ASPForm
category = request("category")
title = request("title")
if len(Form("upload_file").FileName) > 0 then
filename = Form("upload_file").FileName
DestinationPath = Server.mapPath("personal/allrounder/dokumente/")
Form.Files.Save DestinationPath
end if
end if
Nothing too special here so far. Later however, when I try to access my request object, the error mentioned above occures:
<% if request("todo") = "new" then %>
...
My question now, how to get rid of it or fix this. I don't want to open the upload in a popup if there is another way around. This is the only solution I could think off.
Perfectly would be an object, which checks Form and request. Alternatively maybe a check at the top of the file, which object I have to use?
Thanks for any suggestions.
There used to be a very popular ASP class/component that solved ASP file uploads. The site for that component has been taken down, but the code is mirrored here:
https://github.com/romuloalves/free-asp-upload
You can include this ASP page on your own page, and on your page instantiate the class to get access to the files in your form, but also to the form variables. Here is a piece of example code (Upload.Form accesses the form fields):
Dim uploadsDir : uploadsDir = server.mapPath(".") ' whatever you want
Dim Upload, ks, fileKey, mailto
Set Upload = New FreeASPUpload
call Upload.Save(uploadsDir)
ks = Upload.UploadedFiles.keys
for each fileKey in ks
Response.write(fileKey & " : " & Upload.UploadedFiles(fileKey).FileName & "<br/>")
next
mailto = Upload.form("mailTo")
Set Upload = Nothing
If you want to stick to your own implementation, you can probably figure out how to get to the form variables in a multipart/form-data encoded data stream by having a look at the code they use to do so.
I need to change dataset connectionstrings to point to different DBs at run time.
I've looked at a number of solutions however they all seem to be related to WinForms or web application projects or other technology slightly different than what I'm using, so I haven't figured out how apply them.
The application is like a discussion. It's a web site project based on code originally written under VS2005, and there's no budget (or personal talent!) for major changes at this time. The app is written in vb.net; I can understand answers in c#. I'm working in VS2013.
The app has three typed datasets pointing to one MDF, call it "MainDB.mdf". There are dozens of tableadapters among the three datasets.
I'm going to deploy the app it as an "alpha/demo" version. I would like to use the same code base for all users, and a separate physical version of MainDB for each user, to reduce chances that the users crash each other.
The initial demo access URL will contain query string information that I can use to connect the user with the right physical database file. I should be able to identify the database name and thus the connection string parameters from the query string information (probably using replace on a generic connection string). If necessary I could use appsettings to store fully formed connection strings, however, I would like to avoid that.
I would like to be able to change the connection strings for all the datasets at the time that the entry point pages for the app are accessed.
Changing the tableadapter connection strings at each instantiation of the tableapters would require too much code change (at least a couple of hundred instantiations); I'd just make complete separate sites instead of doing that. That's the fall back position if I can't dynamically change the connectionstrings at runtime (or learn some other way to make this general scheme work).
Any suggestions on how to approach this would be appreciated.
Thanks!
UPDATE: Per comments, here is a sample instantiation of tableadapter
Public Shared Sub ClearOperCntrlIfHasThisStaff( _
varSesnID As Integer, varWrkprID As Integer)
Dim TA As GSD_DataSetTableAdapters.OPER_CNTRLTableAdapter
Dim DR As GSD_DataSet.OPER_CNTRLRow
DR = DB.GetOperCntrlRowBySesnID(varSesnID)
If IsNothing(DR) Then
Exit Sub
End If
If DR.AField = varWrkprID Then
DR.AField = -1
TA.Update(DR)
DR.AcceptChanges()
End If
End Sub
UPDATE: Below is the test code I tried in a test site to modify the connectionString in a single instantiation of a tableadapter. It feeds a simple gridview. I tried calling this from Page_Load, Page_PreLoad, ObjectDataSource_Init, and Gridview_Databind. At the concluding response.writes, the wrkNewConnString looks changed to TestDB2, and the TA.Connection.ConnectionString value looks changed to TestDB2, but the displayed gridview data is still from TestDB1. Maybe it needs to be called from somewhere else?
Sub ChangeTableAdapter()
Dim wrkNewConnStr As String = ""
Dim wrkSel As Integer
wrkSel = 2
wrkNewConnStr = wrkNewConnStr & "Data Source=.\SQLEXPRESS;"
wrkNewConnStr = wrkNewConnStr & "AttachDbFilename=D:\9000_TestSite\App_Data\TESTDB1.MDF;Integrated Security=True;User Instance=True"
Select Case wrkSel
Case 1
wrkNewConnStr = wrkNewConnStr.Replace("TESTDB1", "TESTDB1")
Case 2
wrkNewConnStr = wrkNewConnStr.Replace("TESTDB1", "TESTDB2")
Case 3
wrkNewConnStr = "Data Source=localhost; Initial Catalog=test01;"
wrkNewConnStr = wrkNewConnStr & " User ID=testuser1; Password=testuserpw1"
End Select
Try
Dim TA As New DataSetTableAdapters.NamesTableAdapter
TA.Connection.ConnectionString = wrkNewConnStr
Response.Write("1 - " & wrkNewConnStr)
Response.Write("<br/>")
Response.Write("2 - " & TA.Connection.ConnectionString)
Catch ex As Exception
Dim exmsg As String = ex.Message
Response.Write(exmsg)
End Try
End Sub
The connection string:
<add name="TestDB1ConnectionString"
connectionString="Data Source=.\SQLEXPRESS;
AttachDbFilename=D:\9000_TestSite\App_Data\TESTDB1.MDF;Integrated Security=True;User Instance=True"
providerName="System.Data.SqlClient" />
UPDATE: the following post has lots of solutions, however, they seem to focus on web application projects, that have a project file with settings, which this web site project does not.
link with possible solutions
UPDATE: this next link was brought to my attention, and in working on it I did get it to work, however, it still relies either on having a web application project (with project file) or modifying each table adapter as they are instantiated. So, while I'm not going to implement it, I believe that is the technical answer.
modifying connection strings
sorry if this answer is too late, but I have exactly the same problem and eventually came up with a solution using Reflection.
My solution was to "save" a new default value for the connection string in the settings at run time, which means any further use of the table adapter uses the the new connection string.
It should be noted the term "save" is misleading as the new value is lost when the application closes.
Have tested and worked perfectly.
public void ChangeDefaultSetting(string name, string value)
{
if (name == null)
throw new ArgumentNullException("name");
if (value == null)
throw new ArgumentNullException("value");
Assembly a = typeof({Put the name of a class in the same assembly as your settings class here}).Assembly;
Type t = a.GetType("{Put the full name of your settings class here}");
PropertyInfo propertyInfo = t.GetProperty("Default");
System.Configuration.ApplicationSettingsBase def = propertyInfo.GetValue(null) as System.Configuration.ApplicationSettingsBase;
//change the "defalt" value and save it to memory
def[name] = value;
def.Save();
}
EDIT - RESOLVED: the difference was that in the "main" case the download was initiated via a callback cycle, and in the "test" case it was initiated through a server side button click function. My guess is that the download request and the callback cycle interfered with each other, both stopping the download and causing the page to become inactive (as described below). When I rewired the download on the main page to start with a submit instead of a callback, it did initiate the download.
This is in VS2013 Ultimate, Win7Pro, VB.Net, websites (not projects),IISExpress.
I built a test site to develop functionality for creating OpenXML PPTX and XLSX memorystreams and zipping and downloading them using DotNetZip. Got it to work fine. I then merged all that code into my "main" site. Both sites are on the same machine; I can run the test site and the main site at the same time. The main site processing is somewhat more complicated, but only in terms of accessing and downloading more files.
However, the Zip and Download function (below) works fine in the test site, but the exact same code doesn't work in the main site (with or without the test site up and running).
There's an error trap (see below) around the Zip.Save function where the download occurs but no error shows up.
Same overall behavior in Chrome, Firefox and IE11.
One peculiarity that might be a clue is that when the main site download fails, the server side functionality "goes dead". Local JS functions work, but the app doesn't respond to callbacks. When I do an F5 on the browser it works again.
I did a refresh on the DotNetZip package in the main site. The Zip object appears to be working properly, because it generates an error on duplicate file names.
I thought it might be the download function as written, however, it works in the test site. Also, another piece of the main site does a non-zipped download of a memory stream (included as the second code block below) and that works fine.
I thought it might be the data. So I kludged the main site to access, convert to memorystream and download the same file that the is accessed and downloaded in the test site. Still the main site download doesn't work.
When I compare the watch values on the Zip object in the two sites, they look identical. The length of the wrkFS.ContentStream is identical in both cases. The file names are different, however, they are:
Test_2EFVG1THK5.xlsx (main)
6-18_12-46-28_0.xlsx (test)
which are both legal file names.
EDIT: I saved the zip file to disk from the main program, instead of trying to download it, using this:
wrkFilePath = "D:\filepath\test.zip"
wrkZip.Save(wrkFilePath)
And it worked fine. So that possibly isolates the problem to this statement
wrkZip.Save(context.Response.OutputStream)
EDIT: Base on help I received here:
Convert DotNetZip ZipFile to byte array
I used this construct:
Dim ms as New MemoryStream
wrkZip.Save(ms)
wrkBytes = ms.ToArray()
context.Response.BinaryWrite(wrkByteAr)
to get around the ZipFile.Save(to context), and that didn't work either; no download, no error message, and page goes dead. However, at least I can now assume it's not a problem with the ZipFile.Save.
At this point I'm out of ways to diagnose the problem.
Any suggestions would be appreciated.
Here is the code that works in the test site but not in the main site.
Public Sub ZipAndDownloadMemoryStreams(ByVal context As HttpContext) _
Implements IHttpHandler.ProcessRequest
Dim rtn As String = ""
Try
Dim wrkAr As ArrayList
wrkAr = SC.ContentArrayForDownLoad
If wrkAr.Count = 0 Then
Dim wrkStop As Integer = 0
Exit Sub
End If
Dim wrkFS As ZipDownloadContentPair
Using wrkZip As New ZipFile
'----- create zip, add memory stream----------
For n As Integer = 0 To wrkAr.Count - 1
wrkFS = wrkAr(n)
wrkZip.AddEntry(wrkFS.FileName, wrkFS.ContentStream)
Next
context.Response.Clear()
context.Response.ContentType = "application/force-download"
context.Response.AddHeader( _
"content-disposition", _
"attachment; filename=" & "_XYZ_Export.zip")
'---- save context (initiate download)-----
wrkZip.Save(context.Response.OutputStream)
wrkZip.Dispose()
End Using
Catch ex As Exception
Dim exmsg As String = ex.Message
Dim wrkStop As String = ""
End Try
End Sub
Below is the non-zip download function that works fine in the main site.
It might be possible to convert the Zip content to a byte array and try the download that way, however, I'm not sure how that would work.
(SEE EDIT NOTE ABOVE --- I implemented a version of the below, i.e. try to download byte array instead of directly ZipFile.Save(), however, it didn't help; still doesn't download, and still doesn't give any error message)
Public Sub DownloadEncryptedMemoryStream(ByVal context As HttpContext) _
Implements IHttpHandler.ProcessRequest
Dim wrkMemoryStream As New System.IO.MemoryStream()
wrkMemoryStream = SC.ContentForDownload
Dim wrkFileName As String = SC.ExportEncryptedFileName
wrkMemoryStream.Position = 0
Dim wrkBytesInStream As Byte() = New Byte(wrkMemoryStream.Length - 1) {}
wrkMemoryStream.Read(wrkBytesInStream, 0, CInt(wrkMemoryStream.Length))
Dim wrkStr As String = ""
wrkStr = Encoding.UTF8.GetString(wrkMemoryStream.ToArray())
wrkMemoryStream.Close()
context.Response.Clear()
context.Response.ContentType = "application/force-download"
context.Response.AddHeader("content-disposition", "attachment; filename=" & wrkFileName)
context.Response.BinaryWrite(wrkBytesInStream)
wrkBytesInStream = Nothing
context.Response.End()
(Per the note now at the top of the question): The difference was that in the "main" case the download was initiated via a callback cycle, and in the "test" case it was initiated through a server side button click function. My guess is that the download request and the callback cycle interfered with each other, both stopping the download and causing the page to become inactive (as described below). When I rewired the download on the main page to start with a submit instead of a callback, it did initiate the download.
In an ASP.NET 4 application, I have existing code to access a user's Active Directory information (potentially under Windows Authentication or FBA) like this:
// authType taken from run-time config file, default below
AuthenticationTypes authType = AuthenticationTypes.Secure;
string path = "LDAP://" + domain;
DirectoryEntry entry = new DirectoryEntry(path);
entry.AuthenticationType = authType;
// Bind to the native AdsObject to force authentication.
Object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
// set search Filter/Properties etc. ..., nice and correctly
SearchResult result = search.FindOne();
It has always worked fine for me, on my LAN. But I get no feedback from customer sites (other than it works). I now note a post like http://www.justskins.com/forums/directoryentry-nativeobject-slow-with-203410.html, implying this COM way of going via DirectoryEntry.NativeObject might be inefficient or ill-advised? On the other hand, I see here LDAP search using DirectoryServices.Protocols slow, implying it is OK?
This code probably dates from .NET 1/2, when perhaps System.DirectoryServices had less in it; it came from some MS example for using ADSI somewhere.
In a word: I don't want to change the code just for the sake of it, but will if faster. Is there actually nowadays any superior method(s) in DirectoryServices which I should be using?
i am not a programmer, but i can frankenstein code snippets with sufficient proficiency that if, by the grace of a few good souls, i could come across some sample ASP code that acts as a GUI to the ms index server, i could certainly make it work and look good.
if anyone can offer any help, i would do a backflip. but i won't put it on youtube. there's enough faceplant videos out there.
summary: does anyone know where i can find index server asp pages? the more complete, the better. snippets are more than welcome.
btw: io tagged this as sharepoint since this is so similar. some moss admins will certainly be able to lend me a hand!
How about some samples from CodeProject? Would that suit your needs? I'm sorry I can't offer any more specific help without knowing more details and what you are trying to do.
Microsoft Index Server class for ASP (classic ASP)
Your free search engine – Microsoft Indexing Server
To talk to an index server catalogue from asp.net you can use an ole db connection object.
OleDbConnection conn = new OleDbConnection("Provider=MSIDXS;Integrated Security .=;Data Source=" + catalogName);
cmdQuery = new OleDbCommand(query, conn);
Where catalogName is the name of the catalog on your machine you are querying. And query is a string containing the index query you are using.
//Get reader
rQuery = cmdQuery.ExecuteReader(CommandBehavior.CloseConnection);
//Create dataset and load values from reader into it
dataQuery = new DataSet("IndexResults");
dataQuery.Load(rQuery, LoadOption.OverwriteChanges, new string[] { "" });
//Return the first table which will be the results from the query
results = dataQuery.Tables[0].Copy();
Don't forget to dispose of the connection and reader in a finally statement :)
Index query itself is very similar to SQL - you can also set properties in the query to be used as aliases so it is easier to read.