views:

120

answers:

4

Hello

I've the following doubt. I've a page "MyPage" and i've declared few dictionary objects in the page class.

My doubt is

  1. If i declare the dictionary as a private non-static object i'm not able to use it across the functions in that page class (the object is getting nulled)
  2. But if i declare the dictionary to be static i'm able to across the object across the functions. But will that object be same across all the users who have opened the page right now (guessing that each user will have an instance of the page in turn has an instance for the page class and static variables of a class are invariable across all the instances of the class)

Is my understanding right? How to declare the object to be available across all the functions within the page class and unique for each instance of the page (user).

Update1

Okie, i find that the initialization of the dictionary object in the page class is done in a different thread (WCF Duplex callback). But in the main page thread the dictionary object is still remaining as null (uninitialized). Any ideas?

Update2

Marshalling - useful by any chance?

Update3

In reply to John-

Thanks for your reply. The problem i'm facing now is to pass the data from the WCF callback class at the client side(which will be invoked in a separate thread) to the asp.net page. So how can i do that? View state may help me to persist the data across requests. But when the callback is invoked by the server notifying for a change how should i pass the changes (data) to the UI thread (asp.net page)?

A: 

you are right that a static member will be the same for all instances of the page, and thus all individual users. You need to make it a non-static member if you want to access it from every method in the class. You should look into why the object is null. Are you properly instantiating it at the proper time?

matt-dot-net
I'm passing the values of the dictionaries from another class (which is invoked asynchronously - WCF duplex callback) to a static method in the page class and raise an event to handle the values and insert into the dictionary object. I do an asynchronous postback every second using a timer and update the page.
NLV
the static method cannot operate on instance members, so you should change the static method to a non-static instance method.
matt-dot-net
I'm just raising a custom event in the static method. The event calls non-static delegates/methods to do the initialization and assignment of values. Any ideas?
NLV
But the initialization is done in a different thread (asynhcronously). Is that a problem?
NLV
The reason you are seeing a null is because you are not initializing the member in the current *instance* not thread. Static members/methods are the same for any thread.
matt-dot-net
Ya i know that. Do you have any solution for that? I think if i describe the message with my real time requirement (where i use WCF) it will be more understandable.
NLV
Okie, anything with marshalling?
NLV
+1  A: 

You are right in the second case. In your first case I'm guessing you mean that if a user clicks multiple controls on your page then the event handlers are seeing that the dictionary is null (instead of having the result from the previous event handler).

Remember that every request on a page (even from the same user) creates a new instance of your page class. That means that each time a request starts, your dictionary will be null. The only way for a variable to maintain its value between subsequent requests is to persist it server-side (for example, in user-specific session information on the server) or to push it to the client with the page content so that it can be part of the subsequent request data (so it's stored in ViewState or other storage at the client's browser between requests).

Dan Puzey
Can i do anything with the 'fancy' marshalling?
NLV
+1  A: 

Rereading this question, there are three seperate state machines, and none of them are being coupled together - hence the problem :)

  • State of the "user state" - these are the key/value pairs in the dictionary, their lifetime spans multiple page requests and callbacks

  • State of a "page", which needs to consume the data from "user state". Pages are destroyed after each and every page request.

  • State of the "service call" which needs to populate the data in "user state" Service calls are generally destroyed after each invocation.

There are a few strategies that could enable you to couple the systems:

  • ViewState such that the state machine for "user state" is sent down as part of the state of the page, and sent back on postbacks. This may constrain how you perform service callbacks

  • Session such that the state machine for "user state" is stored server side, and can be accessed by key.

  • Static dictionary of user states, where the key for the outer dictionary would be the identity of the "user state", where the 1st page request would create the "user state" entry, and you'd need to manage teardown. (v.similar to session - though works without ASP.NET).

There are lots of nuances to each solution - I'd advise light reading :)

stephbu
Can i do anything with the 'fancy' marshalling?
NLV
Marshalling won't help here, the lifetimes of page and service call instances don't overlap. That's why you need an external instance with a longer lifespan to then persist the service data until a new page instance is created.
stephbu
+1  A: 

Don't do things like this.

If you need to maintain data between pages, use Session state. That's what it's for. You should remember that you get a new instance of your page class on every request. Do not use statics to keep changing data around for subsequent requests. You will probably get into trouble with multiple requests updating the data at the same time.


You can't do things like this with ASP.NET!

You seem to be treating this as though it were a desktop program - as though your class instance and all state will still be there for you next time you execute a method on the page. That's not true - when the request is complete, your page will be Disposed. Nothing about the page will remain valid.

In particular, if the callback doesn't happen before the request ends, then the callback method had better not reference anything having to do with the request, like your page. That's because the callback might fire after the request is already over! The state is corrupt or worse.

Unless you are going to have the page wait for the callback, you'd really better not use them in your pages. Instead, create a separate Windows Service or something and have it issue the requests and await the callback. The page can then use Ajax or something to ask if the request is complete, and to get the response once complete.


If you think you heard me say to call back to an ASP.NET page, then you misunderstood.

Create a Windows Service. Your Windows Service will host a WCF service that the ASP.NET application will talk to. The WCF Service will keep track of things like who's joined a chat, who's typing, etc.

The web application cannot be notified when something interesting happens. Instead, the web application will have to poll the WCF service, asking if anything interesting has happened. When something happens, the WCF service will pass the "something" back to the ASP.NET application (or possibly, back to the page, called by AJAX).

I misspoke earlier. You simply cannot use a callback contract at all in this situation. It's not like the web pages are like a desktop application, one per user, waiting to be notified. They're more like a desktop application where, when the user makes a request, you take his PC and give him a new one just like it, before the response arrives.

John Saunders
Thanks for your reply John. Please see my edited post (update3).
NLV
Since using callback contract a server can invoke a particular client 'anytime' i dono when the callback comes to the client. Should i infinitely wait for the callback from the server? Sure the callback can be fired after the page request completes. Previously i had the dictionaries to be static and i made asyn postbacks to read from the dic (but it causes problems as you have noted earlier). But i'm looking for a design pattern or a common 'place' where the callback thread can put in and page can take from that.
NLV
@NLV: you're looking for the wrong thing. None of this should take place in the page. Create a WCF service. Host it in a Windows Service so you can take advantage of fast protocols. Have the page call the service to ask for the operation that requires the callback. The callback will call back to the Windows Service. The page can poll periodically to see how the operation is progressing. When it find the operation is complete, it gets results from the Windows Service.
John Saunders
Sorry, i'm finding it hard to connect the dots. Lets take a chat app for example. I created service 'S' with service contract 'SC' and callback contract 'CC'. Created a asp.net web application ChatAPP (client). Implemented CC in the web application for callback. User A joins the chat by calling Join() in the service contract. Then, User B joins the chat. Service S calls NewUserJoined() of User A to tell User B joined. What i don't understand in your answer is "page can poll periodically to see how the operation is progressing". Dont we lose the main purpose of the duplex channel here?
NLV
@NLV: The problem isn't the channel - the problem is that you want the channel to talk to something that will disappear as soon as the request is over.
John Saunders
Okie. So i need to check with the service (do an async postback) constantly for new updates, right? I started at this point, chose WCF duplex, and i'm back to the same point. I was thinking that a constant postback at a regular interval is a overhead.
NLV
It's an unavoidable small overhead. You can just do an AJAX post, sending nothing but some token that comes back from the service when the request starts. Only when there is "something interesting" would any significant amount of data flow.
John Saunders