Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Public Shared variable in multi user 1

Status
Not open for further replies.

bigfoot

Programmer
May 4, 1999
1,779
US
Hello all.

I've been reading on the net about the use of classes in web pages but the information gets erased on every page trip to the server.
Then I was reading a book on C# and it used a class with Shared functions and variables.

If I have a web application in asp.net and I reference a class with Shared variables and functions, will I run into any problems with multi users?

If so then how else is it done? I wanted to store all of my variables in a class the same as I do with an exe.


Public Shard Function xyz()

Any info would be great. I don't want to do all this work then have to rewrite it.
 
1. learn the concepts of Object Oriented Programing.
2. learn the concepts of the .net framework. if you are just starting out I would recommend C# over VB. there are minor differences between the languages. and if you can read c# syntax you can read just about any OOP language.
3. learn the asp.net Framework. this is a framework, not a programming language. I'm amazed how many people get confused about this.

now the asp.net has a concept of a page life cycle. you need to understand this to create effect web applications using the webforms postback model. this page life cycle is unlike any other web framework.

the web is stateless so each request is atonomous to itself. (where as the desktop enviornment can manage state).
if you just start to drag/drop controls without an understanding of the tools then you will eventually get a webpage up and running, but you will also pick up many bad habits that will become hard to break.

At some point in your reading I would recommend the following books
Head First Design Patterns (java, but concepts are language egnostic)
CLR via C# (C#)
Domain Driven Design (language egnostic)

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
I'm truly sorry if I sound snippy, but all my months of work just went into the dumper.

Thanks Jason but I don't have time to relearn.
It was a C# book that got me in trouble in the first place.
It said to save the data this way.
BTW, it was C# for Dummy's. LOL

I think like an application programmer. I can't help that. I've been doing apps for almost 25 years and web is a way different animal.

I understand stateless because I wrote a few sites in classic asp but now I can use classes and be right at home again. At least I thought so.
If the classes go away with each post back then what good are they?
How can I persist the data between postbacks?

I've read a lot on ViewState and have saved a few things but I understand it's not an option for large amounts of data.

An xml config file is out. It needs to be located in memory I'd assume.

Again, really sorry for the 'tude. Can you point me to an article that might help?
This app was due a while back. Thanks so much.

 
I meant the bad things that can happen while using Session state. :)
 
but all my months of work just went into the dumper
that would set any developer off:)
your not being snippy, your realistic. I can understand if there's little time to research as someone always wants a new feature yesterday.

back to your original question about shared (public?) properties.

if you new up an instance of the class in each response you won't have any problems.
Foo foo = new Foo();
string bar = foo.Bar;

if these values are constant readonly values. you can create a singleton with the values.
public class Foo
{
private Foo() {}
public string Bar {get {return "bar";}};
public static readonly Foo Instance = new Foo();
}

if you use and IoC register Foo into the container and resolve the object when necessary.

now if your object is mutable where values can change. then instantiating the object and storing values become more (but not much more) complex. you would need to maintain the state of this object. maintianing this state depends on the scope of the object.

