SessionID not retaining same value through a session - asp.net

I have a strnge problem which I dont know how to resolve.
The sessionID keeps changing every time I open a page in the application.
But when I debug the program, the sessionID remains constant and does not change
The application is installed on Windows server 2008 R2 (iis 7.5 and dotnet framework 4.0)
<sessionState cookieless="UseCookies" mode="InProc" sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes" stateConnectionString="tcpip=127.0.0.1:42424" timeout="60" />
What is the matter?
Note: This works fine on my local development machine.
EDIT
This is the code in Global.asax.vb for Session_Start`
Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
Session("mySessions") = "junk"
AddMySessions()
If User.Identity.IsAuthenticated Then
Dim cmd As New SqlCommand
Dim sql As String
sql = String.Format("SELECT EmpID FROM Intranet_Employees WHERE Username='{0}'", sUserName)
cmd.CommandText = sql
' Production ...
Session("EmpID") = CType(Dao.ExecuteScalar(cmd, ConfigurationSettings.AppSettings("cSqlTemplateDB")), String)
Dim oEmpInfo As New TOrders.Data.Objects.Employee(Convert.ToInt64(Session("EmpID")))
Session("EmpInfo") = oEmpInfo
If Application("SessionCount") Is Nothing Then
Application.Lock()
Application("SessionCount") = 0
Application.UnLock()
End If
Application.Lock()
Application("SessionCount") += 1
Application.UnLock()
Else
Response.Redirect("http://intranet/tsystem")
End If
End Sub
Private Sub AddMySessions()
Dim sMsg As String = Session.SessionID & ";" & Now.ToString & ";" & Request.ServerVariables.Get("AUTH_USER").ToString
If IsNothing(Application("mySessions")) Then
Dim arrSessions As New ArrayList
arrSessions.Add(sMsg)
Application.UnLock()
Application("mySessions") = arrSessions
Application.Lock()
arrSessions = Nothing
Else
Dim arrTemp As ArrayList = CType(Application("mySessions"), ArrayList)
arrTemp.Add(sMsg)
Application.UnLock()
Application("mySessions") = arrTemp
Application.Lock()
arrTemp = Nothing
End If
sMsg = Nothing
End Sub
`

From MSDN:
When using cookie-based session state, ASP.NET does not allocate
storage for session data until the Session object is used. As a
result, a new session ID is generated for each page request until the
session object is accessed. If your application requires a static
session ID for the entire session, you can either implement the
Session_Start method in the application's Global.asax file and store
data in the Session object to fix the session ID, or you can use code
in another part of your application to explicitly store data in the
Session object.
If your application uses cookieless session state, the session ID is
generated on the first page view and is maintained for the entire
session.

After more than week of frustration, I finally figured it out. The issue was not with the code or web.config - but with the naming of the Server. The server name contained the underscore '_' which was blocking cookies. The server name was changed and everything worked fine.
#fnostro - Thanks for your patience and suggestions.
Here is the link from microsoft.
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q316112

Related

Can't share isolated storage file between applications in different app pools

I've got various web apps (containing WCF services) in IIS under the default website. As long as they are all running in the same app pool they can access a shared isolated storage file no problem.
However, once I move them to different app pools I get "System.IO.IsolatedStorage.IsolatedStorageException: Unable to create mutex" when one tries to access a file created by another. They are all running under NetworkService user. I tried GetUserStoreForAssembly and GetMachineStoreForAssembly all with the same result. Any ideas why they couldn't use a shared file?
I made sure to close the stream and even dispose it in case one was holding onto it, but I am running a simple test where one service writes it, then another tries to read from it later, and it always fails.
Also, I am accessing the isolated store from a signed assembly.
Does anybody have any ideas?
Here is the code:
Private Sub LoadData()
Dim filename = FullFilePath(_fileName)
Dim isoStorage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForAssembly()
' Tried GetMachineStoreForAssembly, same failure
isoStorage.CreateDirectory(ROOT_DIRECTORY)
If (isoStorage.GetFileNames(filename).Length = 0) Then
Return
End If
Dim stream As Stream = New IsolatedStorageFileStream(filename, FileMode.OpenOrCreate, isoStorage)
If stream IsNot Nothing Then
Try
Dim formatter As IFormatter = New BinaryFormatter()
Dim appData As Hashtable = DirectCast(formatter.Deserialize(stream), Hashtable)
Dim enumerator As IDictionaryEnumerator = appData.GetEnumerator()
While enumerator.MoveNext()
Me(enumerator.Key) = enumerator.Value
End While
Finally
stream.Close()
stream.Dispose()
stream = Nothing
End Try
End If
End Sub
Public Sub Save()
Dim filename = FullFilePath(_fileName)
' Open the stream from the IsolatedStorage.
Dim isoFile As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForAssembly()
' Tried GetMachineStoreForAssembly, same failure
Dim stream As Stream = New IsolatedStorageFileStream(filename, FileMode.Create, isoFile)
If stream IsNot Nothing Then
Try
Dim formatter As IFormatter = New BinaryFormatter()
formatter.Serialize(stream, DirectCast(Me, Hashtable))
Finally
stream.Close()
stream.Dispose()
stream = Nothing
End Try
End If
End Sub
Looks like it was a trust issue.
After adding the assembly accessing the isolated storage file to the gac it magically worked as everything in the gac has full trust set automatically.
This works for me, but it might not always be an option to do this for other solutions. Check out the .NET Framework caspol utility if this is the case.
Hope this helps somebody! It was a huge pitafor me.

