Wednesday, June 06, 2007

Tech Ed Day 3 Part 1 - Hidden Gems in ASP.Net 2.0

I have so so many notes on the first session today I thought I'd put it in its own entry. That session was Hidden Gems in ASP.NET 2.0, a packed rundown of many features that should really be documented better.

For instance, we all know that you can use Ajax technologies to post back sections of pages, so you don't have screens flickering and the like. ASP.NET 2.0 has support for callbacks right out the box, without having to use any Ajax specific stuff. It's a lot simpler to do with Ajax, and Ajax is more flexible, but if you only need to update a few strings or something then ASP.NET 2.0 can do it. There are some samples you can download for all of these examples.

A feature that I didn't know about was the new $ syntax for ASPX code. This allows you to specify your own prefixes through custom expression builders. I won't go into detail on this as the MSDN article above covers it better than I could here.

And then there's encrypting your Web.config file to keep hackers away from sensitive information such as SQL connection string. You don't have to worry about doing this yourself, ASP.NET can do it for you.

"Why would you bother doing this?" I hear you ask, "IIS won't serve a .config file to the browser!" Well, no it won't. But through administrative errors it's common for this to happen.

Say you or a network admin needs to make a change to the Web.config. How common is it for that person to make a backup of the existing one before changing it? And what if that person copies the file to the same directory, but just renames the file to something like Web.config.bak, or Web.config.old? Will IIS still keep it hidden for you? No, IIS will push that file down to the browser just like it was a regular file.

Hackers will try every permutation of Web.config backup names once they've found out you've got ASP.NET running on the server. You can remove the risk of these admin errors by encrypting your sensitive sections of the file.

You can use the aspnet_regiis.exe utility with a /pef switch (for Protect Encrypt File) and specify the Web.config file to encrypt, or you can do it programatically with SectionInformation.ProtectSection.

Have you heard about Adapters in ASP.NET? No? Me neither.

These latch onto controls and intercept the markup that they are sending back to the browser. The intention of this originally was to allow developers to plug in a WML adapter to a normal ASP.NET web app to allow WML rather than HTML to be sent to the browser for mobile applications. Unfortunately this adapter never made it into the final release, but the architecture for doing it is still there and is accessible to developers to provide their own adapters.

Apparently there is a CSS Control Adapter Toolkit which just takes the form of an adapter that just changes the markup generated to be "more CSS friendly". I'm not sure what this means as I've not spent that much time with CSS, but maybe Neil will be able to shed some light on what the CSS problems are currently and why this new adapter is needed.

ViewState getting too big to push to the browser? Want to store ViewState in session state? The current way I know to do this is to override methods in the Page for loading and saving ViewState. An easier way is to use adapters.

That's all you need. Maybe Neil would like to take a look at that one too ;)

And now Virtual Path Providers. You know how ASP.NET 2.0 web applications can be built in a way that you don't need to have the ASPX files on the server--they're included in the binary. Do you know how they do that? More importantly, can I extend it to store my ASPX pages somewhere else?

With Virtual Path Providers you can. All registered Virtual Path Providers will be interrogated on every request to the application. Here you can intercept the path being requested and feed something else to the browser.

So lets say you wanted to read all the pages from a database, or maybe they're all encrypted. Derive a class from VirtualPathProvider and override the FileExists and GetFile methods. There are similar methods for directory requests too.

In the FileExists method check the path being requested and return true if you can handle that, or return Previous.FileExists if not.

Remember what I say about "all registered Virtual Path Providers"? Well just because your provider can't handle that file doesn't mean that another can't, so let someone else play if you don't want to. That's what Previous does, it's a property on the base class you're inheriting from.

Same goes for the GetFile method, do your processing to get the file (look into a database, or decrypt a file or something) and return a VirtualFile object that contains it.

So, now you can have dynamic pages loaded from a database but still have nice looking URLs instead of putting things in the query string.

To tell the web app about the provider though is a little different. Because the provider needs to be loaded prior to the entire Web.config file being loaded you have to declare the provider in a static method that the application can reflect into when the app starts.

Just provide a static method in your application called AppInitialize that includes the line HostingEnvironment.RegisterVirtualPathProvider, and your provider is registered.

And moving swiftly onto Session State Partitioning. As web farms grow in size, the database feeding the session state becomes the bottleneck for performance in the application. ASP.NET allows you to spread this load across a number of databases relatively simply.

Create a class that implements the IPartitionResolver interface, providing an implementation for the ResolvePartition method. Use this method to decide which session state database you want to use and return the connection string from it. Then in the Web.config file, where you would normally enter the connection string parameter in the SessionState element, intead put a reference to the class you've just created in the partitionResolverType attribute.

Now, how this handles the scenario of one server starting the session with a connection to 1 database, and another server finishing it with a connection to another wasn't made that clear, but I'm sure there must be a way around that.

As an example of web farm sizes that require this, it was said that MSDN ran on 4000 servers, and Hotmail on 1000. So larger than most web farms will be, but if the session database is proving to be a bottleneck in your system, then partitioning in this way is a possible solution for you.

The final part of this session (didn't I say it was packed?) touched on asynchronous pages. There is a glass ceiling on ASP.NET web apps that dictates how many requests it can feed at a given moment, and that is the maximum size of the ThreadPool. If threads are hanging around waiting for lengthy operations to complete, then that's one less thread that can respond to incoming requests.

As your application reaches this limit you'll see slowdown. If it passes this limit you'll see 500 errors, as the server will not respond to the request. You can get around this by using asynchronous pages.

Now, the session overran at this point, so an already fast paced session went into overdrive, and I'm afraid I didn't catch all the details, and there was no time for questions at the end. However, there is a session on Friday I think that covers just this section in detail, so I'll try to get to that.

Anyway, what it involves is splitting your processing into an asynchronous programming model, where you begin processing, do that processing on another thread, and then end processing by calling back. I assume that these new threads are taken out of a different pool though, as if they weren't it wouldn't give you an improvement at all.

Like I said, I'll try to get to the in depth Friday session for more information.


DreamBig said...

sir, i am a software developer from Pune,India.
Can you please provide me an example regarding session state partioning?

Ian Dykes said...

Sorry, but that's all the Tech Ed session covered, I've not implemented it myself.

It looks like you've covered more than I have on your own blog.