for instance if the values are specific to the user/client then the values are within the scope of a specific session (although it doesn't need to specificly know about session).
if the value is specific to the request, then just instaniate, set state then let GC take over when the request is complete.
if the object is globally specific then it's scope is at the application level.

since your coming from the desktop world, think if it like this. you have your domain and services which tie into the GUI. at the GUI level you are working with objects.

with the web you are working with strings at the GUI level, not objects. so if you need the customer a entity for a given request, get the ID from the request (request, form, control, querystring, etc) and fetch the customer from where they are stored. then modify the customer and send the customer back to stroage.

not sure if this is more or less helpful than my last post.

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
Not sure if your fimilar with the MVP or MVC patterns. if not this may get confusing.

My style of app architecture is to push as much of the respsonsibilty of the system into the core/domain. that said the code contained within an asp.net project is very minimal. a given Page object would also inherit a related view's interface with properties of simple data types (int, date, string) or DTOs. I pass these objects to the presenter/controler and this object interacts with the core. usally through a service fascade. the fascade is where all the "real" work of the system is done. creating/loading entities, conducting business process of some kind, storing data.

I try to keep my web project to only formatting, web requests, and ajax type stuff. this way things like session, statelessness, and postbacks don't clutter my domain.

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
Hi Jason.

Ok I think I understand your approach.
The class is a generic data access layer and used for pulling database information and giving it to the middle tier.

The next class is my middle tier and this is the one I'm having trouble with. It needs to hold the user info and other variables for the duration of the page.

Specifically, the class in question feeds a custom reporting page, which has a view control. The page contains 4 views and works like a wizard to walk the user through creating a custom report from the database.

View 1 saves the report name and description, also creates a datatable. Actually it sends the info back to the middle tier class that creates the datatable.

View 2 presents a list of fields from the database to the user which it retrieved from the middle tier. The middle tier used the generic database class to send it the info.

View 3 displays the report and gives the user access to a save button to save the report or export it to Excel.

After it's saved and the user leaves the screen, the class can be distroyed and GC can have it.

I'm using 2 classes for the middle and database tiers.
If I instantiate it each time, I'll loose the data saved in its properties, and also the datatable.

I thought an explanation was in order so you could see my thinking.

I thought about having the class save the variables in the ViewState or the Session.

Also started reading this:

I don't want to give up on web but I understood exe's way better. My data was mine. :)
 
I don't want to give up on web but I understood exe's way better. My data was mine.
i'm just the opposite:) i understand webforms better than desktop envoirnments, at the moment anyway.

there are a couple ways to handel this.
the most OOP approach is to have a service store the values in a repository between requests.

Code:
interface IRepository<T>
{
   T GetEntity(string key)
   void Remove(string key)
   void Save(string key, T Entity)
}

public class SessionRepository
{
   private HttpContext context = HttpContext.Current;
   public T GetEntity(string key)
   {
       if(context.Session[key] == null)
           return default(T);
       return (T)context.Session[key];
   }
   public void Remove(string key)
   {
       if(context.Session[key] == null)
           return;
       context.Session.Remove(key);
   }
   public void Save(string key, T entity)
   {
      context.Session[key] = entity;
   }
}

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
Thank you so much.
Sorry to take up so much of your time.
I really mean that. I'm always grateful for a point in the right direction.

Also nice to know someone that understands this stuff. :)

I'll spend some time researching this and see how it works.

I was just reading something early this morning on Session vs Viewstate.
I learned Viewstate transmits two times per page cycle and Session saves like a memory variable. Seems right to me.

I also can see how ViewState can bloat the page, since I can see this large block of text it brings with it.

Sessions do time out I see, but if so then my page would be no good to the user by that time.

So this is yet another piece of the .net puzzle that gos into my bag with "don't use drag and drop controls" At least not the database ones. :p

Thanks again for all your help. It's appreciated.




 
no problem. I'm glad this helps.

the session timeout should be an issue in this context, because session timeout is similar to loggin out. (very lossely similar).

viewstate is the hack M$ created to provide state to the stateless. This can get out of control quickly with enumerated data like gridviews and repeaters.

you are able to disable viewstate at a contorl/page/application level, but in doing so changes how you push/pull data with webforms.

As much as I hate viewstate and postbacks, I'm still utilizing (depending) on this for development. I focus on the domain core and slap on a gui. fortunately my end users prefer simple guis over complex options. but I digress.

viewstate and postback is unique to asp.net, no other language has it. if you become dependent on it, understanding other web frameworks/languages becomes very difficult.

I didn't read the entire atricle from fowler but I saw the title was IoC. there are 2 great frameworks for this in the .net world. Windsor and Structure.Map both are OSS and very active. Since discovering them I can't think of building without them.

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
I found something really interesting. This works great. I think I may go for it but it's magic.


The reason I say this is he creates a class. Ok, no prob.
Then a Global class, no problem.