.NET 4.0 FormsAuthentication.SetAuthCookie FAIL

I know there are a few questions out there on this already but none seem to help my problem.
I am debugging a VB.NET webForms app and I cannot Get FormsAuthentication.SetAuthCookie to work (with a non-persistent cookie). It seems to create an HttpContext.Current.User object when I check for it in a watch window it seems to have created the object, but not its "Identity" property.
I've read a bunch of SO posts checked the basic things, like seeing if my browser supports cookies, etc... This project is a direct port from an earlier project of ours, which uses the same code for all things listed here, and it works just fine, relatively speaking. Where this throws an exception is where it's called from my BLL code that is supposed to get it.
Here is the code that calls the FormsAuthentication method...:
'When participant logs in having already created records in DB.
Protected Sub btnGo_Click(ByVal sender As Object, ByVal e As System.Web.UI.ImageClickEventArgs) Handles btnGo.Click
If Me.txtUsername.Text.Trim.Length <> 0 AndAlso Me.txtPassword.Text.Trim.Length <> 0 Then
If Membership.ValidateUser(Me.txtUsername.Text, Me.txtPassword.Text) Then
FormsAuthentication.SetAuthCookie(Me.txtUsername.Text, False)
'This is where we run into trouble; the property checks with the forms auth...
MyBLL.Common.CurrentUser = New MyBLL.User(Me.txtUsername.Text)
'set site property..
If Site_ IsNot Nothing Then
MyBLL.Common.CurrentUser.Site = Me.Site_
End If
MyBLL.Common.CurrentParticpant = Nothing
MyBLL.Common.CurrentParticpantVisitID = -1
Response.Redirect("~/Apps/Dashboard.aspx", True)
Else
Me.lblLoginMsg.Visible = True
End If
Else
Me.lblLoginMsg.Visible = True
End If
End Sub
Here is the code for the BLL object (which has a shared property calling user from HttpContext...)
Public Shared Property CurrentUser() As MyBLL.User
Get
Dim objUser As MyBLL.User
If Not IsNothing(HttpContext.Current.Session("currentSiteUser")) Then
objUser = CType(HttpContext.Current.Session("currentSiteUser"), MyBLL.User)
If objUser.Username <> HttpContext.Current.User.Identity.Name Then
objUser = New MyBLL.User(HttpContext.Current.User.Identity.Name)
HttpContext.Current.Session("currentSiteUser") = objUser
End If
Else
objUser = New MyBLL.User(HttpContext.Current.User.Identity.Name)
HttpContext.Current.Session("currentSiteUser") = objUser
End If
Return objUser
End Get
Set(ByVal value As MyBLL.User)
'_CurrentUser = value
HttpContext.Current.Session("currentSiteUser") = value
End Set
End Property
Here is the Forms element from my webConfig; everything seems alright here to me...
<authentication mode="Forms">
<forms loginUrl="~/Public/Default2.aspx" defaultUrl="~/Public/Default2.aspx" timeout="60"/>
</authentication>
You should immediately redirect after callaing the SetAuthCookie method and only on subsequent requests you may hope to get the full IPrincipal to be initialized. Do not try to access HttpContext.Current.User.Identity.Name in the same controller action in which you called the SetAuthCookie method. It won't have any effect. The redirect is important so that on the next request the forms authentication module will built the principal from the request cookie.
In your CurrentUser method you seem to be calling the HttpContext.Current.User.Identity.Name property but this is not available until you redirect.

How can I transfer login value to another page?

