Where to place server code to invoke when client page closes.

R

Ricardo Vazquez

Hi!

I have a new problem with this SCENARIO I already described in a previous
post:
- PBX (a private telephone exchange or switch)
- A Telephony Server Application running on computer "A" (it communicates
with the PBX via IP)
- An ASP.NET application (running on computer "A") for web clients of that
telephony server (running on computer "B", "C", etc.)

PROBLEM: When the web client closes the page (or the browser) ASP.NET should
invoke a method of the Telephony Server (DisconnectClient). This is very
important. If not, ghost clients would be living forever in the memory of
the Telephony server.
It doesn't mind if the method is invoked several minutes after closing the
browser (15 or 20 minutes as a maximum); but it has to be invoked.

I ALREADY HAVE TRIED...
to invoke it at "Session_End" in Global.asax. But at this point of the code
the Telephony-server proxy object is already "null".
Then I thought: If the object is null, code has to step through the
destructor and/or the Dispose method of it: but it doesn't.
Then I thought: I could try the "OnDispose" event of an important graphic
asp.net component of the page: Never called, either.
The "OnUnload" event: This one is called too frequently, maybe because of an
ajax timer I use in the page...
Client-side "onunload": but it has no access to server-side objects...
And, well, I have run out of ideas!

Could you please tell me where should I place this code?

Thank you very much!

Ricardo.
 
M

Mark Rae

I ALREADY HAVE TRIED...
to invoke it at "Session_End" in Global.asax. But at this point of the
code the Telephony-server proxy object is already "null".

Why is is null? Are you setting it to null somewhere? Is the GC destroying
it because it's fallen out of sope?
PROBLEM: When the web client closes the page (or the browser) ASP.NET
should invoke a method of the Telephony Server (DisconnectClient). This is
very

How does the DisconnectClient method know which client to disconnect? Do you
pass it some sort of argument? Does each client object have some sort of
unique identifier property?

I have encountered a similar problem with a login audit table where the
Session_End needed to record the time that the logged-on user logged out. If
the user didn't log out "cleanly" i.e. by clicking the "Log out" button,
then all sorts of problems occurred when the session ended.

The solution was quite simple: when the user logged in, I persisted a unique
identifier representing the login object which I stored as a Session
variable, then amended the Session_End method to use that instead when the
session was torn down, either manually by the user logging out cleanly or by
the session timing out automatically.
 
R

Ricardo Vazquez

Thank you very much for your interest, Mark!
Here I answer your questions:
Why is is null? Are you setting it to null somewhere? Is the GC destroying
it because it's fallen out of sope?

The object is called "app", and here it is its creation (this is the only
point where "new Aplicacion" is called):

protected void btnEnter_Click(object sender, EventArgs e)
{
...
if (app == null)
{
app = new Aplicacion(Request.UserHostAddress,
Server.MapPath("App_Data"));
Session["app"] = app;
}
...
}

As you see, I make it a persistent Session object.
I do not set it to null anywhere.

Whereever I need it I call something like this:

Aplicacion app = Session["app"] as Aplicacion;
if (app == null)
{
return;
}

But the "if (app == null)" condition is false everywhere but in
"Session_End".

Aplicacion implements the IDisposable interface, but the "Dispose" method is
never called (I also try the Disconnect I need here):
public void Dispose()
{
if (g_cti != null && g_cti.Conectado)
{
string sClientId = ClientIdentifier;
g_cti.DisconnectClient(ref sClientId);
}
}
How does the DisconnectClient method know which client to disconnect? Do
you pass it some sort of argument? Does each client object have some sort
of unique identifier property?

Yes. One of the Properties of "app" (instance of class Aplicacion for a
webclient) is "ClientIdentifier".

I have encountered a similar problem with a login audit table where the
Session_End needed to record the time that the logged-on user logged out.
If the user didn't log out "cleanly" i.e. by clicking the "Log out"
button, then all sorts of problems occurred when the session ended.

The solution was quite simple: when the user logged in, I persisted a
unique identifier representing the login object which I stored as a
Session variable, then amended the Session_End method to use that instead
when the session was torn down, either manually by the user logging out
cleanly or by the session timing out automatically.

When Session_End is fired, this is the code that runs:

Aplicacion app = Session["app"] as Aplicacion;
if (app != null)
{
if (app.g_cti != null && app.g_cti.Conectado)
{
string sClientId = app.ClientIdentifier;
app.g_cti.DisconnectClient(ref sClientId);
}
}

Which I think is quite similar to your solution, isn't it?
But, as I said, here app is null, so I never get this working... :-(


Any ideas on what may be happening?


Thank you very much,

Ricardo.
 
M

Mark Rae

The object is called "app", and here it is its creation (this is the only
point where "new Aplicacion" is called):

I'm presuming that 'Aplicacion' is a custom class, and not the Spanish
language way of referring to the 'Application' object...?
As you see, I make it a persistent Session object.

Hmm - I'm not entirely sure that you do...
I do not set it to null anywhere.

Maybe not, but something clearly does...If you're not explicitly disposing
it, then I can only assume that the GC is disposing it for you because it
has fallen out of scope - that's why I don't think you're are persisting it
in the Session object in the way that you think you are...
Whereever I need it I call something like this:

Aplicacion app = Session["app"] as Aplicacion;
if (app == null)
{
return;
}

But the "if (app == null)" condition is false everywhere but in
"Session_End".

Hmm - OK - so the app object is available everywhere in your app APART from
in Session_End...? Is this the same if you tear down the session manually,
or if the session times out automatically...?
Aplicacion implements the IDisposable interface, but the "Dispose" method
is never called (I also try the Disconnect I need here):
public void Dispose()
{
if (g_cti != null && g_cti.Conectado)
{
string sClientId = ClientIdentifier;
g_cti.DisconnectClient(ref sClientId);
}
}

Are you absolutely sure it's never called...? Have you set a breakpoint at
the top of the method...?
But, as I said, here app is null, so I never get this working... :-(
Any ideas on what may be happening?

Well, something somewhere is clearly disposing your app object - can you set
a watch on it and step through (F11, not F10) your web application until the
object is disposed...? This could be a bit of a chore, but I can't really
think of any other way at the moment...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,234
Latest member
SkyeWeems

Latest Threads

Top