Then assigns a value to the property THRU the class that is read only.

I see no place he saves the information to the Session!!!
(Magic) LOL

It's Friday and almost the end of the day so my brain is fried, reading posts of ViewState vs Session.

And I got hung up on <T>. Would not convert and I'm still researching it.
 
<T> is the generic so you implement you would do MyObject foo = SessionRepository<MyObject>.Get("foo");

this is simlilar to the code I provided. the difference is my solution above would work for any object you want insession. what the post provided would require you to alter the "global" class each time you wanted to add new objects to session.

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
That converts to:
Dim foo As MyObject = SessionRepository(Of MyObject).[Get]("foo")

Some of the other code does not convert well. I need to figure it out then rewrite it from scratch. We're a vb shop here.
I've never had to write an interface. Ever. I'd love an environment where I had other developers on the same project.
 
Ok I think I have it. with just a bit of reading on Interfaces, I solved it.

VB:
Code:
Public Interface IRepository
  Function GetEntity(ByVal key As String) As Object
  Sub Remove(ByVal key As String)
  Sub Save(ByVal key As String, ByVal Entity As Object)
End Interface


Public Class SessionRepository

  Implements IRepository

  Private context As HttpContext = HttpContext.Current

  Public Function GetEntity(ByVal key As String) As Object Implements IRepository.GetEntity
    If context.Session(key) Is Nothing Then
      Return Nothing
    End If
    Return DirectCast(context.Session(key), Object)
  End Function

  Public Sub Remove(ByVal key As String) Implements IRepository.Remove
    If context.Session(key) Is Nothing Then
      Return
    End If
    context.Session.Remove(key)
  End Sub

  Public Sub Save(ByVal key As String, ByVal entity As Object) Implements IRepository.Save
    context.Session(key) = entity
  End Sub

End Class
 
looking at my code above, it's missing the most important piece:
Code:
public class SessionRepository[COLOR=blue]<T> : IRepository<T>[/color]
{
   private HttpContext context = HttpContext.Current;
   public T GetEntity(string key)
   {
       if(context.Session[key] == null)
           return default(T);
       return (T)context.Session[key];
   }
   public void Remove(string key)
   {
       if(context.Session[key] == null)
           return;
       context.Session.Remove(key);
   }
   public void Save(string key, T entity)
   {
      context.Session[key] = entity;
   }
}

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
Ah yes! On my end it's the Implementspart.

So how would you use this?

It still wants me to enter a key name when I load and save the variables, or objects.

If I have a class that accepts a variable (a) then I'd write:

dim myClass as class1 = new class1
myClass.a = "Gary"

Then your part:

Dim rep as Repository = New SessionRepository
rep.Save("mykey", myClass)

This is correct?


Sorry I don't write C# as well as vb but I'm learning it as a second language.
 
I would have a service and provide this in the ctor
Code:
public class MyService : IService
{
   private readonly IRepository<Foo> repository;
   private const KEY = "Key for foo";

   public class MyService(IRepository<Foo> repository)
   {
       this.repository = repository
   }

   public void SaveAFooToRepository()
   {
      repository.Save(KEY, new Foo());
   }

   public Foo GetFooFromRepository()
   {
      return repository(KEY);
   }
}
for my projects I use Windsor to wire my objects together. I would provide windsor with the types MyService and SessionRepository<T>. Windors would know to wire SessionRepository<T> to MyService. StructureMap can do the same thing.

another option is to use an overloaded ctor
Code:
public class MyService()
   : this(new SessionRepository<Foo>())
{
}

public class MyService(IRepository<Foo> repository)
{
   this.repository = repository
}

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
As an update to this old post, I did complete the project. I didn't save the dataset and I used the ViewState for the few pieces of data that I needed to save.
A side note though. Having data marked as Shared allows 2 or more users access to the same data. Not sure when this will come up but I'm betting I can use this in the future.

Oh and thanks Jason, for the help.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top