Tuesday, November 28, 2006

The Case of the Overzealous Profile

Asp.NET 2.0 ships with a wonderful feature called "Profile", which is essentially a server-side replacement for cookies, most commonly used for persisting user settings. The advantage of the server-side solution being of course that you're not dependant anymore on users actually supporting cookies and/or deciding to delete them in a sudden fit of paranoia. ***

Another nice thing about the Profile is that it follows the Provider model and ships with a pre-working SQL Server implementation.

In a recent ASP.NET application, we made some extensive use of the Profile in our searchscreens, however since we were working on an Oracle database, we had to create our own custom Provider. This is however absolutely no problem since DotNet makes it really easy to do so, and to plug your resulting custom provider into your application without any hassle.

However, we did notice a performance degradation upon use of the Profile, and we occasionally even got Oracle errors, when the application received a lot of strain. When we finally found some time to investigate the issue, we discovered that the SetPropertyValue method of the Provider was being called on each and every visit to the page and this for every available property in our Profile, resulting in at least 15-20 extra database calls per page access. Needless to say, this did not help performance one bit.

After digging around some more, it turned out that the Profile mechanism has in fact an auto-load and auto-save mechanism built-in. In other words:
  • at the start of the page cycle, all properties get read from the data store
  • at the end of the page cycle, all properties get persisted to the data store

Fortunately, there was also an option to turn this automatic save off, this by a simple modification of the web.config.



< profile automaticSaveEnabled="false">

Not quite as well-documented as I'd hoped though...


*** Note that the Profile can however be enabled for anonymous usage, in this case you will need cookies again for this to work. :)

Monday, November 27, 2006

How to take Control... of your controls

When creating custom ASP.NET controls, there's the question of which baseclass to use for your control.
Generally speaking, you have three big categories:

  • Rendered Controls
  • Container Controls
  • Inherited Controls

Of those choices, inherited controls are the simplest, in that they simply inherit from an existing control (custom or otherwise). An example would be inheriting from a DropDownList and adding some custom code to pre-populate it. Or a ConfirmButton control, which inherits from Button, and automatically renders a "are you sure?" javascript alert when you click it. Inherited Controls are to be used when you want all the functionality of a certain control, and then just "something" extra.

Rendered Controls are created by inheriting from the WebControl class. They operate by directly injecting HTML into the output stream. As such they bypass the normal event lifecycle for any of its containing subcontrols. The result is that a Rendered Control will render much faster than a Container Control, but does not support event postbacks 'out-of-the-box'. While it is possible to provide these events, by means of implementing IPostBackEventHandler and IPostBackDataHandler, and then providing custom code to handle these events, this does raise complexity a bit and tends to create quite cluttered code. It is advisable then, to only use Rendered Controls, for simple, mostly static controls.

Container Controls, as their name implies, function as containers or collections for other controls. They are implemented by inheriting from CompositeControl. Your subcontrols are dynamically added to the Control collection of your CompositeControl, and they will then go through their normal event lifecycle, allowing you to customise them as needed. While this functionality comes at a price (somewhat worse performance compared to Rendered Controls), it allows you to build your webcontrols in a true object-oriented fashion, and apply all your usual Design Patterns to them. It also makes it much easier to inherit from your own controls, and in doing so, create an reusable and extensible library of server controls.

The choice between those three types of controls is - as is usually the case - dependant on the requirements of your project, but generally speaking, Composite Controls will be your best friend the moment your controls become a bit more complex and require event interaction.

Tuesday, February 14, 2006

Sometimes it really is _that_ easy

Sharepoint has a Page Viewer webpart, allowing you to integrate external applications into your Portal. Very useful, but sometimes this presents problems of its own.

Case in point, one of our clients used this webpart to integrate his .NET web application in a WSS site, and had some trouble with his Session variables not showing up, when viewed through the webpart. Logical, if you think about it, because the site is being referenced through an Iframe of another site, so your cookies are not going to be accessible. Its not a bug, its a feature! In this case, a security feature, because how would you like it if any external site could just frame you (pun intended) and nose around in your cookies?

Faced with the prospect of having to rewrite his entire application without Session variables, the client's developer started considering jumping off the nearest bridge. That is, until I pointed out to him that he could simply switch the session state handling in his .NET application by modifying the web.config.


< sessionState mode="InProc" stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;user id=sa;password="
cookieless="true"
timeout="20"
/>


By setting the "cookieless" attribute to true, ASP.NET will automatically (and with no impact on the application!), switch from using cookies to track session ids to appending a session identifier to the Url. No fuss, no need to rewrite your application!

Problem solved, client happy. If only everything was so easy.

Tuesday, January 17, 2006

Alive

Yes, I'm still alive.

I'll post a proper update soon, but in the meantime, this might be a good read.

Tale of conversion from an ASP.NET 1.1 application to 2.0