This is a migrated thread and some comments may be shown as answers.

HttpModule and RadAjaxManager

1 Answer 130 Views
Ajax
This is a migrated thread and some comments may be shown as answers.
Ed
Top achievements
Rank 1
Ed asked on 17 Jun 2008, 09:58 PM
Hi - yet another HttpModule conflict issue.  Unfortunately I can't figure out what specifically in my HttpModule causes the problem.

Anyway, the issue is that I get the dreaded Javascript error messages if I use my own HttpModule.  Unfortunately, I need to use it because it implements (using a mechanism proven to work reliably even with these errors) the ability to detect if the user hit the page refresh button.  It is critical that this detection exists in my application because of other mechanisms we need to use.  Anyway, below if the full code of my HttpModule and related classes:

public class RefreshAction

{

// ***********************************************************

// Constants

public const string LastRefreshTicketEntry = "__LASTREFRESHTICKET";

public const string CurrentRefreshTicketEntry = "__CURRENTREFRESHTICKET";

public const string PageRefreshEntry = "IsPageRefresh";

// ***********************************************************

// ***********************************************************

// Manage to check if the F5 button has been pressed

public static void Check(HttpContext ctx)

{

// Initialize the ticket slot

EnsureRefreshTicket(ctx);

// Read the last ticket served in the session (from Session)

int lastTicket = GetLastRefreshTicket(ctx);

// Read the ticket of the current request (from a hidden field)

int thisTicket = GetCurrentRefreshTicket(ctx);

// Compare tickets

if (thisTicket > lastTicket ||

(thisTicket == lastTicket && thisTicket == 0))

{

UpdateLastRefreshTicket(ctx, thisTicket);

ctx.Items[PageRefreshEntry] =

false;

}

else

{

ctx.Items[PageRefreshEntry] =

true;

}

}

// ***********************************************************

// ***********************************************************

// Ensure that the slot for the last ticket served isn't null

private static void EnsureRefreshTicket(HttpContext ctx)

{

// Initialize the session slots for the page (Ticket) and the module (LastTicketServed)

if (ctx.Session[LastRefreshTicketEntry] == null)

ctx.Session[LastRefreshTicketEntry] = 0;

}

// ***********************************************************

// ***********************************************************

// Return the ticket of the last request in the session

private static int GetLastRefreshTicket(HttpContext ctx)

{

// Extract and return the last ticket

return Convert.ToInt32(ctx.Session[LastRefreshTicketEntry]);

}

// ***********************************************************

// ***********************************************************

// Return the ticket of the last request in the session

private static int GetCurrentRefreshTicket(HttpContext ctx)

{

return Convert.ToInt32(ctx.Request[CurrentRefreshTicketEntry]);

}

// ***********************************************************

// ***********************************************************

// Return the ticket of the last request in the session

private static void UpdateLastRefreshTicket(HttpContext ctx, int ticket)

{

ctx.Session[LastRefreshTicketEntry] = ticket;

}

// ***********************************************************

}

public class RefreshModule : IHttpModule

{

// ***********************************************************

// IHttpModule::Init

public void Init(HttpApplication app)

{

// Register for pipeline events

app.AcquireRequestState +=

new EventHandler(this.OnAcquireRequestState);

}

// ***********************************************************

// ***********************************************************

// IHttpModule::Dispose

public void Dispose()

{

}

// ***********************************************************

 

// ***********************************************************

// Determine if a F5 or back/fwd action is in course

private void OnAcquireRequestState(object sender, EventArgs e)

{

// Get access to the HTTP context

HttpApplication app = (HttpApplication)sender;

HttpContext ctx = app.Context;

// Check F5 action

RefreshAction.Check(ctx);

return;

}

// ***********************************************************

}

This is then used by a custom Page class that my app inherits from that allows me to check if this is a page refresh or not.  The relevant methods from my Page class are below:

// **************************************************************

// Indicates if the page is being viewed in response to F5 hit

public bool IsPageRefresh

{

get

{

object o = HttpContext.Current.Items[RefreshAction.PageRefreshEntry];

if (o == null)

return false;

return (bool)o;

}

}

// **************************************************************

// **************************************************************

// Increase the internal counter used to generate refresh tickets

public void TrackRefreshState()

{

InitRefreshState();

int ticket = Convert.ToInt32(Session[RefreshTicketCounter]) + 1;

Session[RefreshTicketCounter] = ticket;

}

// **************************************************************

 

#region

Private Members

// **************************************************************

// Create the hidden field to store the current request ticket

private void SaveRefreshState()

{

int ticket = Convert.ToInt32(Session[RefreshTicketCounter]) + 1;

RegisterHiddenField(

RefreshAction.CurrentRefreshTicketEntry, ticket.ToString());

}

// **************************************************************

// **************************************************************

// Ensure that the ticket counter is initialized

private void InitRefreshState()

{

if (Session[RefreshTicketCounter] == null)

Session[RefreshTicketCounter] = 0;

}

// **************************************************************

// **************************************************************

// Handle the PreRender event

private void RefreshPage_PreRender(object sender, EventArgs e)

{

SaveRefreshState();

}

// **************************************************************

 

If there is anything obvious in the above that would interfere with RadAjax, could you suggest how to avoid breaking it?  I do understand that I may be able to resolve the problem by having the application(s) reference the scripts and set UseEmbedded Scripts="False", but these HttpModule and Page classes are actually being used as our base classes on several applications.  It becomes somewhat less than ideal from a software release distribution standpoint if we have to modify our page markup to reference the right version path of the RadControls for several applications every time we upgrade to a new release of RadControls.  It also tends to make the applications know more about the underlying controls than I would prefer, since normally it wouldn;t be typical to have to add the script references on the pages using them.

Thanks,

-Ed


 

1 Answer, 1 is accepted

Sort by
0
Ed
Top achievements
Rank 1
answered on 18 Jun 2008, 02:28 PM
I found my own resolution.  When the page first loads and as each Ajax request fires, the AcquireRequestState event of the HttpModule gets fired once each time around.  However, when the Refresh button is hit, it first fires for the refreesh of the page, and then it fires once more for each reference in the page to WebResource.axd.  When these subsequent events get fired, the Context.Session is null.  As a result, I was actually throwing an exception that was manifesting as javascript errors.

I have no idea why the extra events fire only on refresh nor why there is no Session at that time, but the easy solution for me was to check for non-null Session.  (I could have checked fror WebResource.axd as the file requested, but that might have only covered one scenario, and clearly I can't be executing my code to check Session if it's null anyway.)

Hopefully this will help others too.

-Ed
Tags
Ajax
Asked by
Ed
Top achievements
Rank 1
Answers by
Ed
Top achievements
Rank 1
Share this question
or