How to share a variable value with a webmethod? - asp.net

I have this code:
Dim main_id As int
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
main_id =1
End Sub
<WebMethod()> _
Public Shared Function BindPersonnel(ByVal product_id As String) As String
Dim project_id AS int16
project_id=main_id 'this doesn't work
End Function
On page load, I set the value of variable main_id and I need a way to somehow share the main_id with webmethod function, how can this be done? I have not tried session variable and I don't want to use session variable. I found this link Accessing a common variable in WebMethod and jQuery but I can't figure out how this is going to solve my problem. I also read some posts about using hidden field, which requires me to go two trips. I would love to avoid that.

WebMethods are independent of the other variables on the page. If you want to access main_id, you could declare it as Private Shared main_id As Integer, but that would then cause all of your users to have access to the same ID value, which you probably don't want.
Perhaps the easiest way to do this is to store the value in SessionState, and enable sessionstate access in the WebMethod. On the other hand, this removes the asynchronous-like functionality that you are looking for (it may not be an issue).
SessionState will give you the ability to have a per-session value (avoiding the use of the Shared solution mentioned above).
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Session("main_id") = 1
End Sub
<WebMethod(EnableSession:=True)>
Public Shared Function BindPersonnel(ByVal product_id As String) As String
Dim project_id As Integer = CInt(HttpContext.Current.Session("main_id"))
End Function

Related

Variables Code Behind Cant Access

