Session Variables in IE - asp.net

Searched, but couldn't find a good answer.
I have an ASP.NET application that I am developing. I'm using session variables within the app.
In Firefox & Chrome, they all work.
But in IE (ver 9), there's one variable that's not working. I'm not sure if it's a storage or a retrieval (or both) at this point. The variable in question that I'm storing is a List(T) type. It's the only one of it's kind that I'm using. Can't help but think there's a correlation there.
One other old post mentioned the possibility that cache is causing the problem, but I didn't understand the answer very well.
P.S. If possible, please post any code samples in VB. Sometimes I can read the C# and translate it, and sometimes not.
Dim Rec_IDs As New List(Of String)
Rec_IDs = Session("Rec_IDs")
and
Dim Rec_IDs As New List(Of String)
Dim Rec_ID As Int32
Rec_IDs = Session("Rec_IDs")
For Each Row As GridViewRow In gvParts.Rows
If CType(Row.FindControl("chkSelect"), CheckBox).Checked Then
Rec_ID = gvParts.DataKeys(Row.RowIndex).Value
If Not Rec_IDs.Contains(Rec_ID) Then
Rec_IDs.Add(Rec_ID)
End If
CType(Row.FindControl("chkSelect"), CheckBox).Checked = False
End If
Next
Session("Rec_IDs") = Rec_IDs
lblCount.Text = String.Format("You have {0} records selected", Rec_IDs.Count.ToString)
Other answer: Session Variable not working in Internet Explorer, but works fine in Firefox / Chrome

First check your cookies are enabled or not in your browser. If the cookies are blocked that will be the problem with IE
Also have a look at
Cookieless ASP.NET,
ASP.NET State Management Overview,Difference between browser session and asp.net session

Related

Finding Client Printer ASP.Net

From what I have read its not possible to find a clients local printer using modern browsers for security reasons. I have a few conditions that might make that answer different.
I am trying to get clients local printers from within a company network. So this isnt published 'outside'
I thought several years ago Microsoft released a small version of .Net that could be run from the clients browser. If so and its still around I wonder if that could inspect clients local printer.
Thanks
One way to give the appearance of retrieving the clients printers is to run a server side application in the same network with the same access permissions. Silverlight may be able to do it. I have no experience with it unfortunately.
Check here: Get list of network printers silverlight
This ended up being a lot of work with little information because nearly all my searches on the internet for a solution assumed we want to get the printers of the client from the browser. We want to find such information it via the Network.
The solution ended up being with DirectorySearch and the like. here is the code with some privacy stuff removed. Its in a POF state so it might have some not so great syntax
Dim list As New List(Of String)
Dim listtemp As New List(Of String)
Dim resultCollection As SearchResultCollection
Dim computer_name As String = System.Net.Dns.GetHostEntry(Request.ServerVariables("remote_addr")).HostName.Replace(".ourcompany.com", "").ToLower 'clients machine name
Dim dirEntry As New DirectoryEntry("LDAP://DC=OURCOMPANY, DC=com")
Dim dirSearcher As New DirectorySearcher(dirEntry)
dirSearcher.Filter = "objectCategory=printQueue"
dirSearcher.PropertyNamesOnly = True
dirSearcher.PropertiesToLoad.Add("Name")
dirSearcher.SearchScope = SearchScope.Subtree
resultCollection = dirSearcher.FindAll()
For Each sresult As SearchResult In resultCollection
If sresult.GetDirectoryEntry.Name.ToLower.Contains(computer_name) Then
list.Add(sresult.GetDirectoryEntry.Name.ToLower.Substring(3).Replace(computer_name + "-", ""))
End If
Next

ASP.NET modify connectionstring at runtime

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();
}

asp.net vb2010 How to log Windows Authentication events - i.e. save user name and login time

