Asked by:
Issue firing Server side method when browser closes via X button

Question
-
User2037455357 posted
Hello there I have the following method with a [Webmethod] attribute and a button to fire the method
[WebMethod] public static bool AbandonSession() { using (SqlConnection DBconnection = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["DBConnectionString"].ToString())) { DBconnection.Open(); String LogDesc = "Application has been terminated"; SqlCommand InsertLog = new SqlCommand("[dbo].[NewLog]", DBconnection); InsertLog.CommandType = System.Data.CommandType.StoredProcedure; InsertLog.Parameters.Add("@UserID", System.Data.SqlDbType.Int); InsertLog.Parameters["@UserID"].Value = Convert.ToInt32("1"); //InsertLog.Parameters.Add("@UserID", System.Data.SqlDbType.Int); //InsertLog.Parameters["@UserID"].Value = Convert.ToInt32(Cache.Get("UserID")); InsertLog.Parameters.Add("@MachineName", System.Data.SqlDbType.NVarChar); InsertLog.Parameters["@MachineName"].Value = System.Environment.MachineName.ToString(); InsertLog.Parameters.Add("@Webpage", System.Data.SqlDbType.NVarChar); InsertLog.Parameters["@Webpage"].Value = HttpContext.Current.Request.Url.AbsoluteUri.ToString(); InsertLog.Parameters.Add("@Description", System.Data.SqlDbType.NVarChar); InsertLog.Parameters["@Description"].Value = LogDesc.ToString(); InsertLog.ExecuteReader(); DBconnection.Close(); HttpContext.Current.Session.Abandon(); return true; } } protected void Button1_Click(object sender, EventArgs e) { AbandonSession(); }
Below is my aspx code with a script function to fire the button with the method.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Global.aspx.cs" Inherits="TestDropdowns.Global1" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <script type="text/javascript"> //<![CDATA[ function HandleClose() { alert("Killing the session on the server from Global.aspx!!"); document.getElementById('Button1').click(); //PageMethods.AbandonSession(); } </script> <title></title> </head> <body onbeforeunload="HandleClose()"> <%--onbeforeunload="HandleClose()"--%> <form id="form1" runat="server"> <div> <asp:scriptmanager id="ScriptManager1" runat="server" enablepagemethods="true" /> </div> <asp:Button ID="Button1" runat="server" Text="CreateLog" Height="24px" OnClick="Button1_Click" /> </form> </body> </html>
This works fine. but if I can the script to the following
<script type="text/javascript"> //<![CDATA[ function HandleClose() { alert("Killing the session on the server from Global.aspx!!"); //document.getElementById('Button1').click(); PageMethods.AbandonSession(); } </script>
The AbandonSession() does not fire,
Could some point me in the right direction of what I'm doing wrong please. I just want to fire off the method on server side when the browser is closed unexpectedly or via the X button.
Regards Rob
Sunday, July 7, 2019 7:47 PM
All replies
-
User753101303 posted
Hi,
Try https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon or a sync Ajax call.
The issue is likely that your async PageMethods is not even firred before the document is unloaded.
I believe it should be window.onbeforeunload (else it's the document rather than the window)
IMO sometimes this kind of little enhancement is counter productive. If a user opened a new tab, you'll close the session as well while a window is still opened.Monday, July 8, 2019 7:40 AM -
User-719153870 posted
Hi masterdineen,
Are you sure that your first method is feasible, because as far as I know, the alert method has been ignored in the onbeforeunload event in HTML5. You can see this at here.
Generally, we use return ("xxx") to display the prompt information.
You can try using the following code to invoke the background method:
Notice: Please make sure your AbandonSession method is workable.
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <script src="Scripts/jquery-3.3.1.min.js"></script> <script type="text/javascript"> //<![CDATA[ function HandleClose() { //alert('Killing the session on the server from Global.aspx!!'); PageMethods.AbandonSession(OnSuccess);//put pageMethods before return //document.getElementById('Button1').click(); return ("Killing the session on the server from Global.aspx!!"); } function OnSuccess() { } </script> <title></title> </head> <body onbeforeunload="return HandleClose()"> <%--onbeforeunload="HandleClose()"--%> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true" /> <asp:Button ID="Button1" runat="server" Text="CreateLog" Height="24px" OnClick="Button1_Click" /> </div> </form> </body> </html>
Best Regard,
Yang Shen
Monday, July 8, 2019 7:59 AM -
User2037455357 posted
Hello Yang
Thank you for your reply and suggestion, sorry its taken me so long to get back ive been on holiday.
I have changed my code to the following but the method is not firing, I have a button to fire off my method and that works ok so I know the method is ok.
The HandleClose function is not being called as I don't even get the "Killing the session on the server from Global.aspx!!" message.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Global.aspx.cs" Inherits="TestDropdowns.Global1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<script type="text/javascript">
//<![CDATA[
function HandleClose() {
//document.getElementById('Button1').click();
PageMethods.AbandonSession();
//return ("Killing the session on the server from Global.aspx!!");
}
window.onbeforeunload = HandleClose();{
return ("Killing the session on the server from Global.aspx!!");
}
</script>
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:scriptmanager id="ScriptManager1" runat="server" enablepagemethods="true" />
</div>
<asp:Button ID="Button1" runat="server" Text="CreateLog" Height="24px" OnClick="Button1_Click" />
</form>
</body>
</html>
Sunday, July 28, 2019 9:09 PM -
User475983607 posted
Session is lost once the browser is closed.
Server memory is cleaned up when the user's Session times out on the server. The Global.asax has a Session_End event where you can execute code in response to a Session timeout.
Basically, you need to rethink the design based on how ASP.NET and Browsers work.
Monday, July 29, 2019 6:07 PM -
User2037455357 posted
Hi, I have taken a different approach but I am still not getting anywhere
see code below.
aspx code below
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Global.aspx.cs" Inherits="TestDropdowns.Global1" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <script type="text/javascript"> window.onbeforeunload = function test() { $.ajax( { type: "POST", url: "Global.asax/AbandonSession", contentType: "application/json; charset=utf-8", success: function (msg) { return "Message from server."; } }); } </script> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:scriptmanager id="ScriptManager1" runat="server" enablepagemethods="true" /> </div> <asp:Button ID="Button1" runat="server" Text="CreateLog" Height="24px" OnClick="Button1_Click" /> </form> </body> </html>
AbandonSession() function C# code below
[WebMethod] public static bool AbandonSession() { SqlConnection DBconnection = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["Risk_AssessmentConnectionString"].ToString()); String LogDesc = "Application has been terminated"; SqlCommand InsertLog = new SqlCommand("[dbo].NewLog]", DBconnection); DBconnection.Open(); InsertLog.CommandType = System.Data.CommandType.StoredProcedure; //InsertLog.Parameters.Add("@UserID", System.Data.SqlDbType.Int); //InsertLog.Parameters["@UserID"].Value = Index.UserID; InsertLog.Parameters.Add("1", System.Data.SqlDbType.Int); InsertLog.Parameters["@UserID"].Value = Index.UserID; InsertLog.Parameters.Add("@MachineName", System.Data.SqlDbType.NVarChar); InsertLog.Parameters["@MachineName"].Value = System.Environment.MachineName.ToString(); InsertLog.Parameters.Add("@Webpage", System.Data.SqlDbType.NVarChar); InsertLog.Parameters["@Webpage"].Value = HttpContext.Current.Request.Url.AbsoluteUri.ToString(); InsertLog.Parameters.Add("@Description", System.Data.SqlDbType.NVarChar); InsertLog.Parameters["@Description"].Value = LogDesc.ToString(); InsertLog.ExecuteReader(); DBconnection.Close(); HttpContext.Current.Session.Abandon(); return true; } void Application_Start(object sender, EventArgs e) { // Code that runs on application startup RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); }
When I run my app I get the following error
Line: 15
Error: '$' is undefinedcould someone help please
Tuesday, July 30, 2019 9:20 PM -
User-719153870 posted
Hi masterdineen,
Line: 15
Error: '$' is undefinedThis error is because you used jQuerry but didn't refer to jquery.js.
Please add your local jquery reference or an online one.
For exacmple:
<head runat="server"> <title></title> <script src="Scripts/jquery-3.3.1.min.js"></script><%--This is my local jquery.js--%> <%--<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>--%><%--This is jquery online reference--%> </head>
Best Regard,
Yang Shen
Wednesday, July 31, 2019 7:45 AM -
User475983607 posted
Hi, I have taken a different approach but I am still not getting anywhereModern browser do not send AJAX request when the browser is closing. Doing so can cause the browser to stay open waiting for a response which is not user friendly.
As stated above, Session is lost when the user closes the browser. Move your code to the Session_End in the Global.asax. The Session_End event, for InProc Session, fires when the Session times out on the server.
Wednesday, July 31, 2019 10:57 AM