I am a newbie in using asp.net with code behind of vb.net I just wanna know on how to see the name of the admin on the POS page. it seems that this code doesn't work??
Main.lbl_name.Text = CurName.ToUpper
POS.lbl_cashier.Text = CurName.ToUpper
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim cmd1 As New SqlCommand
Dim rdr As SqlDataReader
cmd1.Connection = cn
cmd1.Connection.Open()
cmd1.CommandText = "SELECT * from UserTable WHERE Username ='" & txt_username.Text & "'"
rdr = cmd1.ExecuteReader
If rdr.HasRows = True Then
rdr.Read()
If txt_username.Text = rdr.Item(0) And txt_password.Text = rdr.Item(3) Then
CurPos = rdr.Item("Type")
CurUser = rdr.Item("Username")
CurName = rdr.Item("EmployeeName")
If rdr.Item(4) = "ADMINISTRATOR" Then
MsgBox("WELCOME! " & rdr.Item(4), MsgBoxStyle.Information)
'Main.lbl_name.Text = CurName.ToUpper
'POS.lbl_cashier.Text = CurName.ToUpper
cmd1.Connection.Close()
Response.Redirect("ACESCHOOLSUPPLIES.aspx")
'Me.Dispose()
You can't just access other pages, ASP.NET runtime is ignorant about other pages, you have access to your current page only!
You can use the Session variable to store some data temporarily for current user session, the Session object is available on every ASP.NET Page.
Session("adminname") = CurName
On other page where you want to show it you just reload it from Session
Dim NewName = Session("adminname")
Take some hidden field and use session.add("username") and store your username or which ever you want and the n retrieve that from your second page.
Session.Add("Username",Username);
does essentially the same as
Session["Username"] = Username;
As Alaudo suggested, storing variables in Session state is an option.
For the sake of completeness other options you have are:
Cookies
QueryString
Hidden fields (for POST requests)
The logged on user name is something I personally would not store in Session state or pass around using any of the alternate techniques I mention above.
Looking at your code it seems you are trying to authenticate some credentials (user name/password).
I recommend you look at MemebershipProvider in ASP.NET. Are you familiar with this? You can then easily access the logged in user.

How to make a fileupload interface in ASP.NET