This is probably is straight forward.
I have a DropDownList and once a user click on an item I need to remember what they clicked before the DropdownList gets rebound so I made a variable outside.
But the problem is that variable cant be seen. The only time I managed to get it to work is using Public Shared variableoutside as Integer. But this makes it available to every page I only need it on this page I am running.
Dim variableoutside as Integer
Protected Sub lstTest_DataBound(sender As Object, e As EventArgs) Handles lstTest.DataBound
if variableoutside > 0 Then lstTest.SelectedIndex = variableoutside
End Sub
Protected Sub lstTest_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lstTest.SelectedIndexChanged
variableoutside = lstTest.SelectedIndex
lstTest.DataValueField = "ID"
lstTest.DataTextField = "testvalue"
lstTest.DataSource = List_TestA.List_Test()
lstTest.DataBind()
End Sub
Fields only live as long as the request. On postback you get a new instance of the Page class, so new instance fields.
A Shared (static in C#) field does live longer (entire lifetime of the application), but it's value is shared between all users of your site - probably not what you want.
A solution is to store that value in Session. That is designed for request-spanning storage of user-specific values. Note that the values are stored as Object, so you will need to cast back to Int.
EDIT
for instance, your code
Protected Sub lstTest_DataBound(sender As Object, e As EventArgs) Handles lstTest.DataBound
if variableoutside > 0 Then lstTest.SelectedIndex = variableoutside
End Sub
could be
Protected Sub lstTest_DataBound(sender As Object, e As EventArgs) Handles lstTest.DataBound
Dim variableoutside as Integer
variableoutside = Session("ListIndex") ' probably cast this to Integer
if variableoutside > 0 Then lstTest.SelectedIndex = variableoutside
End Sub
(note that I am guessing at the correct VB syntax, so you may need to tweak this)
And of course in the other method, instead of:
variableoutside = lstTest.SelectedIndex
use this to set that session value:
Session("ListIndex") = lstTest.SelectedIndex
You can remove that class field, as that's no longer used.
Wow, that is really cool. I like it, Thank you...
I changed it a little though and ditched the Dim variableoutside
and used the Session("lstTest") as my main variable. It remembers every time.
You have opened lots of doors for me, and now I can use them to remember lots
of settings for DropDownList,CheckBoxes, Textboxes.
Only thing I wanted to know is how many of those session variables are you allowed, as I am assuming that the sessions are using cookies and cookies have a max allowed per client and browser before that start overwriting themselves. At least this was true when I was using PHP back in the day.

How to prevent the object from becoming null?

I have the following code. During page load, I get the customer object from the database. After that when I try to access the same object in a different method, the object comes out as empty. Assume Student object has properties like firstName, lastName etc.
Public class Test
Public oStudent as Student
Public Sub Page_Load(ByVal sender as Object, ByVal e as System.EventArgs) Handles Me.Load
oStudent = getStudent(22) 'This is just a sample. This is not my actual database.
End Sub
Public Sub Update(ByVal sender as Object, ByVal e as System.EventArgs) Handles crtlStudent.Update
Update(oStudent)'This one updates makes a database call to update the studnet
End Sub
End class
When the page loads, the student is returned from the database correctly. However, when I'm on my update method, oStudent object becomes null/empty. Is this the way the page life cycle works? If yes, I would need to store the oStudent in a session or cache it right? Is there any other way to prevent the oStudent from becoming null other using session variables or caching it?
It is not the case that the object is null in the other method but after the page is disposed. That happens at the end of every page's lifecycle, so when it was rendered as HTML and sent to the client.
So you either have to re-initialize/load the object on every postback or persist it somewhere. In your sample-code you are loading it always in Page_Load, hence i doubt that it's null anywhere. So i guess that it's not the real code which could be:
Public Sub Page_Load(ByVal sender as Object, ByVal e as System.EventArgs) Handles Me.Load
If Not IsPostBack Then
oStudent = getStudent(22) ' in a button-click handler it will be null since it's a PostBack
End If
End Sub
Is there any other way to prevent the oStudent from becoming null
other using session variables or caching it?
Nine Options for Managing Persistent User State in Your ASP.NET Application

Friendly URLs and Query Strings

In my project (ASP.NET Web Forms) I want to use Friendly URLs, installed from NuGet.
I registered route in global.asax file:
Public Shared Sub RegisterRoutes(routes As RouteCollection)
routes.MapPageRoute("Route", "default/{id}", "~/default.aspx?id={id}")
End Sub
With this code, I can use default/123 instead of default?id=123. I want to add name, assigned to the id, in the url. So I can have url like this: default?123-Firstname-Lastnam. Name is saved in database, in single column. How can I add second parameter (name) to the url, add symbol - and display it without letters like this: řčš (because the application is in Chech language.
Thanks for answer.
To use FriendlyUrls, after you install it from NuGet, go to your global.asax and enable it:
Imports Microsoft.AspNet.FriendlyUrls
Public Class Global_asax
Inherits System.Web.HttpApplication
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
RegisterRoutes(RouteTable.Routes)
End Sub
Sub RegisterRoutes(ByVal routes As RouteCollection)
routes.EnableFriendlyUrls()
End Sub
'rest of global
That is pretty much it. To get the values out of a URL for a page, you'll need to loop through the URL segments (don't forget Imports Microsoft.AspNet.FriendlyUrls):
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
For Each segment As String In HttpRequestExtensions.GetFriendlyUrlSegments(Request)
Dim val As String = segment
Next
End Sub
So visiting siteURL.com/default/123 will loop once and give you 123, while siteURL.com/default/122/Bilbo/Baggins will loop three times and give you 122, Bilbo, and Baggins.
Or, if you just want to use plain routing and not FriendlyUrls:
routes.MapPageRoute("id-route", "default/{id}", "~/default.aspx")
One good thing about routing is you can use the URL to pass variable data without using query strings. So the route to pass name data could look like
Sub RegisterRoutes(ByVal routes As RouteCollection)
routes.MapPageRoute("name-route", "default/{id}/{firstName}/{lastName}", "~/default.aspx")
End Sub
And then default.aspx could be hit with siteURL.com/default/123/Frodo/Baggins and has:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
Dim id As Integer = 0
Int32.TryParse(Page.RouteData.Values("id"), id)
Dim firstName As String = Convert.ToString(Page.RouteData.Values("firstName"))
Dim lastName As String = Convert.ToString(Page.RouteData.Values("lastName"))
'do something if id > 0
End Sub
Other Considerations: If you only want name in a single column, then you can combine the firstName and lastName variables for saving. Using - as a delimeter like you show in question isn't a good idea, as people can have hyphenated names. Saving name in a single column tends to cause problems as it makes it much harder to sort by first or last name, etc.
Also it appears you will be inserting into your database from a GET command. I would think this would be much more clear to do using PUT or POST.

Preserve Data-structure on AJAX postback

Partial Class ClientCenter_UpdateSub
Inherits System.Web.UI.Page
Structure PInfo
Dim Name As String
Dim Surname As String
End Structure
Dim OldPInfo As New PInfo
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
'blah blah
OldPInfo.Name = Dt.Rows(0).Item("Name").ToString
OldPInfo.Surname = Dt.Rows(0).Item("Surname").ToString
end if
end sub
End Class
The first time the page loads my structrure is filled correctly.
After an AJAX postback all the structure fields are setting to nothing. (It seems that the Dim OldPInfo As New PInfo is called again), but i should better ask the SO Experts.
So anyway, what am i doing wrong here?
First off, You should never assign a variable outside of a property or a method.
Second, web applications are stateless (which means NOTHING is automatically saved from call to call - unless you store it somewhere like Viewstate, Session, etc.).
Remember to accept this answer if it helps solve your problem.

How to Persist Variable on Postback

I created a single page (with code behind .vb) and created Public intFileID As Integer
in the Page load I check for the querystring and assign it if available or set intFileID = 0.
Public intFileID As Integer = 0
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
If Not Request.QueryString("fileid") Is Nothing Then
intFileID = CInt(Request.QueryString("fileid"))
End If
If intFileID > 0 Then
GetFile(intFileID)
End If
End If
End Sub
Private Sub GetFile()
'uses intFileID to retrieve the specific record from database and set's the various textbox.text
End Sub
There is a click event for the Submit button that inserts or updates a record based on the value of the intFileID variable. I need to be able to persist that value on postback for it all to work.
The page simply inserts or updates a record in a SQL database. I'm not using a gridview,formview,detailsview, or any other rad type object which persists the key value by itself and I don't want to use any of them.
How can I persist the value set in intFileID without creating something in the HTML which could possibly be changed.
[EDIT] Changed Page_Load to use ViewState to persist the intFileID value
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
If Not Request.QueryString("fileid") Is Nothing Then
intFileID = CInt(Request.QueryString("fileid"))
End If
If intFileID > 0 Then
GetFile(intFileID)
End If
ViewState("intFileID") = intFileID
Else
intFileID = ViewState("intFileID")
End If
End Sub
As others have pointed out, you can store it in the Session or the ViewState. If it's page specific, I like to store it in the ViewState as opposed to the Session, but I don't know if one method is generally preferred over the other.
In VB, you would store an item in the ViewState like:
ViewState(key) = value
And retrieve it like:
value = ViewState(key)
Store in:
Session
ViewState
Hidden input
Just to summarize what is said above.
You can use Session, Viewstate, or a hidden field.
I personally prefer viewstate as it will work in web farm environments, Session does not, it does not store it on the server waiting for the user, for up to 20 minutes to be removed, and in general viewstate is the place to be for page level data.
You can use a hidden field, but then a user could more easily modify it.
Store it in the Session.
Page.Session["MyPage_FileID"] = intFileID
You'll need to have logic that manages it as the user navigates around, but if it is always set when the page loads from a GET (or you clear it, if not available on GET) then you should be ok using it later from the Session on your submit PostBack.
Remember:
Each time your server code runs, it's in a brand new instance of your page class. That's for every postback.
Actually, since an ASP.NET page postbacks to itself - including the query string - you could just remove the If Not Page.IsPostBack condition. Then it'd set itself on each postback.
I personally would choose to store the value in control state instead of viewstate as viewstate can easily be switched off. ControlState will persist even if viewstate is switched off for any reason. I have included an example on how this may be done.
Private intFileId As Integer = 0
Public Property FileID() As Integer
Get
Return intFileId
End Get
Set(ByVal value As Integer)
intFileId = value
End Set
End Property
Protected Overrides Function SaveControlState() As Object
Dim objState(2) As Object
objState(0) = MyBase.SaveControlState()
objState(1) = Me.FileID
Return objState
End Function
Protected Overrides Sub LoadControlState(ByVal savedState As Object)
Dim objState() As Object
objState = savedState
MyBase.LoadControlState(objState(0))
Me.FileID = CInt(objState(1))
End Sub
Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
Me.Page.RegisterRequiresControlState(Me)
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
If Not String.IsNullOrEmpty(Request.QueryString("fileid")) Then
Me.FileID = CInt(Request.QueryString("fileid"))
End If
End If
Response.Write(Me.FileID.ToString())
End Sub
Session["KeyName"] = your value;
Type cast to the type to retrieve and store the data from session like given below :
Datatable dt = (DataTable)(Session["KeyName"]);
or
ViewState["KEY"]= value;
Type cast to the type to retrieve and store the data from session like given below :
String str = (String)ViewState["KEY"];
I'll use Session as suggested by tvanfosson.
ViewState and HiddenField might be too heavy if you want to keep large data like a dataset for comments in a forum's topic pages..

Resources