Question

I am trying to work within a legacy application that uses framesets. I am trying to fire server side code from the page unload event. Here is some example code that demonstrates the problem.

Default.aspx:

<%@ Page Language="C#" AutoEventWireup="false" CodeBehind="Default.aspx.cs" Inherits="SimpleTest._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<frameset rows="20%,80%">
    <frame name="Frame2" src="Frame2.aspx">
        <frameset>
            <frame name="Frame1" src="Frame1.aspx">
    </frameset>
</frameset>
</html>

Frame2.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Frame2.aspx.cs" Inherits="SimpleTest.Frame2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
</head>
<body>
<form id="form1" runat="server">
    <div>
        <asp:Button ID="btnSecond" runat="server" Text="Button Second" onclick="btnSecond_Click" /> 
    </div>
</form>
<script type="text/javascript">
    if ('onbeforeunload' in window) {
        window.onbeforeunload = (function () { clearSessionData(); });
    } else {
        if ('onunload' in window) {
            window.onunload = (function () { clearSessionData(); });
        }
    }

    function clearSessionData() {
        alert("clearSessionData fired!");
        $.ajax({
            type: "POST",
            url: "Frame2.aspx/someFunction",
            success: function () { alert("SUCCESS"); },
            error: function () { alert("ERROR"); }
        });
    }
</script>
</body>
</html>

Frame2.aspx.cs:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace SimpleTest
{
    public partial class Frame2 : System.Web.UI.Page
    {
        protected void btnSecond_Click(object sender, EventArgs e)
        {
            int test = 1;
            test++;
        }

        protected void someFunction()
        {
            int test = 1;
            test++;
        }
    }
}

I did not include the code for Frame1.aspx because that page is empty, in this example.

If I run this testing code, the alert that says "clearSessionData fired!" runs, and the alert box is displayed. But, the next line does not fire the server function "someFunction".

I have also tried using $.post() instead of $.ajax() but, have had no luck with that either. Does anyone have experience with this? Is there some problem with trying to fire server-side code from framesets using jQuery? How would you accomplish this, using jQuery or any other method? I have tried several options but, nothing seems to fire the server side code.

Any suggestions would really be appreciated.

Thanks.

ADDED COMMENT:

As a side note, if I have a simple page, with no frames, I can put code in a button's server-side click event, then create a Javascript function that uses jQuery's "trigger" method to call the button's server-side click code without any problem. See this example code:

<body>
<form id="form1" runat="server">
<div>
    <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
</div>
</form>
<script type="text/javascript">
    if ('onbeforeunload' in window) {
        window.onbeforeunload = (function () { clearSessionData(); });
    } else {
        if ('onunload' in window) {
            window.onunload = (function () { clearSessionData(); });
        }
    }

    function clearSessionData() {
        $("#Button1").trigger("click");
    }
</script>

This works just fine, with the click event code firing when the browser is closed (and other events that fire unload). But, for whatever reason, using frames breaks all of this.

Was it helpful?

Solution

You need to turn someFunction (on the server) into a page method. Page methods can be called from client side code through AJAX calls.

Here is an article explaining such: http://encosia.com/using-jquery-to-directly-call-aspnet-ajax-page-methods/

Basically you decorate your method with the WebMethod and ScriptMethod attribute. Also, make it public:

[WebMethod, ScriptMethod]    
public static void someFunction()
{
    int test = 1;
    test++;
}

These will require using statements for System.Web.Services and System.Web.Script.Services.

UPDATE: I just saw your updated question saying you are using .NET 2.0. If you cannot use Page Methods, here is a workaround. First, create a Generic HttpHandler. I called mine KillSession.ashx. Note you also have to implement the marker interface IRequiresSessionState to be able to access the HttpSession.

KillSession.ashx.cs:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.SessionState;

namespace TestFrames
{
    /// <summary>
    /// Summary description for KillSession
    /// </summary>
    public class KillSession : IHttpHandler, IRequiresSessionState
    {

        public void ProcessRequest(HttpContext context)
        {
            if (context.Session != null)
            {
                context.Session.Clear();
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

In your Default.aspx (frame container) add a function called killSession. Notice it calls KillSession.ashx:

<%@ Page Language="C#" AutoEventWireup="false" CodeBehind="Default.aspx.cs" Inherits="SimpleTest._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
    <script>
        function killSession() {
            console.log("Killing Session");
            $.ajax({
                type: "POST",
                url: "KillSession.ashx",
                success: function () { alert("SUCCESS"); },
                error: function () { alert("ERROR"); }
            });
        }
    </script>
</head>
<frameset rows="20%,80%">
    <frame name="Frame2" src="Frame2.aspx">
        <frameset>
            <frame name="Frame1" src="Frame1.aspx">
    </frameset>
</frameset>
</html>

Then from your frames page (e.g. Frames2.aspx):

<script type="text/javascript">
    if ('onbeforeunload' in window) {
        window.onbeforeunload = (function () { clearSessionData(); });
    } else {
        if ('onunload' in window) {
            window.onunload = (function () { clearSessionData(); });
        }
    }

    function clearSessionData() {
        alert("clearSessionData fired!");
        if (typeof window.top.killSession === "function") {
            window.top.killSession();
        }
    }
</script>

This will call the top level frame (Default.aspx) killSession function whenever there is an unload event within the frame.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top