Development With A Dot

Blog on development in general, and specifically on .NET

Sponsors

News

My Friends

My Links

Permanent Posts

Portuguese Communities

January 2012 - Posts

Remove View State from UpdatePanel Call

You may not be aware that view state (and control state) is included on each UpdatePanel call, even if the controls placed inside it have it disabled. As view state can get quite large, it may be useful to disable posting it during UpdatePanel calls, as long as you know what you are doing!

Here’s one possible solution, using Microsoft’s AJAX Library to intercept the asynchronous call before it is actually sent to the server:

   1: function removeViewState(body)
   2: {
   3:     var builder = new Sys.StringBuilder();
   4:     var parts = body.split('&');
   5:  
   6:     for (var i = 0; i < parts.length; ++i)
   7:     {
   8:         if (parts[i].indexOf('__VIEWSTATE=') < 0)
   9:         {
  10:             builder.append(parts[i]);
  11:         }
  12:  
  13:         if (i != parts.length - 1)
  14:         {
  15:             builder.append('&');
  16:         }
  17:     }
  18:  
  19:     return (builder.toString());
  20: }
  21:  
  22: Sys.Net.WebRequestManager.add_invokingRequest
  23: (
  24:     function (s, e)
  25:     {
  26:         var webRequest = e.get_webRequest();
  27:         var body = webRequest.get_body();
  28:  
  29:         body = removeViewState(body);
  30:  
  31:         webRequest.set_body(body);
  32:     }
  33: );

As you can see, I iterate through all of the parameters being sent along with the request, and I skip the view state.

Hope this helps!

Twitter

Follow me at https://twitter.com/#!/RJPeres75

Posted: Jan 27 2012, 03:15 PM by Ricardo Peres | with no comments
Filed under:
Detecting Authentication Expiration in ASP.NET

I recently had to solve a problem: when issuing an asynchronous call by using an UpdatePanel, if the user is no longer authenticated – due possibly to long inactivity – this situation is silently ignored. What happens is, when an unauthenticated user tries to access a protected resource, ASP.NET redirects the request to the login page, and still returns a 302 HTTP status code (Found).

Here’s what I did: first, I hooked an event listener to the completedRequest event of the Sys.Net.WebRequestManager JavaScript object, part of Microsoft’s AJAX Library. This event fires whenever an asynchronous call, made typically by an UpdatePanel, terminates.

Inside it, I look at the response text, directly at the XMLHttpRequest instance. If it contains a text that I know only my login page contains (a comment inside <!-- -->, such as <!—this is the login page -->), then I know I am no longer authenticated, since my async requests are getting redirected.

All I can do at this point is give the user the option to authenticate again, by redirecting to the login page (yes, I know about application services, but that is not the point here).

So, here’s the code:

   1: Sys.Application.add_init
   2:     (
   3:         function ()
   4:         {
   5:             Sys.Net.WebRequestManager.add_completedRequest
   6:             (
   7:                 function (s, e)
   8:                 {
   9:                     if (s._xmlHttpRequest.responseText.indexOf('this is the login page') >= 0)
  10:                     {
  11:                         if (window.confirm('You are no longer authenticated. Do you wish to return to the login page?'))
  12:                         {   
  13:                             window.location.href = '/Login.aspx?ReturnURL=' + window.location.pathname;
  14:                         }
  15:                     }
  16:                 }
  17:             );
  18:         }
  19:     );

And that’s it. Just place this in your master page or on a control that goes on every page.

Querying an Uninitialized Collection with NHibernate

I have talked before about the problem of accessing an uninitialized collection and presented a solution that allows us to see if the collection contains elements on the DB, and how many there are, without actually loading them. Now I have a general purpose solution for querying the collection on the DB.