I am trying to make a file upload interface in ASP.NET webforms and am looking for some advice on how to proceed.
The file upload interface is part of a website I am making on which users can post adverts. The interface is part of the "create a new advert" and will enable the user to upload up to 6 images. I am using only the asp.net FileUpload server control as I am trying to make a control which will work when users have javascript disabled. That's the background.
The upload for all 6 files occurs on button click. This stores the files in a temp folder (/UserUploads/temp) until the user submits the form in which case the files are moved to the /UserUploads folder and the references in the database or until the user hits the cancel button or navigates away in which case the files are deleted.
First question is: Is storing the files in a temp directory the right way to go about this? Or is there some better way of keeping the temp files on the server until the parent form is submitted? The only alternative I can think about is saving the files to the session, but that seems like a recipe for killing the server...
Second question: I am unclear what to do when the user just closes the browser window. I want to avoid ending up with a mess of orphaned files in the temp directory. Is there some way to make sure that all the files will get cleared out if the user doesn't go through with the form submission? Or do I just have to perform a cleanup of the temp directory every so often?
Third question: Am I doing this completely wrong and there is in fact a much better approach to uploading multiple files?
1) If you are using SQL Server, I personally prefer to store uploaded files in a varbinary(max) field and work with them by their unique ID. Then you don't have to worry about name collisions or de-sync of your DB to your filesystem. This also allows your upload process to be independent of the insertion of the parent form.
The examples below show how to grab the file stream (and metadata) from a FileUpload control in a FormView and supply it as a parameter to a SQL stored procedure. Then, a class implementing IHTTPHandler is used to retrieve files from the DB.
2) As far as clearing out temp files, I would associate each uploaded file with a temp master record so they are tied together. When the real master is confirmed, delete the temp master (and reference files from the real master). Then run a SQL Agent job on a regular interval to delete temp masters and associated files that are older than X amount of time.
Saving:
Protected Sub DetailsView1_ItemInserting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DetailsViewInsertEventArgs) Handles DetailsView1.ItemInserting
Dim objUploader As FileUpload = DetailsView1.FindControl("fuFile")
If objUploader.HasFile Then
Dim strFileName As String = objUploader.PostedFile.FileName
strFileName = strFileName.Substring(strFileName.LastIndexOf("\") + 1)
Dim objFileStream As System.IO.Stream = objUploader.PostedFile.InputStream
Dim arrFileImageByteArray(objFileStream.Length) As Byte
objFileStream.Read(arrFileImageByteArray, 0, objFileStream.Length)
e.Values.Insert(0, "FileImage", arrFileImageByteArray)
e.Values.Insert(1, "FileName", strFileName)
e.Values.Insert(3, "PostingDate", Now)
e.Values.Insert(5, "Application", "CorpForms")
Else
e.Cancel = True
objMessages.Add(New StatusMessage(MessageType.Warning, "File Upload canceled. No file was selected."))
End If
End Sub
Retrieving:
Public Class FileServiceHandler : Implements IHttpHandler
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim idFileID As Guid
If context.Request.QueryString("FileID") IsNot Nothing Then
Dim strFileID As String = context.Request.QueryString("FileID")
Try
idFileID = Guid.Parse(strFileID)
Catch ex As Exception
Throw New Exception("Unable to parse File ID")
End Try
End If
Dim objConnection As New SqlConnection(ConfigurationManager.ConnectionStrings("PublicWebConnectionString").ConnectionString)
Dim objCommand As SqlCommand = objConnection.CreateCommand
Dim objReader As SqlDataReader
objCommand.CommandType = Data.CommandType.StoredProcedure
objCommand.CommandText = "spGetUploadedFile"
objCommand.Parameters.AddWithValue("FileID", idFileID.ToString)
Dim arrFileImage() As Byte = Nothing
Dim strFileName As String = String.Empty
Try
objConnection.Open()
objReader = objCommand.ExecuteReader
While objReader.Read
If Not IsDBNull(objReader("FileImage")) Then
arrFileImage = objReader("FileImage")
End If
If Not IsDBNull(objReader("FileName")) Then
strFileName = objReader("FileName")
End If
End While
Catch ex As Exception
Throw New Exception("There was a problem retreiving the file: " & ex.Message)
End Try
If objConnection.State <> Data.ConnectionState.Closed Then
objConnection.Close()
End If
If arrFileImage IsNot Nothing Then
context.Response.Clear()
context.Response.AddHeader("content-disposition", "attachment;filename=" & strFileName)
context.Response.BinaryWrite(arrFileImage)
context.Response.End()
Else
context.Response.ContentType = "text/plain"
context.Response.Write("Unable to retrieve file ID# " & idFileID.ToString)
End If
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return True
End Get
End Property
End Class
Web.Config in file retrieval path:
<configuration>
<system.web>
<httpHandlers>
<add verb="GET" path="*" type="MyNamespace.FileServiceHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers>
<add name="MyNamespace.FileServiceHandler" path="*" verb="*" type="MyNamespace.FileServiceHandler" resourceType="Unspecified" preCondition="integratedMode" />
</handlers>
</system.webServer>
</configuration>
File upload is always annoying. I recently found a great component that does what I belive all upload componentes should do.
See at:
http://aquantum-demo.appspot.com/file-upload
And a sample in C# at:
https://github.com/BoSchatzberg/jfu-CSharp-Example
And, you should store your files in a temporary folder before creating the database row. To avoid a mess of files left useless, you can use a windows temporary folder to delagate to the windows when delete or not those files.
System.IO.Path.GetTempPath()
I would recommend storing the files in the database, rather than a temporary folder.
Don't store them in Session Db - too much information, but include the SessionId in the Files Database record.
So you'd have a Files database with a table along the lines of
Id (int identity field)
Data (varbinary(max))
MimeType (varchar(50))
SessionId (varchar(50))
UserId ??
Then you'd simply need to write a scheduled SQL task to clear images where the session had expired.

Can you name an instance of w3wp.exe so it shows up in attach to process?

I run multiple processes under IIS and when debugging it can be tough to know which process I want to attach to. Can you programatically set the "Title" of a process so that it can be identified in Visual Studio's "Attach to Process" window?
Might be better to change the identity of the process so that you know which one to attach to.
You can use this VS macro to attach to a worker process based on the application name. The only trick is you need to copy Microsoft.Web.Administration.dll from C:\Windows\System32\inetsrv to %PROGRAMFILES(x86)%\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies.
Private Sub AttachToWorkerProcess(ByVal appName As String)
Dim targetPid = FindPoolPIDByName(appName)
If targetPid = -1 Then
MessageBox.Show("Unable to find a worker process hosting " + appName)
End If
Dim processes As EnvDTE.Processes = DTE.Debugger.LocalProcesses
For Each proc As EnvDTE.Process In processes
If proc.ProcessID = targetPid Then
proc.Attach()
End If
Next
End Sub
Private Function FindPoolPIDByName(ByVal appName As String) As Integer
Dim sm As New Microsoft.Web.Administration.ServerManager()
Dim appPoolName As String = Nothing
For Each site In sm.Sites
For Each app In site.Applications
If String.Equals(app.Path, "/" & appName, StringComparison.OrdinalIgnoreCase) Then
appPoolName = app.ApplicationPoolName
End If
Next
Next
If appPoolName Is Nothing Then
MessageBox.Show("Unable to find application " & appName)
End If
For Each wp In sm.WorkerProcesses
If wp.AppPoolName = appPoolName Then
Return wp.ProcessId
End If
Next
Return -1
End Function
Then:
Sub AttachToMyApp()
AttachToWorkerProcess("MyApp")
End Sub
In IIS 7.5 you IIS will automatically create accounts for each appPool with the name of the application pool.
http://learn.iis.net/page.aspx/624/application-pool-identities/

Resources