'webform_postbackoptions is undefined' java script error and WebResource.axd

'webform_postbackoptions is undefined' java script error and WebResource.axd

Old forum URL: forums.lhotka.net/forums/t/4099.aspx


Bob Bedell posted on Saturday, December 29, 2007

CSLA version 1.53 implements two features that give rise the 'webform_postbackoptions is undefined' java script error when targeting .NET 2.0: validation controls and the Application_AcquireRequestState event implementation in Global.asax.

Here's the problem from http://jeffbergman.com/cs/blogs/csjeff/archive/2007/07/27/10.aspx

" The symptoms of the problem are postbacks not working on pages that have validator controls of some sort.  What is happening is that there is an  IHttpHandler, WebResource.axd, which appears to return the javascript that is used to do these postbacks when using a validator control.  However in most web applications we do some sort of processing in the various handlers in Global.asax.vb, such as Application_PreRequestHandlerExecute.  If these handlers try to access session they will generate an exception because there will be no session available for the request to WebResource.axd.  This is because this Handler does not implement the interface IRequireSessionState.  If an HttpHandler doesn't implement this interface then the asp.net runtime will not provide session for the request and the code in Global.asax.vb will blow up.  The solution is to place some code like the following into your Global.asax.vb, in the Applicatoin_PreRequestHandlerExecute and your Application_AcquireRequestState functions.

If (Not TypeOf HttpContext.Current.Handler Is IRequiresSessionState) Then
      'Do any code that does not require session
Else
    '  Perform any operations that require session.
End If

This code checks whether we should expect session for the handler processing the request.  If not don't do any session operations.  Another approach would be to just check if HttpContext.Current.Session is nothing or not in these functions."

I need a CSLA version 2.x style implementation of the Application_AcquireRequestState event written with version 1.53 objects (I think). Can it be done?

Here's version 1.53:

protected void Application_AcquireRequestState(Object sender, EventArgs e)
    {

        // string sessionID = Session.SessionID;
        // set the security principal to our BusinessPrincipal
        if (Session["CSLA-Principal"] != null)
        {
            System.Threading.Thread.CurrentPrincipal = (System.Security.Principal.IPrincipal)Session["CSLA-Principal"];
            HttpContext.Current.User = System.Threading.Thread.CurrentPrincipal;
        }
        else
        {
            if (System.Threading.Thread.CurrentPrincipal.Identity.IsAuthenticated)
            {
                System.Web.Security.FormsAuthentication.SignOut();
                Server.Transfer("Login.aspx");
            }
        }
    }

Here's version 2.1.4:

protected void Application_AcquireRequestState(
    object sender, EventArgs e)
  {
    if (Csla.ApplicationContext.AuthenticationType == "Windows")
      return;

    System.Security.Principal.IPrincipal principal;
    try
    {
      principal = (System.Security.Principal.IPrincipal)
        HttpContext.Current.Session["CslaPrincipal"];
    }
    catch
    {
      principal = null;
    }

    if (principal == null)
    {
      // didn't get a principal from Session, so
      // set it to an unauthenticted PTPrincipal
      ProjectTracker.Library.Security.PTPrincipal.Logout();
    }
    else
    {
      // use the principal from Session
      Csla.ApplicationContext.User = principal;
    }
  }

Can anybody rewrite the 2.1.4 code with 1.53 objects, if its possible?

This is the only piece of version 1.53 I can't get to cooperate with .NET 2.0, which means I can't use the validation controls on ProjectEdit.ascx or ResourceEdit.ascx.

Thanks,

Bob

JoeFallon1 replied on Saturday, December 29, 2007

Bob,

Thanks for the reference to the blog post. I knew that AcquireRequestState got called more than once in ASP.Net 2.0 but was never sure why. I guessed other Handlers were involved but was not sure which ones (I have 3rd party controls too) and I also did not make the leap that they did not implement IRequiresSessionState.

But I figured out that we had to wrap the calls to AcquireRequestState as shown above.

The code above is only trying to get the users CSLA Principal out of session so they do not need to log in again. The only thing that ApplicationContext.User is doing is testing to see if you are in a web or Windows environment first. If there is no principal in Session, Rocky calls .Logout which puts an unauthenticated CSLA principal on the thread (instead of a Generic Principal) so you can then go to a Log-in page and use the data portal. The data portal needs a principal of type CSLA not Generic.

Your code could look something like this:

protected void Application_AcquireRequestState(
    object sender, EventArgs e)
  {

if (HttpContext.Current.Session = null )
{
 
//do nothing
}
else
{
    // string sessionID = Session.SessionID;
        // set the security principal to our BusinessPrincipal
        if (Session["CSLA-Principal"] != null)
        {
            System.Threading.Thread.CurrentPrincipal = (System.Security.Principal.IPrincipal)Session["CSLA-Principal"];
            HttpContext.Current.User = System.Threading.Thread.CurrentPrincipal;
        }
        else
        {
            if (System.Threading.Thread.CurrentPrincipal.Identity.IsAuthenticated)
            {
                System.Web.Security.FormsAuthentication.SignOut();
                Server.Transfer("Login.aspx");
            }
            else
            {
               ProjectTracker.Library.Security.PTPrincipal.Logout();
              
System.Threading.Thread.CurrentPrincipal = (System.Security.Principal.IPrincipal)Session["CSLA-Principal"];
            HttpContext.Current.User = System.Threading.Thread.CurrentPrincipal;
            }
        }
    }

}


Joe

Bob Bedell replied on Saturday, December 29, 2007

Hi Joe,

Thanks for the reply. I'm starting to get a handle on the System.Security objects, finally.

Curious about:

else
{
    ProjectTracker.Library.Security.PTPrincipal.Logout();
    System.Threading.Thread.CurrentPrincipal = (System.Security.Principal.IPrincipal)Session["CSLA-Principal"];
    HttpContext.Current.User = System.Threading.Thread.CurrentPrincipal;
}

The Security namspace and the PTPrincipal object are version 2.1.4 features. Did you mean to include this line of code, or can it be deleted? I set about writing a User property and a Logout method for the version 1.53 BusinessPrinciple class and a UnauthenticatedIdentity method for the version 1.53 BusinessIdentity class to emulate the PTPrincipal.Logout method, then thought I better ask if these modifications need to be made.

The good news is, if I simply delete the line, the validation controls do work; the java script from WebResource.axd is served up correctly, and my problem is solved.

The bad news is, without the call to the PTPrincipal.User property, I'm not sure I'm really in the security context I think I'm in.

Don't knock yourself out over this or anything. It isn't that important. I'm starting to build version 2.1.4. I really just need to know if you intended for the line to be there or not. If it should be there, I'll need to make the necessary revisions to BusinessPrincipal and BusinessIdentity.

Thanks,

Bob

 

Bob Bedell replied on Saturday, December 29, 2007

After playing around a bit, my hunch is that it doesn't need to be there, does it?

We want to assign a CSLA.Security.BusinessPrincipal to the user in the current context.

if
{
    A CSLA.Security.BusinessPrincipal already exists in session...
    We assign it to the threads CurrentPrincipal...
    Then to the user in the current context.
}
else
{
    if
    {
        The threads CurrentPrincipal isn't authenticated (i.e., its a GenericPrincipal)...
        We redirect to the Login form.
    }
   else
   { 
       If the threads CurrentPrincipal is authenticated (i.e., its a CSLA.Security.BusinessPrincipal)...
       We assign the authenticated BusinessPrinciple to the threads CurrentPrinciple... 
       Then to the user in the current context.
    }
}

Thats all we need, isn't it?

Bob

 

JoeFallon1 replied on Saturday, December 29, 2007

Thta line of code was just a sample.

It was assumed you have your own Principal class with your own logout method which works in CSLA 1.x. That is where you would call it.

 

Also, you wrote:
The threads CurrentPrincipal isn't authenticated (i.e., its a GenericPrincipal)...

But the code reads *is* authenticated. In other words, if there happens to be an authencticated generic principal on your thread you want to replace it with a default CSLA prinicpal.

Joe


 

Bob Bedell replied on Saturday, December 29, 2007

I see. Thanks again Joe.

JPrakash replied on Friday, November 14, 2008

Hi,

Thanks Joe, your help have saved my time for the same problem

'webform_postbackoptions is undefined'

after i had migrated a ASP.NET 1.1 web app project to 2.0.

As you said i have changed my code as follows and now no more error in my 2.0 app.

in my Global.asax.vb

Protected Sub Application_PreRequestHandlerExecute(ByVal sender As Object, ByVal e As EventArgs) 

  If IsNothing(HttpContext.Current.Session) Then
            'do nothing
  Else ' do the session object access code

 End If

 

Regards,

Prakash

Copyright (c) Marimer LLC