Just now getting into the asp.net environment with VB 2010. I have designed an intranet page that we will be using to auction off old equipment to employees. I've had some very good luck getting the whole thing working, but I have hit a snag on one minor issue: I would like to keep a database table of user logins and times.
Several methods have presented themselves, but so far none of them have been adequate. The main problem seems to be that regardless of the event I use to record the login, they fire multiple times resulting in as many as 4 or 5 entries in the login database for the same login event, not to mention additional times when something on the page changes for whatever reason.
The system uses Windows Authentication, so the user must login with his/her company credentials.
I can't remember what all I have tried, but the first thing I tried was the Page_Load event because it seemed obvious. I've learned that because the page updates the display every ten seconds, Page_Load event fires numerous times throughout the session.
Fighting my way through other ideas, all of which failed, I came to the WindowsAuthentication_OnAuthenticate event in the Global_asax class, shown below:
Imports System.Web.SessionState
Imports System.Data.SqlClient
Imports System.Web
Imports System.Web.UI.WebControls
--------------------------------------------
Public Sub WindowsAuthentication_OnAuthenticate(ByVal sender As Object, ByVal args As WindowsAuthenticationEventArgs)
Dim strLoginName = args.Identity.Name
Dim sqlCommandString As String = "INSERT into tblLogin (UserLogin,DateTime) VALUES ('" & _
strLoginName & "','" & _
Format(Now, "MMM dd, yyyy hh:mm:ss") & "');"
Dim sqlConn As New SqlConnection(strConnectionString)
Dim sqlCommand As SqlCommand = New SqlCommand(sqlCommandString, sqlConn)
sqlCommand.Connection.Open()
sqlCommand.ExecuteNonQuery()
sqlCommand.Connection.Close()
End Sub
which also seems to fire multiple times. I then tried to work a way where setting a Boolean value to TRUE upon authentication so that the data would be written to the database only once:
Public Sub WindowsAuthentication_OnAuthenticate(ByVal sender As Object, ByVal args As WindowsAuthenticationEventArgs)
If Not boolUserIsLoggedIn Then
boolUserIsLoggedIn = True
Dim strLoginName = args.Identity.Name
Dim sqlCommandString As String = "INSERT into tblLogin (UserLogin,DateTime) VALUES ('" & _
strLoginName & "','" & _
Format(Now, "MMM dd, yyyy hh:mm:ss") & "');"
Dim sqlConn As New SqlConnection(strConnectionString)
Dim sqlCommand As SqlCommand = New SqlCommand(sqlCommandString, sqlConn)
sqlCommand.Connection.Open()
sqlCommand.ExecuteNonQuery()
sqlCommand.Connection.Close()
End If
End Sub
and subsequent authentication iterations would skip the database write code; but then I needed to find a way to clear the Boolean value when the user logged off or closed the session. I couldn't figure out how to trap a "Logged Off" event, and the Session_End and Application_End events didn't work as I had hoped.
I feel like this is getting too convoluted to make sense. To put it simply, I just need a way to record a user's login name and date only once per session. Can anyone help?
[Edit: Although this is not really an essential element of the page, it has become a crusade for me to get it to work if not for any other reason than to understand the process.]
Researching more about JDB's suggestion using the session ID property, I discovered another property that seems to be doing exactly what I need: The IsNewSession property.
With that in mind, I have this code in my default.aspx's Page_Load event:
If Context.Session.IsNewSession Then
Login()
End If
Which calls the Login sub that writes the login information to the database:
Protected Sub Login()
Dim strConnectionString As String = "Data Source = toponet\sqlexpress; initial catalog = TopoAuction; Integrated security = True"
Dim strLoginName = System.Web.HttpContext.Current.User.Identity.Name
Dim sqlCommandString As String = "INSERT into tblLogin (UserLogin,DateTime) VALUES ('" & _
strLoginName & "','" & _
Format(Now, "MMM dd, yyyy hh:mm:ss") & "');"
Dim sqlConn As New SqlConnection(strConnectionString)
Dim sqlCommand As SqlCommand = New SqlCommand(sqlCommandString, sqlConn)
sqlCommand.Connection.Open()
sqlCommand.ExecuteNonQuery()
sqlCommand.Connection.Close()
End Sub
So far, testing has shown that it fires only once per session. Even if the browser moves to another site and comes back, it will not count that as a new session. This seems to be the perfect solution.
I'm open to hear any comments or concerns about this, anybody?
I think, perhaps, you are getting hung up on the request/response cycle of a web page. If you have only ever used WebForms and come from a desktop development background, the statelessness of the HTTP protocol can be very confusing.
Essentially, the client (the browser) requests information from the server (where your .NET code is running). Each request is completely independent from every other request - the server maintains no memory of prior requests.
Now, WebForms was an attempt to bridge the gap by shoe-horning on a sort of pseduo-statefullness on top of HTTP. This is where ViewState and other similar concepts come in. Basically, WebForms includes additional information about the state of the web application in each Response, which is then included again in following Requests, maintaining the application's state and giving the appearance of statefulness. There are other tricks too, like server variables, which can be used to maintain some "memory" of past transactions.
However, this statefulness is easily broken. For example, if you include a basic anchor tag (not an ASP.NET server control), and you redirect to another page (or even the same page) without including the view state, then you will lose some of your application state. Even if you are using server controls and maintaining your view state, you must pay careful attention to the WebForms Page lifecycle. If you are handling the wrong event (such as Page_Load) or attempting to access a property at the wrong time (before the web page has had a chance to reload it's state), you may not get the results you are expecting.
In this scenario, I recommend you check the user's Session ID. It changes very infrequently. If you have a user ID coming in with a session ID you've not seen before (or that's not been associated with that user in some amount of time - say 30 minutes), then you probably have a unique logon event. If you have seen that user ID/Session ID combo, then that user has probably already "logged in" and you don't need to record it again.
Alternatively, just store the user's login state in a session variable. You can check that variable on each Page_Load and branch (using an If statement) based on your needs.

Excel VBA query external .aspx page and retrieve data

I've been struggling with this for about a day. Basically, I want to write an excel macro to loop through a list in excel, query a webpage and retrieve some data. Ideally I just want to retrieve the data I need so I can place it in an adjacent cell, but I'd do whatever it takes at this point.
The page is ASP.net, which I have no experience in; if it was .php I could probably manage, but I’m not even sure how to post to .aspx through javascript.
I can loop through my data just fine, and once I get the data I can write it to excel, so there are two parts I’m struggling with:
Part 1 – querying the webpage
This is the page I want to query. I need to search in Property Address and retrieve data from the results. The address I'll use for the example is 400 W Church St. I thought it may be simple to submit a form like ".../ParcelSearch.aspx?name=...&value=...", but no dice.
Part 2 – grabbing the data
On the results, there is a table DetailsSummary_Master up top, with fieldsets that are defined with <legend> tags. I need the data in <legend>Municipality</legend>:
I can’t figure out what to do, loop through the <td>s? I thought maybe I could GetElementByID or maybe by tag, but I can’t seem to figure it out.
VBA
I used a few SO threads to try to figure it out so far. First, Second and Third, but I can't even seem to get it to POST properly. I'm keeping the subs separate for now.
This is what I have (stolen from the other thread) in regards to my problem:
Sub SubmitForm()
Dim objIE As Object
Dim xmlhttp As Object
Dim ieButton As Object
Dim strResponse As String
Dim strUrl As String
Dim strID As String
Dim strValue As String
Dim strSubmit As String
strID = "?name=ctl00_ctl00_ctl00_ctl00_ContentMain_ContentMain_ContentMain_ContentMain_TabContainer1_Searches_SubTabContainer1_QuickSearches_CompositAddressSearch1_AddressSearch1_ctl00_Address&value="
strValue = "400 W Church St"
strSubmit = strID & strValue
strUrl = "http://www.ocpafl.org/searches/ParcelSearch.aspx"
Set objIE = CreateObject("InternetExplorer.Application")
objIE.navigate "about:blank"
Set xmlhttp = CreateObject("MSXML2.ServerXMLHTTP")
'~~> Indicates that page that will receive the request and the type of request being submitted
xmlhttp.Open "POST", "http://www.ocpafl.org/searches/ParcelSearch.aspx", False
'~~> Indicate that the body of the request contains form data
xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
'~~> Send the data as name/value pairs
xmlhttp.Send "strSubmit"
strResponse = xmlhttp.responseText
objIE.navigate strUrl
objIE.Visible = True
Do While objIE.readystate <> 4
DoEvents
Loop
objIE.document.Write strResponse
Set xmlhttp = Nothing
End Sub
I don't actually need to run it through IE, I'd like to run it all hidden. I'm running this on Excel 2007 at work, but I have 2010 at home. We also have ridiculous IE8, so the less of that, the better. And I can loop or use an array, but I just can't seem to interface with the query. Any help would be greatly appreciated.
For making the query, given the complexity of the form fields that the ASPX page is expecting on postback, you might find it easier to control the browser when making this call. It will be rather slow, but it should work.
A fairly reliable tool for this is Selenium, and there are plugins to control Selenium from Excel VBA.
Edit: This Excel VBA code snippet should read out "Municipality Orlando". You need to parameterize the below code and add cases for error conditions for your final version to query by any street address to get its municipality. This should get you started though. I used Selenium IDE with Firefox to generate the VBA code based on recording user actions, and then came up with an XPath query to grab the text.
Dim selenium As New SeleniumWrapper.WebDriver
selenium.Start "firefox", "http://www.ocpafl.org/searches/ParcelSearch.aspx"
selenium.setImplicitWait 5000
selenium.setImplicitWait 5000
selenium.Open "/searches/ParcelSearch.aspx"
selenium.Click "id=popup_ok"
selenium.Type "id=ctl00_ctl00_ctl00_ctl00_ContentMain_ContentMain_ContentMain_ContentMain_TabContainer1_Searches_SubTabContainer1_QuickSearches_CompositAddressSearch1_AddressSearch1_ctl00_Address", "400 W Church St"
selenium.Click "id=ctl00_ctl00_ctl00_ctl00_ContentMain_ContentMain_ContentMain_ContentMain_TabContainer1_Searches_SubTabContainer1_QuickSearches_PropertyNameSearch1_ctl00"
selenium.Click "id=ctl00_ctl00_ctl00_ctl00_ContentMain_ContentMain_ContentMain_ContentMain_TabContainer1_Searches_SubTabContainer1_QuickSearches_CompositAddressSearch1_AddressSearch1_ctl00_ActionButton1"
Dim municipalityResult As String
municipalityResult = selenium.getText("//fieldset[contains(legend,'Municipality')]")
selenium.stop

ASP.NET ScriptManager History url hash lost after redirect

I have seen several posts online complaining that Firefox maintains the history url hash after redirecting.. That is the behavior I am hoping for - and it happens in Firefox (11.0), Chrome (18.0), and Opera (11.61), but not IE (9) or Safari (5.1.2).
On my page, I have ASP.NET 4.0 history points set up and working (has been working for a couple years). I also pass a few querystring params to the page. What I am trying to do now is check the value of a new querystring param, and if it does not match what I am expecting, redirect to the same page with an updated value. I am using this mechanism to track the session of individual tabs of a browser so that when they have the same page open in multiple tabs, the session values dont step on each other from tab to tab.
Anyway, I have everything working correctly including the back/forward using ASP.NET History points - and when I visit a bookmark and the querystring param does not match, I redirect and change the querystring param to track the session, and the history state that is in the url of the bookmark is then used to reload the page to the state I want. But that only works in Firefox, Chrome, and Opera. Not IE which is the big one for me (based solely on our user base), and not Safari.
I have identified that in addition to (or perhaps because of) the fact that the url history state is not present, ScriptManager.Navigate is not called after the redirect in IE or Safari.
Is there a setting/option that I can set on the ScriptManager or during the redirect to maintain the History state in the url? If the history state was in the url, I could call ScriptManager.Navigate directly if I needed to, but the values are not present in the url.
If it helps at all, here's a listing of where I do the check and redirect. The ReportRunID is then appended to the session variable keys that need to be unique to each tab. I keep a listing of previous ReportRunIDs to keep track and to clean them out (after a certain time period, or when more than [MAX] ids are encountered) so that I dont overload server memory with these session entries.
Private Sub Page_PreInit(sender As Object, e As System.EventArgs) Handles Me.PreInit
If IsPostBack = False Then
Dim rrid As String = Request.QueryString("RRID")
If ReportRunIDExists(rrid) = False Then
ReportRunID = Now.ToString("_HHmmssfff")
Dim url As String = Request.Url.PathAndQuery
If String.IsNullOrEmpty(rrid) Then
Response.Redirect(String.Format("{0}&RRID={1}", url, _reportRunID))
Else
Dim idx As Integer = url.IndexOf("&RRID=")
Response.Redirect(String.Format("{0}&RRID={1}{2}", url.Substring(0, idx), _reportRunID, url.Substring(idx + 6 + rrid.Length)))
End If
End If
End If
End Sub
Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
'save current RRID/Page/Time to session
UpdateSessionReportRunID(_reportRunID)
End Sub
...
If my bookmarked url looks like:
mysite.com/mypage.aspx?Rpt=123&RRID=_095224678#&&state1=abc&state2=def...
In FF/Chrome/Opera after the redirect, my url looks like:
mysite.com/mypage.aspx?Rpt=123&RRID=_102176253#&&state1=abc&state2=def...
But in IE/Safari after redirect, my url looks like:
mysite.com/mypage.aspx?Rpt=123&RRID=_102176253
Any ideas?
After much more searching, I have come to the realization that History State hash is not sent to the server. It is stored in the querystring so that it is included in bookmarks, but it is accessed by the client-side scriptmanager which causes a postback to load the state values. Since the Server never sees the hash value in the querystring, I have no way of finding those values when a user follows a bookmark to that page.
This problem was introduced as I was trying to start tracking the session state of different browser tabs individually. In my code above, if the RRID parameter is empty or invalid, I have to redirect to self with a new RRID value. When I do that redirect the History State hash was being lost for IE and Safari (but not for the other browsers).
My workaround:
The problem is that I needed to include the hash value in my redirect, but that is not available from the server, so I decided to inject some javascript to the page to perform the redirect from the client where the hash is available.
I already had a Client Redirect extension helper method that I have used in different scenarios, and I modified it to include the current hash value:
<System.Runtime.CompilerServices.Extension()>
Public Sub ClientRedirect(ByVal Response As HttpResponse, ByVal url As String, Optional ByVal target As Target = Nothing, Optional ByVal windowFeatures As String = Nothing, Optional includeCurrentHash As Boolean = False)
If IsNothing(target) Then
If windowFeatures = String.Empty Then
target = ResponseHelper.Target._self
Else
target = ResponseHelper.Target._blank
End If
End If
Dim page As Page = CType(HttpContext.Current.Handler, Page)
url = page.ResolveClientUrl(url)
Dim script As String
script = "window.open(""{0}"", ""{1}"", ""{2}"");"
script = String.Format(script, url & If(includeCurrentHash, "#"" + window.location.hash + """, String.Empty), target.ToString, windowFeatures)
If target = ResponseHelper.Target._self Then
'execute after page has loaded
page.ClientScript.RegisterStartupScript(GetType(Page), "Redirect_" & Now.ToString("HHmmssfff"), script, True)
Else
'execute as page is loading
page.ClientScript.RegisterClientScriptBlock(GetType(Page), "Redirect_" & Now.ToString("HHmmssfff"), script, True)
End If
End Sub
Then in my Page_PreInit where I do the redirects, I changed that to do the ClientRedirect including the current hash, and that has gotten the desired result:
Redirecting the browser while maintaining the History State hash on all browsers.
'redirect from the client so that we keep the History State URL hash
Response.ClientRedirect(String.Format("{0}&RRID={1}", Request.Url.PathAndQuery, _reportRunID), , , True)

Resources