Here it is:

   1: public static IQueryable<T> Query<T>(this IEnumerable<T> collection)
   2: {
   3:     if (collection is AbstractPersistentCollection)
   4:     {
   5:         IPersistentCollection col = collection as IPersistentCollection;
   6:  
   7:         if (col.WasInitialized == false)
   8:         {
   9:             String role = col.Role;
  10:             Object owner = col.Owner;
  11:             Object key = col.Key;
  12:             ISessionImplementor sessionImpl = typeof(AbstractPersistentCollection).GetField("session", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(collection) as ISessionImplementor;
  13:             ISession session = sessionImpl as ISession;
  14:             ISessionFactory sessionFactory = session.SessionFactory;
  15:             String ownerEntityName = sessionImpl.BestGuessEntityName(owner);
  16:             Type ownerType = Type.GetType(ownerEntityName);
  17:             IClassMetadata metadata = sessionFactory.GetClassMetadata(ownerEntityName);
  18:             String idPropertyName = metadata.IdentifierPropertyName;
  19:             MethodInfo ownerIdGetMethod = ownerType.GetProperty(idPropertyName).GetGetMethod();
  20:             String childPropertyName = role.Split('.').Last();
  21:             MethodInfo ownerChildGetMethod = ownerType.GetProperty(childPropertyName).GetGetMethod();
  22:             Type childType = typeof(T);
  23:             ParameterExpression a = null;
  24:             IQueryable<T> details = typeof(Queryable).GetMethods(BindingFlags.Static | BindingFlags.Public).Where(x => x.Name == "SelectMany" && x.GetParameters().Length == 2).First().MakeGenericMethod(ownerType, childType).Invoke
  25:             (
  26:                 null,
  27:                 new Object[]
  28:                     {                    
  29:                         typeof(Queryable).GetMethods(BindingFlags.Static | BindingFlags.Public).Where(x => x.Name == "Where").First().MakeGenericMethod(ownerType).Invoke
  30:                         (
  31:                             null,
  32:                             new Object[]
  33:                             {
  34:                                 typeof(LinqExtensionMethods).GetMethods(BindingFlags.Static | BindingFlags.Public).Where(x => x.Name == "Query" && x.GetParameters()[0].ParameterType == typeof(ISession)).Single().MakeGenericMethod(ownerType).Invoke
  35:                                 (
  36:                                     null,
  37:                                     new Object [] { session }
  38:                                 ),
  39:                                 Expression.Lambda
  40:                                 (
  41:                                     typeof(Func<,>).MakeGenericType(ownerType, typeof(Boolean)),
  42:                                     Expression.Equal(Expression.Property(a = Expression.Parameter(ownerType, "x"), ownerIdGetMethod), Expression.Constant(key, ownerIdGetMethod.ReturnType)), new ParameterExpression[] { a }
  43:                                 )
  44:                             }
  45:                         ),
  46:                         Expression.Lambda
  47:                         (
  48:                             typeof(Func<,>).MakeGenericType(ownerType, typeof(IEnumerable<>).MakeGenericType(childType)),
  49:                             Expression.Property(a = Expression.Parameter(ownerType, "x"), ownerChildGetMethod), new ParameterExpression[] { a }
  50:                         )
  51:                     }
  52:             ) as IQueryable<T>;
  53:  
  54:             return (details);
  55:         }
  56:     }
  57:  
  58:     return (collection.AsQueryable());
  59: }

As you can see, I first check to see the collection is an NHibernate one, if not, I fall back to LINQ to Objects; also, if the collection is already initialized, I also use LINQ to Objects.

Hope this helps!

NHibernate Pitfalls: SQL Queries and Parameter Prefix

This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.

When you execute an SQL query with NHibernate with named parameters, you would perhaps expect them to be prefixed with a symbol specific to the current DB you are accessing, for example, @ for SQL Server and : for Oracle; that is not the case. NHibernate requires that you always use it’s DB-neutral parameter prefix, :, the same that you use for HQL queries:

   1: //for SQL queries
   2: session.CreateSQLQuery("SELECT * FROM [Order] WHERE Id = :id").SetParameter("id", 1).List();
   3: //for HQL queries
   4: session.CreateQuery("from Order where id = :id").SetParameter("id", 1).List();
More Posts