There is a subtle difference in the default ASP.NET 2.0 ASPX files for VB and C#. I mention the difference only because C# is traditionally the ‘explicit’ language while VB.NET is the language with late binding features built-in.
A new VB.NET web form places AutoEventWireup=”false” in it’s @ Page directive. This means your code is responsible for explicitly wiring up Page events.
A new C# web form places AutoEventWireup=”true” in it’s @Page directive. This means the runtime will reflect upon your code to find method names in the form of Page_EventName and attach the methods as event handlers for named event.
Why is this?
VB.NET’s Handles keyword allows you to catch an event in a declarative manner. There is no comparable feature in C#. It’s a nice feature to have.
Here is something nice that comes from the new compilation model in ASP.NET 2.0. Let’s say you add a custom property to a master page code-behind file like so:
Partial Class otcMaster Inherits System.Web.UI.MasterPage Public Property FooterText() As String Get Return Footer.Text End Get Set(ByVal value As String) Footer.Text = value End Set End Property End Class
You can get to the master page for a web form using the inherited Master property, which returns a MasterPage reference. To get to a property defined in otcMasterPage though, you might think you need to use a cast.
CType(Master, otcMaster).FooterText ="foo"
Casting to a derived type is just a part of life when using frameworks and statically typed languages, but there is a better way. Use the @ MasterType directive in the ASPX.
<%@ MasterType VirtualPath="~/otc.master" %>
Now when ASP.NET codegens the page, it puts the following inside a partial class definition. Notice the Shadows keyword (that would be the new keyword in semicolon land [yeah, I’m experimenting with alternative languages]).
Public Shadows ReadOnly Property Master() As otc Get Return CType(MyBase.Master,otcMaster) End Get End Property
The result is a strongly typed Master Page. We don’t need a cast, we can go right to the Master.FooterText property. Another way to do this is to specify a TypeName in the @MasterType directive.
This weekend I’m playing in the pit orchestra for a community theater production of Sondheim’s Tony winner “Into The Woods”. The musical is a funny blend of fairy tales into a story of love, lust, and death by angry giant. I enjoy the music and storytelling in this show. My only criticism is the blatant use of a deus ex machina near the end.
Some of my favorite quotes:
Cinderella: Opportunity is not a lengthy visitor.
Cinderella’s prince: I was raised to be charming, not sincere.
Rapunzel’s prince: Dwarves are very upsetting.
Jack’s Mother: Children can be very queer about their animals.
Witch: I'm not good, I'm not nice, I'm just right.
I'm the Witch.
You're the world.
I should have grown up to be a researcher. Easy money – no stress.
Take this for example: someone made money doing a survey that discovers the vast majority of men at a nude beach don’t object to seeing nude females.
Well, duh.
As a follow up, the survey team will find out if the majority of people in a steak house restaurant object to seeing medium rare prime rib.
Here is another interesting study: IQ Dips More on Email Than Pot. The study claims that distractions from emails and instant messages make people
brb
Where was I?
Oh, right.
I was wondering how one could measure a change in IQ during periods of high-tech intrusiveness. IQ isn’t like blood pressure, as far as I know – but then I see a lot of email, so maybe I’m getting dumb. Who cares? Let’s chat!
Even if your research doesn’t pan out – just make something up. There is good money in fake numbers.
I’d like to start publishing my own research white papers. I’ve decided to start analyzing raw data at my disposal – like the log files for OdeToCode. Here is a break down of RSS readers hitting the site since July 1.
Name | % of hits |
SharpReader | 38.1% |
RssBandit | 23.6% |
NewsGator | 17.2% |
OmeaReader | 10.4% |
RssReader | 5.6% |
FeedDemon | 3.0% |
Others | < 3% |
Based upon these statistics, I’ve concluded that .NET is the only viable platform for building a popular RSS feed reader. I plan to publish these findings alongside some glossy pie charts and sell them to analysts in need of market research.
Who wants to invest?
Here are areas to watch when moving an ASP.NET app from Windows 2000 / XP ( IIS 5.x) to Windows Server 2003 (IIS 6.0). These notes assume you do not configure IIS 6.0 to use IIS 5.0 isolation mode.
In IIS 6.0, the worker process is w3wp.exe. The process runs under the NETWORK SERVICE account. The NETWORK SERVICE account has access to the machine credentials for outbound connections, and will appear to a remote machine as [DomainName]\[ComputerName]$.
What this means.
When granting permissions to local resources, make sure to pick the correct account. On Windows 2003, the .NET installation will still create the ASPNET account event though the worker process runs as NETWORK SERVICE by default. If you need access to remote resources, like when making a trusted connection to a database, you can grant access to the web server’s machine account if the worker process runs as NETWORK SERVICE.
Under IIS 5.0, the <processModel> section in machine.config controls many of the settings for the worker process (aspnet_wp.exe). Under IIS 6.0, only the following <processModel> settings are used: maxWorkerThreads, maxIoThreads, and responseDeadlockInterval. All other settings, such as idleTimeout are now configured using the IIS 6.0 metabase.
What this means
Except for the three settings above, use the Application Pool settings in the IIS management console to adjust settings for the worker process. This includes changing the identity for the worker process. You’ll need to right click and select the Properties option for the Application Pool your code runs in. You can find out which pool to use by inspecting the “Application settings” under the directory properties tab where your application lives.
Most non-critical services are off by default in Server 2003. If you see 404 errors requesting ASPX forms, or the forms display server side markup instead of dynamic content, you need to enable ASP.NET.
What this means.
Use Manage Your Server to enable ASP.NET.
The default <processModel> setting for the idleTimeout property is Infinite. Once the application has been inactive for an idleTimeout amount of time, the worker process will shut down (never, if idleTimeout is infinite). Remember though, on IIS 6.0 the metabase overrides the <processModel> settings, and the default timeout is 20 minutes. If applications in the pool receive no requests for 20 minutes, the worker process terminates. In-process Session state and Cache are emptied, and connections are closed.
What this means.If a worker process has to start from scratch, there is quite a bit of work to do. The cache will be empty, the connection pool will be empty, and your web application code needs JIT compiled. All the work means you could see a sluggish response to the one request that starts the application running again. If you have a dedicated server for your application, consider disabling the idle timeout. Also note: if you’ve configured session timeout to be longer than the idle process timeout, then sessions will appear to timeout prematurely.
When I saw Adam Barr’s “Monad and RSS” posts (Part I, II, III), I thought of something I’ve wanted to have recently: a utility to parse through my OPML file and tell me what feeds were dead or not updated for months.
Monad is the up and coming command line shell in Windows. Adam’s samples made XML in Monad look easy, so I thought I could bang out a quick script…
… then I discovered the pain of umpteen different syndication formats, each with their own quirky implementations. I am now amazed there are any working feed readers in existence. Why does simple stuff always get so difficult?
Still, I have something that works “okish”. The script tells me about dead and deserted feeds. There are some quirks. For instance, Ted Neward’s <pubDate> element refuses to parse into a DateTime in Monad. I blame it on the JSP extension in Ted’s URL.
The exception handling took some getting used to – but is great to have in script. On the other hand, I kept turning things into strings when I didn’t want strings. I stumbled into the right format to use for namespace-qualified elements, but I do like the way it works. I didn’t want to throw XmlNamespaceManager mumbo jumbo into script.
I’d like to see someone who actually knows Monad take the script and turn it into one of those 5 line masterpieces full of pipe symbols and regular expressions.
$opmldoc = [xml]$(get-content $args[0])
$webclient = new-object System.Net.WebClient
$cutoff = [DateTime]::get_Now().AddDays(-30)
foreach($feed in $opmldoc.opml.body.outline)
{
$date = $null
$doc = $null
trap [System.Net.WebException]
{
write-host "Web error fetching feed for " $feed.title
write-host " Error: " $_.Exception.Status
continue
}
trap [System.Exception]
{
write-host "Choked on: " $feed.title
continue
}
#because of goofy leading chars in msdn feed
$raw = $webclient.DownloadString($feed.xmlUrl)
if($raw -ne $null)
{
$doc = [xml]$raw.SubString($raw.IndexOf("<"))
}
#see if this is rss
if($doc.rss -ne $null)
{
if($doc.rss.channel.item[0].pubDate -ne $null)
{
# uses <pubDate>
# sort items by date and pick the most recent
$date = [DateTime](
$doc.rss.channel.item |
sort-object @{ e = { [DateTime]$_.pubDate }; asc=$false}
)[0].pubDate
}
if($doc.rss.channel.item[0].{dc:date} -ne $null)
{
# uses <dc:date>
$date = [DateTime](
$doc.rss.channel.item |
sort-object @{ e = { [DateTime]$_.{dc:date} }; asc=$false}
)[0].{dc:date}
}
# if we still don't have a date, try <lastBuildDate>
if($date -eq $null)
{
$date = [DateTime]$doc.rss.channel.lastBuildDate
}
}
# check for RDF
elseif($doc.{rdf:RDF} -ne $null)
{
$date = [DateTime](
$doc.{rdf:RDF}.item |
sort-object @{ e = { [DateTime]$_.{dc:date} }; asc=$false}
)[0].{dc:date}
}
# check for ATOM
elseif($doc.feed -ne $null)
{
$date = [DateTime](
$doc.feed.entry |
sort-object @{ e = { [DateTime]$_.issued }; asc=$false}
)[0].issued
}
if($date -eq $null)
{
write-host "Did not parse date from " $feed.title
}
elseif($date -lt $cutoff)
{
write-host "Stale feed alert!! : " $feed.title
}
}
If you derive your web form code-behind pages from a base class to manipulate common controls, your code won’t be happy with beta 2. For instance, deriving a web form from the following class will result in a null reference exception in AppBasePage_Load (commonLabel is null).
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
public class AppBasePage : Page
{
protected override void OnInit(EventArgs e)
{
this.Load += new EventHandler(AppBasePage_Load);
}
void AppBasePage_Load(object sender, EventArgs e)
{
commonLabel.Text = "Hello World";
}
protected Label commonLabel;
}
In 1.x ASP.NET would wire up commonLabel to a server-side control with the same ID. In 2.0 ASP.NET will code-gen a partial class with a commonLabel declaration that hides the base class declaration. The base class object's commonLabel reference will remain null.
According to ScottGu’s “Compatibility Testing” post, this problem should be fixed by the migration wizard in RTM bits. Hopefully the fix will be in a CTP soon - I'm curious to see if there will be an elegant solution.