Skip Navigation Links
Search site. 
Powered by Google
Darren Neimke (Me)

My Book

Readify

">ASP.NET MVP


Interesting Portals 

NetVibes
This portal feels similar to PageFlakes in many ways but I love their gallery. They also have a feature whre certain chrome elements only become visible when you hover over the web part.

Xtra
A New Zealand news portal. I especially liked the content rotator web part at the top of the middle row. Seems like a nice way to allow a user to browse through data.

 

Posts Archive 

Posts for: Mar 2006

Those funky Live.com guys

The Live.com guys are a funky lot.  What, with all of that lovely AJAX and champagne swishing around the place why wouldn't they be funky.  But do they really understand community or are they simply using a f#$@king huge bag of cash and no requirements to stage the worlds largest internet party? 

The funky Live.com guys impress me with how they've managed to integrated the ASP.NET stuff with the stuff that MS Research built for them but they fail to convince me that they have any plan for community other than to create the biggest pile of HTML and Javascript on the internet. 

Here's my advice...

Hey funksters, when you host your pals at dinner and you ask them to email you with any feedback - make sure that you take the time to reply when they do email you. 

And when you have an uber-cool offering (Gadgets) that nobody really understands, make some sort of effort to help people understand them.  Case in point here is that while having 3 different sites that all point to the same outdated copy of "HOW TO" instructions you seem to have single-handedly failed to give any kudos to the hand that feeds you (the ASP.NET team's new Atlas portal with Gadget template was announced last week and yet you still have those outdated tutorials up that were written by some guy on the C++ team).

Close the champagne bottles, answer your emails, and get down and dirty with community and you'll do well!

posted on 3/31/2006 9:34:12 PM ( 0 Comments )


ReadiFridays

Wow, you miss all the cool news when you head overseas for a week.   I was running through Outlook this morning and noticed that we've announced ReadiFridays.  Mitch also blogged about this here.

ReadiFridays is a concept that we're really excited about because it will enable us to get out and talk to groups around the country about the really important new technologies in a way that allows plenty of interaction.  Derrick is kicking off with the first ReadiFriday which is about Real Time Collaboration and LCS.  Read the agenda for that here (you can also register to attend from this page):

    http://www.readify.net/Default.aspx?tabid=396

You can browse here to learn more about the ReadiFriday concept:

    http://www.readify.net/Default.aspx?tabid=392

For me the best part of ReadiFridays is that we get to talk about the new technologies that we are the most passionate about and I think that will make them different to anything that has come before.

posted on 3/30/2006 8:42:01 AM ( 0 Comments )


Vista Touchdown - Day 2

Today was really intense.  We finished off WPF by looking at Animation, 3D, Documents and Text formats, and also Interop.  My favorite two topics here were definitely the Text formats with the new font rendering - just wait until you see it - and the Metro document stuff.  The interop stuff was also very impressive and I'll be interested to see what kind of discussions come up around migration when we show this in Australia.  Basically you can host Win32 in WPF and you can host WPF in Win32.

Just prior to and immediately after lunch we looked at Peer-to-peer technologies and then InfoCard.  InfoCard is very, very exciting as it is built around open standards.  Imagine a federated identity system that uses open standards... Mmmmmmmmm!

The afternoon was spent in what I'd call WCF immersion.  We basically go through the architecture of WCF and then look at specific implementation patterns that use the technology and finish off by looking at some of the tooling that supports administration of WCF applications.

At the end of the day I was totally stuffed and so stayed at the hotel for a few beers - as opposed to going out to the local electronic gadget store.  Luckily for me Ian Griffiths was equally stuffed and so we were able to have dinner together.  Over dinner I stole more information from his brain but shared a few beers, a main course, and many interesting stories - ranging from languages, to blogging, to some wild speculation about where the next major branch of ASP.NET innovation might occur (discounting Atlas of course).

Anyways, tomorrow us WF, Deployment, and RSS.  Here's a couple of photo's from today.  One is a photo that I took during a break where a few of the guys were eating the interesting ice-creams that we were given and Ian seems to be happy for the opportunity to catch his breath. 

The second photo is a close-up of the ice-creams.  Notice the flavours: Sweet Corn, Red Bean, Yam, and Durian.  Believe me, they were actually very nice :-)

Well earned break
Well earned break!

 

Interesting Ice-Creams
Interesting Ice-Creams

posted on 3/29/2006 11:34:08 PM ( 0 Comments )


Vista Touchdown - Day 1

Well, I'm in my hotel at Singapore getting ready for Day 2 of the Vista Touchdown training event and thought that I'd better make some notes about what happened yesterday.

There are about 25 people in our group plus Ian Griffiths who is the teacher, and then Ed and Mary - the two Microsoft DPE guys from Redmond and Angela the Program manager from Asentus in Canada.

Yesterday we started off with a short presentation from Intel which walked us through the various chipsets and how they support the features that will be required for Vista.

After the Intel presentation we got straight into WUX (Windows User Experience) and went through the updated style guidelines for building great Vista applications.

Next up came Search and and we learned about the Search system and the Properties system and saw how to consume those services from within our own applications.

After lunch we went through the new User Account model and saw how the the new least privellage stuff in the Vista security model works.

After that we ran straight into pure presentation stuff.  A short session on how to develop Sidebar Gadgets and then 3 sessions of pure WPF content- WPF Overview and 2D, WPF Tools, WPC Databinding.  Now I can finally say that I've built some custom UI using Sparkle and written code against it in VS.NET!

Everybody was thoroughly rooted by the end of the day but we persisted on to dinner at a local Chinese restaurant where I managed to have my first ever dish of Jellyfish :-)  It was great to really get to spend time with people at dinner and there were lots of really funny jokes and stuff to keept he night entertaining.

Dinner finished at around 8:30 and we caught a bus to the Singapore zoo so that we could go to something that they call the "Night Safari".  The Singapore zoo is huge and we basically caught a train that they have there which ran us all around it to show us the animals.  The ride lasted for about 45 minutes.

Here's some photo's from dinner last night:

View from restaurant View from restaurant View from restaurant
This is the view from the restaurant.

 

Eating Jellyfish!
Eating Jellyfish!

 

At dinner
The guys on my table at dinner.

 

posted on 3/29/2006 9:55:18 AM ( 0 Comments )


High Intensity Warm-up Drill

This exercise will really get the intensity up early in the training session and can be run for anywhere between 10 and 15 minutes.

High Speed High Intensity Warm Up Drill

 

You have groups of players at each of the hats marked 'A' and 'B'.  The ball starts with the players on the 'A' hat and is passed alternately to the next player at the 'B' cone.  The emphasis of this drill is for the passing to be very firm and accurate and for the finishing shot to be direct and hard.

posted on 3/26/2006 2:47:27 PM ( 3 Comments )


Vista training in Singapore next week

I'm heading to Singapore on Monday to attend the Vista Touchdown Trainer Event.  Throughout the 4 days of training we cover Vista User Experience, WPF, InfoCard, WCF, and WWF.  After attending the course I will be a "go to" trainer for the Vista Touchdown program which will start in Australia around the middle of the year.  The Touchdown program will be run bu the DE team in Australia so keep an eye on Frank's blog for details.

One of the highlights of the Singapore training trip will be that I get to meet Ian Griffiths (who is the trainer for the week).  I've followed Ian's writing for a long time and it will be great to finally meet with him.

posted on 3/25/2006 10:07:20 AM ( 0 Comments )


The new Messenger UI?

I've been running the version 8 beta of Messenger for a while now but it seems to crash very regularly whenver I minimize the window - at which point you get one of these:

Do you really listen?

I must have sent about 30 error reports to Microsoft in the past 30 days but still I'm faced with this "dialog" (Is this what they mean when they say that they want to have a "conversation" with me?).

posted on 3/24/2006 8:05:59 AM ( 0 Comments )


Good, General Purpose Warm-up Exercise

This drill is a good way to start a training session because it get's people moving around a lot and brings the goal keeper into play on every run through.

Warmup Exercise

 

You have two group of players lined up on the hats labelled 'A' and they run either in a straight line or through hats, dribbling the ball into the circle.  When they enter the circle a firm pass is given to a player standing at 'B'.  The player receiving the ball initially pushes or flicks the ball at goal. 

Eventually, when the goal keeper is warmed-up, the receiving players start to take a firm shot at goal.

posted on 3/23/2006 8:08:17 PM ( 0 Comments )


Do you work with XML?

Here's a couple of tools that I wrote recently while doing a lot of work with XML.  The first tool is called XSLTTestHarness and it allows you to create XSLT's and view the output of a transform immediately.  Here is a screenshot of XSLTHarness:

XSLTTestHarness

[Grab the source code]


The next tool allows me to quickly validate XML against a schema by loading a schema and an XML file and pressing validate.  You are notified of any errors in the XML and you can correct the XML within the tool and re-submit it to re-validate it.  Here is a screenshot of SchemaValidator:

Schema Validator

[Grab the source code]

posted on 3/23/2006 9:21:27 AM ( 2 Comments )


Managing my tasks

Over the past month I've been using Outlook in a much more aggresive manner to manage the tasks that I do on a daily basis.  Since implementing this methodology my daily tasks have been solely driven from the Today screen in Outlook as the following image shows:

The Outlook Today page

Whenever an email arrives in my Inbox one of three things happens to it immediately after I've read it:

1) Delete it
2) Drag it into the Tasks folder
3) Drag it into the Calendar folder

This highlights the fact that all email is either purely informational - in which case you can delete it after consuming it or that it requires some form of action.  The emails that require action are either events (Calendar) or require action (Tasks).

When a task is overdue it is displayed in red font and so you should always update the date of red tasks.  It's as important to keep your task clean as it is to keep your email list clean.  If you added a task but didn't get it done, re-assign it to another date or delete it.

posted on 3/21/2006 4:05:06 PM ( 0 Comments )


Buggy XSD Behavior? Cannot convert type 'string[]' to 'string'.

Suppose that you wanted to craft some schema that would match to the following XML:

<MyNames>
  <Name>
    <Nickname>Bluey</Nickname>
    <Nickname>Red</Nickname>
    <Nickname>Chief</Nickname>
    <Nickname>Tiger</Nickname>
  </Name>
  <Name>
    <Nickname>Red</Nickname>
  </Name>
</MyNames>


This would do the trick:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="Test"
  targetNamespace="http://new.webservice.namespace"
  xmlns:my="http://new.webservice.namespace"
  elementFormDefault="qualified"
  xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:complexType name="NamesType">
    <xs:sequence maxOccurs="3">
      <xs:element name="Name" type="my:NameType" minOccurs="0" />
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="NameType">
    <xs:sequence>
      <xs:element name="Nickname" type="xs:string" maxOccurs="unbounded" />
    </xs:sequence>
  </xs:complexType>

  <xs:element name="MyNames" type="my:NamesType" />
</xs:schema>


However when you run that through XSD it creates the following class definition:

public partial class NamesType {
   
    private string[][] nameField;
   
    /// <remarks/>
    [System.Xml.Serialization.XmlArrayItemAttribute("Nickname", typeof(string), IsNullable=false)]
    public string[][] Name {
        get {
            return this.nameField;
        }
        set {
            this.nameField = value;
        }
    }
}


That's interesting.  A multi-dimensional array of strings names Name.  Not quite what I'd expect to see.  I would have expected that the NamesType class would have an array of complex types called NameType and that the NameType class would have an array of strings.

Anyways, I came across this behavior when I received an error by adding a Web Reference to a valid WSDL file that had been created in XML Spy.  The error occurs when you have operations on a WSDL file that return these types.  The operations deserialize correctly by returning an array of strings for the Nickname element whereas the generated types contain a string[][]. 

There's some documentation about this behavior here:

    http://support.microsoft.com/?scid=kb;en-us;891386&spid=1444&sid=5

posted on 3/21/2006 11:03:56 AM ( 0 Comments )


Daily Links

How many cool websites do you visit on any given day?  I'll bet that there must be some amazing sites and web pages that people visit on any given day that just go un-remembered and un-shared.  Not any more!  Today I added a new feature to my blog called "Daily Links" which allows me to arbitrarily add cool or interesting links via an administrative web part and have them appear on an RSS feed.  You can subscribe to the feed here:

    http://markitup.com/DailyLinksRss.ashx

This idea was originally an SUBV2 feature suggestion by Howard Van Rooijen as you can see in this comment:

    http://markitup.com/Posts/Post.aspx?postId=622ac040-d459-40dc-a66d-5478bbe2db8a#94085f1b-853d-4d1e-b1be-37f2ecc23448

I think that it would be great if this took off and we all started blogging our most interesting "visited links"; I think that this will turn up some real gems!

Thanks Howard :-)

posted on 3/20/2006 5:37:38 PM ( 5 Comments )


Follow-up on prescriptive guidance for instrumenting code

How many of the pages in your web application execute in over 1 second?  How many execute in over 3?  Do you know?  And for the pages that are taking longer than 3 seconds, what's the cause and how often does it occur?

Last week I posted an intro article on the topic of instrumenting code and discussed some of the issues as I see them.  The point of writing about this topic is that I want to arrive at some simple prescriptive guidance for when and how to use Health Monitoring and Instrumentation in applications.  In this post I want to mention some of things that should be monitored for health. 

Unlike standard tracing, the purpose of health monitoring is exactly that - to determine the health of code so that we can be proactive in fixing code before problems occur.  Here is a list of some of the things that are good candidates for Health Monitoring code:


Calls to External Systems
Whether it is a connection to a database or a web service call to an external site, you should monitor these activities and raise health alerts when the time to perform the action exceeds a certain limit.  For example, if you make a web service call as a part of the execution of a page you don't really want to get an alert for every call that is made and you don't want to wait until that connection starts timing out.  Instead you can write some health monitoring code that notifies you whenever the time that it takes to make the web service call rises beyond a certain limit - say 1 second.  Or you could write the code so that it was even smarter and informs you whenever the time that it takes to call that resource is "growing".

Here is a sample of code that raises a custom health event named ExternalCallWebEvent whenever the time to load an XmlDocument from an external resource exceeds a hard-coded limit of 2 seconds:


Stopwatch watch = new Stopwatch();
XmlDocument tmp = new XmlDocument();

watch.Start();
tmp.Load(this.OpmlPath);
watch.Stop();

#region Health Monitoring Code

if (watch.ElapsedMilliseconds >= 2000) {
    ExternalCallWebEvent e = new ExternalCallWebEvent(
        string.Format(
            "The call to {0} took {1} milliseconds to complete.",
            this.OpmlPath,
            watch.ElapsedMilliseconds
        ),
        this,
        WebEventCodes.WebExtendedBase + 1
        );

    e.Raise();

}

#endregion

return tmp.OuterXml;


Application Restarts

Another symptom of failing health is when your application see's a large number of application re-starts.  Aside from anything else, application restarts can indicate things such as thread pool starvation and also denial of service attacks.  Typically you will want to receive batched health alerts when your application has many restarts in a short space of time.  The following configuration entry will raise an alert that will be displayed in the Event Log whenever event 1001 (ApplicationStart) has 5 or more instances within a minute.


<healthMonitoring>
  <rules>
    <add name="Check For DOS"
         eventName="Application Start"
         provider="EventLogProvider"
         profile="Critical" minInstances="5"
         maxLimit="Infinite"
         minInterval="00:01:00" custom=""
         />
  </rules>
  <eventMappings>
    <add name="Application Start"
         type="System.Web.Management.WebApplicationLifetimeEvent,System.Web,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a"
         startEventCode="1001" endEventCode="1001" />
  </eventMappings>
</healthMonitoring>

 

Security Audit Warnings

Another thing to keep an eye out for are security warnings.  If someone enters a bad username/password attempt then that's no biggie, but get 10 of those in a minute and you can be sure that something's going on.  The following article provides some information about health monitoring the security of your application.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag2/html/paght000016.asp

posted on 3/20/2006 12:31:23 PM ( 0 Comments )


From this day forward...

Congratulations G and E!

Grant's wedding

posted on 3/18/2006 4:36:11 PM ( 2 Comments )


App_Offline.htm

A cool feature that has been added in ASP.NET 2.0 is the App_Offline.htm file.  Scott Guthrie blogged about it a while ago when he had this to say:

Basically, if you place a file with this name in the root of a web application directory, ASP.NET 2.0 will shut-down the application, unload the application domain from the server, and stop processing any new incoming requests for that application. ASP.NET will also then respond to all requests for dynamic pages in the application by sending back the content of the app_offline.htm file (for example: you might want to have a “site under construction” or “down for maintenance” message).

For my blog I have an HTML file named App_Offline.RENAMETO_htm that contains the page that I want people to see whenever I'm updating my website - such as when I'm uploading a new set of assemblies.  Before I start the FTP process of the new files I simply rename that file to App_Offline.htm.  Once the upload process has completed I then rename the file back to App_Offline.RENAMETO_htm.

The content that is displayed on my App_Offline.htm file basically tells the viewer about App_Offline.htm and explains that I'm probably updating my site right now :-)

posted on 3/18/2006 12:56:59 PM ( 4 Comments )


My Live.com "killer feature"

One of the killer features on the new Live.com web portal is that all of the web parts offer this great "Read More" feature.

Live.com Killer Feature


With this feature you can hover the mouse over the "[more]" link for an item and have the details of the item displayed in a pop-up panel.  In the case of blog posts or news articles you get the additional text and in the case of something like the Flickr web part you get a larger version of the image.

Very nice as it allows you to consume lots of information without ever having to leave the page.  I find that it also allows you to make pages much busier with links - such as by adding dozens of news web parts - and then simply scanning over them for interesting news titles and then hovering over those interesting titles to get the content.

posted on 3/16/2006 7:37:59 AM ( 0 Comments )


Hey Web 2.0 guy - ShowUsYour

Just like SOA before it, Web 2.0 can mean pretty much anything you "feel" it to mean.  For me it means: Simple, Commercial, and Shiny.

OK, if you are reading this there's a fair chance that you're a programmer right.  Then guess what, even though you say you "Get Web 2.0", you probably don't.  In fact there's loads of people who tell us that they "get" Web 2.0 - and probably about 40 or so who really do.

Lately I've seen new blogs and podcasts springing up all over the place espousing their passion and knowledge for Web 2.0.  Which is fine... kinda.  I guess that I think that there's probably more "feel" that "grok" in there.  In other words, when you hear people say:  "I really get Web 2.0", just keep in mind that what they probably mean is: "I really get a stiffy from Web 2.0".

If you doubt it, ask them to point you at their most successful Web 2.0 "commercial" ventures :-)

posted on 3/15/2006 10:37:03 PM ( 1 Comments )


New web parts and application fixes

Update: the new SUBV2 release is available here.

I've been running a new build of SUB for about a week now and things look pretty good so I'm planning to do a build and release it on ProjectDistributor later tonight.  This build has a bunch of performance fixes that should see your install go from "groggy" to "zippy" in one easy hit.

The other fixes in this build are:

  1. Implementing the Cache Pattern
  2. Url Mappings and Feedburner
  3. Making better use of the UrlFormatter in SUB

I've also included a new web part in this release:

Quote of the Day Web Part: Simply add a bunch of quotes to this web part and it will randomly display a new quote each day on your site. 

Here's a screenshot of the QOTD web part:

Quote of the Day Web Part

posted on 3/15/2006 9:07:22 PM ( 3 Comments )


Providing users with a self-service way of fixing broken pages

Chapter 9 is all about looking at various ways to manage a web portal an my favourite sample from that chapter is a feature that the ASP.NET team showed off at PDC in LA last year.  In that session Mike Harder, who is a Software Design Engineer on the ASP.NET team for the web parts feature, showed us how to create a page that displays all of the web parts for another page and then allows individual web parts to be deleted from the personalization data for that page.  To do this, we dynamically execute the target page "silently" and then handle the PreInit event off of it and then grab the web parts from the WebPartManager instance on the page. 

To dynamically execute another page and attach an event handler we use the following snippet of code:


Page page = (Page)BuildManager.CreateInstanceFromVirtualPath(path, typeof(Page));

WebPartCollection webParts = null;

page.PreLoad += delegate {
    webParts = WebPartManager.
        GetCurrentWebPartManager(page).WebParts;
    };

ExecutePage(page, path, context);


Here we instantiate a page dynamically by using CreateInstanceFromVirtualPath method of the BuildManager class.  This method takes the path of the ASP page that we wish to create an instance of and also a type argument which indicates what the base type for the page class is.

At this point you might be wondering why you would want to create a separate page to delete web parts.  Consider what would happen if you added a web part to your page and that web part had some logic error which caused it to throw an exception from within its RenderContents method.  The answer to this is that the web part would get added to the personalization data for the page and then that page would not be able to be displayed again - because of the exception that is thrown from the web part.  This means that you cannot access the page to remove that web part and fix the problem.  Now consider what would happen if that happened on the home page of a public internet site that you have just deployed!

Now I'm sure that you can see why it's important to provide a separate page so that we can recover from just such a case.


In our example, the helper method for executing the page looks is shown in the following snippet:

 

private static void ExecutePage(Page page, string path,
                                HttpContext context) {
    string originalPath = context.Request.Path;
    context.RewritePath(path);

    try {
        context.Server.Execute(page, TextWriter.Null, false);
    } catch {}

    context.RewritePath(originalPath);
}


You can see here that a null TextWriter is passed to the Execute method so that the page is not rendered anywhere.  Once the page is executed, our anonymous method in the first snippet will get invoked and the web parts will be popped-off into our local webParts variable.  This variable can then be bound to a GridView and displayed to the user.  When the user chooses which part they would like to remove we run through a similar set of steps to when we loaded the web parts initially only our anonymous method uses the DeleteWebPart method on the WebPartManager to remove that web part like so:


page.PreLoad += delegate {

    WebPartManager webPartManager =
        WebPartManager.GetCurrentWebPartManager(page);

    WebPart webPart = webPartManager.WebParts[ID];
    webPartManager.DeleteWebPart(webPart);
};


In the book I go into more depth and there's also a working example of how to hook this up as the standard handling mechanism for errors that occur in a portal application so that users are given an immediate self-service option for fixing their broken page.

Thanks Mike, now I know that I won't get a call from the boss at midnight asking me to fix his broken portal page!

posted on 3/13/2006 9:30:01 PM ( 0 Comments )


OK... so now that we're all mobile...

Answer me this: How will Ajax sites perform on my new JAMin mobile device?

 IMate JAMin

posted on 3/13/2006 8:42:56 PM ( 0 Comments )


Organizing my Live.com Home Portal Page

In my last blog post I mentioned that I've moved to having Live.com as my home portal and today I thought that I'd talk about how I can use the features of the Live.com portal to light up all areas of my browsing world.

The Live.com portal allows you to easily create new pages on the fly and each of these "pages" appears as a tab within the portal itself.  The idea behind this is that you create a page and then you can add web parts to that page to show you a specific set of information.  In my portal I have created the following pages:

  • Home
  • News and Sport
  • Blogs
  • My Custom Feeds

Here is a picture of the tabs being displayed in the Live.com portal page:

Live.com TabPages are nice

The Home page contains my Mail web part, a Flickr web part and also displays the weather and time information for a set of cities that I'm interested in.  For example, I often IM with the Development Editor on my web portal book and so it's useful to have her timezone and weather displayed while I'm chatting with her. 


The News and Sport page is a dump of news, finance, and sporting information from around the globe so that I can easily scan it to look for stories that might be of interest to me.

The Blogs page allows me to easily keep up to date with the latest feeds from a very small subset of Thought Leaders on topics that are relevant to me.  Currently I have Frank Arrigo's blog listed on this page so that I can keep abreast of the latest news from the Australian developer market.  I have Scoble's blog listed there so that I can keep up to date with the latest buzz and gossip that is relevant to the industry.  Finally I have the GadgetNews feed and the Live.com feed listed there so that I know when new Gadgets or Features are being added to the site.


The last page - "My Custom Feeds" - is similar to the blogs page but these feeds are based on custom search queries that I have created to alert me when new information about my projects appears on the web.  Currently I have two web parts on this page - one web part runs a search for information relating to BlogML while the other web part searches for information about SUBV2.


All-in-all I'm enjoying using the Live.com portal to light up my world and keep me in tune with the information that I need to be effective in my role.

posted on 3/13/2006 8:16:27 PM ( 13 Comments )


Managing Personalization Data with PersonalizationAdministration

I'm just finishing off Chapter 9 in my book which is a chapter on how to manage a web portal and in that chapter I take some time to look at the PersonalizationAdministration class to show what it has to offer.  The PersonaliztionAdministration class has static properties and methods that allow us to query personalization data.  For example, using this class you can run a query to view all stale personalization data - that is personalization data that has not been accessed for longer than a given time.  You can also run queries that allow you to view all personalization data for a given user or users.  Most of the queries return a PersonalizationStateInfoCollection which represents the personalization data that matches your query.  Here's an example of a query that is used to return all personalization data that is older than 200 days:


DateTime inactiveSince = DateTime.Now.AddDays(-200) ;

PersonalizationStateInfoCollection inactiveUserResult =
   PersonalizationAdministration.GetAllInactiveUserState(inactiveSince) ;


Running this type of query would be useful for a large, highly active site that did not wish to keep personalization data for users who no longer used the site.  In such a case the site administrator could run this query and then make decisions about which users to delete the personalization information for.  To assist with such a task the administrator could write another query which allowed them to view all personalization data for a specific user before they deleted the data for that user.  The following picture shows what these queries might look like when presented as a couple of administration web parts.

 

Two web parts that are used to view the results of personalization data queries.

 

The code for finding the personalization data for a specific user looks like this:


PersonalizationStateInfoCollection userResult =
    PersonalizationAdministration.FindUserState(null, UserNameTextBox.Text);


When the administrator has decided to delete the personalization data for a specific user they can simply call the ResetUserState method of the PersonalizationAdministration class like so ;


PersonalizationAdministration.ResetUserState(null, UserNameTextBox.Text);


Finally, the PersonalizationStateInfoCollection class contains a collection of PersonalizationStateInfo instances.  The PersonalizationStateInfo class is an abstract class and so each of the items will actually be an instance of either the UserPersonalizationStateInfo class or the SharedPersonalizationStateInfo class.  The PersonalizationStateInfo class itself only contains 3 properties that are useful to us which are: LastUpdatedDate, Path, and Size.  When looping through a collection of personalization data from a query such as GetAllInactiveUserState we must therefore cast each item to a UserPersonalizationStateInfo object before we are able to get at the Username of the user that is associated with the personalization data.  The following code snippet shows an example of the properties that can be found on a PersonalizationStateInfo item:

 

inactiveUserResult[0].LastUpdatedDate;  
inactiveUserResult[0].Path ;
inactiveUserResult[0].Size ;

((UserPersonalizationStateInfo)inactiveUserResult[0]).Username;
((UserPersonalizationStateInfo)inactiveUserResult[0]).LastActivityDate;

posted on 3/13/2006 7:31:41 AM ( 6 Comments )


IE7 - Support for Multiple Home Pages

Last week in Sydney I asked a few people at the Live.com event about how they consume the web because I wanted to see whether people use their web browser for more than search.  My argument was that I only ever use web pages when I'm searching for stuff and that because I mostly used Google for search I had Google/ig as my portal.  This made sense to me because if I'm going to the web to search for stuff then that's where I wanted to be but I could see current news, events, weather, and read blogs from that page by adding web parts to it.  Frank shot me down by telling me that he starts his day by opening up a bunch of web pages to news, sport, weather, blogs and such and browsing through them like a digital version of a newspaper.  Frank will like the feature that I'm about to talk about here...

I've really wanted to give MSNSearch a chance but it's a catch-22 because I won't trust MSNSearch until I use it and I won't use it while I don't trust it.  This problem becomes even greater for me now that Live.com is "lit up" because quite frankly it's easily the best portal on the market and so I'm only robbing myself by using the Google portal just because I use their search.

Thankfully IE7 now allows you to have multiple Home pages and so when I start up my browser I can get the Live.com portal as my main home page and keep the Google window bubbling away in the background until I'm confident enough to sever that link altogether.

Having used MSNSearch as my primary search for a few days now I must say that I'm liking it - and the DHTML "infinite scrollbar" on the Live.com search results page makes it a cinch to page through search results in an Ajaxian way.

posted on 3/12/2006 10:57:02 AM ( 1 Comments )


Lighting up my blog - with a new tagline

Since I started blogging a couple of years ago my blog has had the following tagline's:

  • ShowUsYour<Blog> - this was my first tagline and was used because, prior to having a blog all of my web content was published on my previous site which was called ShowUsYourCode.
  • Irregular Expressions Regularly - this was the tagline for my separate regex blog.
  • Thinking Products... - this is the current tagline for my blog and is meant as a silly play on words.  It means two things in one.  Firstly it emphasizes the fact that I spend a lot of time thinking about building "products" as opposed to just "coding".  Secondly it is a silly way of writing that thinking "produces" things.  In other words the act of thinking itself is productive.

With the upcoming release of my book about creating web portals I'm hoping to align myself much more closely to things such as Vista, Web Portals, and personalization in software and the topic that cuts across these slices and which also has attention is Live.com. 

The phrase that is associated with Live.com is "Light up" and you'll hear it a lot over the coming months.  It is a term that is used to indicate that something has become active or engaged - such as an interaction between two participants or a web part which performs some gesture upon activation.  It is even used to refer to the Live.com site itself.  When Microsoft say: "We're planning to light up Live.com" they are saying that they will "activate the site" or "release it".

Over the next 12 months I'm planning to grow the readership of my blog through much more planned release of content that is targetted around Web 2.0.  In other words, I'm going to "Light Up" my blog.  Because of this new "focus" I want to create a new tagline for this blog that reflects what I'm doing and so far I have the following ideas:

  • Let's Light Up
  • Lighting up the web
  • Lighting up Web 2.0

I think that I prefer the first one because it infers that there is some for of engagement in the blogging activity between me and you - and that's very much how I'd like it to be. 

Which tagline do you prefer?

posted on 3/11/2006 9:12:37 AM ( 4 Comments )


Live.com Gadgets - Come all ye Component Builders?

I was fortunate enough to see a preview of the Live.com platform last night in Sydney.  At the event I saw the Live applications and heard about the future of the platform.  I have to say that I walked away with a head full of ideas.

My main interest in Live.com centers around gadgets and so I'm very interested to see whether  "Live" exposes an open set of services that could act as a bedrock for building rich Web 2.0 mash-up style applications.  My hope is that at some point developers will be able to tap in to the Live services to create gadgets that are highly personalized and which target the end-user.

I haven't done a lot of research into gadgets at this stage but I'm very keen to learn more about where Microsoft is heading with this stuff.   If the Live services are open then this is going to be an amazing time to be a component builder in the web apps space.

 

posted on 3/10/2006 7:14:50 PM ( 0 Comments )


Good news story for BlogML and SubText

Chris blogs about his experience of being able to seamlessly migrate his blog content from Community Server to SUB to SubText.  This is great!

http://chrisfrazier.net/blog/archive/2006/03/07/SubText,BlogML,andPostXING.aspx

Chris's experience reads like a core use-case for BlogML.  If more bloglords adopted BlogML in their products stories such as this would be common-place and users would finally be free to try out as many different blogging platforms as often as they liked.

posted on 3/8/2006 1:30:00 PM ( 1 Comments )


Been bitten? Then you should check for Byte Order Marks

A little while ago Chris Frazier wrote this post about Byte Order Marks in the payload of an XML response.  All that I can say is that I'm extremely grateful for that post because it has saved me on a couple of occassions now.  The first time that it saved me was when Mitch and I were doing some work at a client site last year and we were having trouble reading the XML that was being returned from the TFS web services.  I encountered this problem again the other day while consuming Grant's Readify Bloggers OPML file.  If you download the OPML file and look at the first character you will see that it is not a '<' character.

As Chris points out in his post, the way to fix this is to check the first character of the XML payload before reading it in and if it's not a '<' character then simply strip the Byte Order Mark off like so:


//...the DeserializeResponse method that accepts a stream
StreamReader sr = new StreamReader(stm);

string content = sr.ReadToEnd();

if(content.Trim().Length > 0 && content[0] != '<'){
 content = content.Substring(1);
}

StringReader str = new StringReader(content);

try{
 xdoc.Load(str);
}

posted on 3/8/2006 6:03:03 AM ( 3 Comments )


A huge cover up at work

I recently started a new consulting engagement here in Canberra to do some hard-core work with VSTO.  It's been pretty cool and the guys have been great to work with but unfortunately they have some pretty sloppy induction processes.  For example, can you guess how I discovered that the bathrooms with the showers are Uni-Sex areas? :-)

posted on 3/7/2006 5:45:54 PM ( 3 Comments )


Making better use of the UrlFormatter in SUB

As Brendan pointed out in his recent post, I got pretty slack with implementing the UrlFormatter class in SUB.  Basically, every data type in SUB inherits from a base class known as "ApplicationDataObject" which gives each item enough properties to be displayed within an RSS feed.  One of the classes that I implemented quite early on in the piece was the UrlFormatter whose job it was to take an instance of a generic ApplicationDataObject class and to produce a suitable URL from it.  Internally the code looks something like this:

public class UrlFormatter {
 
    public static string FormatUri(ApplicationDataObject item) {
        if (item is Post) {
            return string.Format("{0}Posts/Post.aspx?postId={1}", Globals.UrlStartPath, item.Id);
        }else if( ... ) {
            ...
        }else{
            return Globals.UrlStartPath;
        }
    }
}

Here we can see that the UrlFormatter is passed an ApplicationDataObject and then uses an if statement to determine the type of the object and then returns the URL for that particular instance.

Over the weekend I went through the SUB source code and identified several of the Repeater that Brendan mentioned in his post that were using independent logic for displaying the URL's for posts.  What I ended up doing was to remove the ItemTemplate code from each of the main display Repeaters that are used to display Posts on the Home Page, the Posts By Category page, and the Posts By Month Page and I put the HTML that was within those ItemTemplates into a User Control and I load that as the ItemTemplate of the Repeaters.  The code for the User Control looks like this:

<div class="post">
 <h5><a href='<%# UrlFormatter.FormatUri((Post) ((RepeaterItem)Container).DataItem) %>'>
            <%# ((Post)((RepeaterItem)Container).DataItem).DisplayName%></a></h5>
 <p><asp:literal runat="server" text='<%# ((Post) ((RepeaterItem)Container).DataItem).Description %>' id="Label4"/></p>
 <p class="postfoot">posted on <%# ((Post)((RepeaterItem)Container).DataItem).DateCreated.ToString()%>
  ( <a href="<%# UrlFormatter.FormatUri((Post) ((RepeaterItem)Container).DataItem) %>#Feedback">
                <%# ((Post)((RepeaterItem)Container).DataItem).CommentCount.ToString()%> Comments</a> )
 </p>
</div>

You can see that the Container must now be cast to a RepeaterItem before it is cast to a Post.  The code in the hosting Repeaters now looks like this:

<asp:repeater id="PostList" runat="server" enableviewstate="False">
    <separatortemplate>
        <hr />
    </separatortemplate>
</asp:repeater>

… and I simply put in some code to load the template at runtime:


protected override void OnInit(EventArgs e) {
    base.OnInit(e);
    this.PostList.ItemTemplate = Page.LoadTemplate("~/UserControls/PostItemTemplate.ascx");


Now I can easily implement Brendan's cool idea for using the FormatUri function of the UrlFormatter as an abstraction for implementing friendly formatted Url's for posts in SUB.

posted on 3/7/2006 5:42:58 PM ( 1 Comments )


Url Mappings and Feedburner

The other day I posted a plea for subscribers of my blog to point the subscription for my feed to my feedburner link but today I'm asking that you change it back to the original Url of:

    http://MarkItUp.com/Rss.ashx

The reason for this is that in a comment to that post, Rick Klau who is the VP of Business Development with Feedburner mentioned that I'd be better off having people continue to point at my Rss.ashx page and performing a silent re-direct to the Feedburner URL under the covers.  This makes a lot of sense because it means that I'm not constantly asking people to change their link - like I am now :-) 

To implement the solution I created a special URL which still exposes my RSS feed and I point the Feedburner bot at that link.  The link for the bot is: http://MarkItUp.com/RssForBots.ashx.  Notice that if you browse to my http://MarkItUp.com/Rss.ashx page that you will end up at the Feedburner page but it you point at the http://MarkItUp.com/RssForBots.ashx URL you will see my raw feed.

Anyways, as with all simple programming tasks things quickly went south and it resulted in a major operation.  My initial thought was that I could simply use the UrlMappings service that comes with ASP.NET and re-target my RSS feed like so:

<urlMappings>
  <add url="~/Rss.ashx" mappedUrl="http://feeds.Feedburner.com/MarkItUp" />
</urlMappings>

Unfortunately it turns out that the UrlMappings service will not serve up URL's that are external to your site.  Damn!  I'm starting to hate that darned UrlMappings thing… me and it just don't hit it off.

So what I decided to do was to create my own UrlMappings service instead.  I iplemented my service as an HttpHandler that would read in a Mappings.xml file and handle re-directions to external URL's. 

First I created a mappings file named UrlMappings.xml which lives in ~/App_Data and which looks like this:

<UrlMappings>
  <UrlMapping url="~/Rss.ashx" mappedUrl="http://feeds.feedburner.com/MarkItUp"></UrlMapping>
</UrlMappings>

Next, because my feed is now served up at two locations I deleted the Rss.ashx physical file and moved it into the ~/App_Code directory and configured a couple of UrlMappings using that silly ASP.NET UrlMapping service like so:

<urlMappings>
  <add url="~/Rss.ashx" mappedUrl="Redirector.ashx" />
</urlMappings>

In this case, Redirector.ashx is the location of the custom HttpHandler that I wrote to manage my own UrlMappings file.  You can see that from the HttpHandler mappings that I created to handle the requests:

<httpHandlers>
  <add verb="GET,POST" path="Rss.ashx" type="MarkItUp.SingleUserBlog.Web.RssFeedHandler" />
  <add verb="GET,POST" path="RssForBots.ashx" type="MarkItUp.SingleUserBlog.Web.RssFeedHandler" />
  <add verb="GET,POST" path="Redirector.ashx" type="MarkItUp.SingleUserBlog.Web.Redirector" />
</httpHandlers>

So now when a user browses to my Rss.ashx page they are redirected to the Redirector which reads my UrlMappings file and sends the request off to Feedburner.  Of course the upside of all this is that SUB now has a dinky little redirector that can map out to external links - whoop-dee-doo!

posted on 3/6/2006 8:47:40 PM ( 3 Comments )


Implementing the Cache Pattern

I mentioned recently that the performance of SUB has been quite poor and I've started diagnosing the cause of this by instrumenting my code to see what's going on.  I also wrote an introductory article on code instrumentation which can be found here:

     http://markitup.com/Posts/Post.aspx?postId=fa94c852-fd16-4ba9-a5f0-1f72437f7cd2

I'll talk more about the specifics of the instrumentation and diagnostics in a follow-up post when I have things totally sorted although the changes that I've made so far have improved things quite dramatically. 

While going through the SUB file handling code I've been taking the time to check some of my coding patterns to ensure that operations such as caching and how I'm handling resource locking is all sweet.  Because caching plays such a large and important role within SUB I decided that I should check my caching pattern just to be sure that things are cool there and that the pattern is solid.  Currently my caching pattern looks something like this:

Data GetData( dataID ) {

     string key = "GetData" + dataID ;

     if (Cache[key] == null) {
         Data item = GotoDatabaseAndFetchData( dataID ) ;
         CacheHelper.Insert(key, item);
     }

     return HttpRuntime.Cache[key] as Data;
}

To check my pattern I headed off to Steve Smith's blog since he is the caching expert that I know best.  While browsing Steve's blog I found the exact post that I was after here:

     http://weblogs.asp.net/ssmith/archive/2003/06/20/9062.aspx

As Steve pointed the correct pattern to use is this:

Data GetData( dataID ) {

    string key = "GetData" + dataID ;
    Data item = Cache[key] as Data ;

    if (item == null) {
         item = GotoDatabaseAndFetchData( dataID ) ;
         CacheHelper.Insert(key, item);
    }

     return item;
}

Notice that in Steve's pattern a local variable is populated and then inserted into the Cache but that it is the variable that is returned from the method.  In my original code I was returning the value held in the Cache directly from the method.  As Steve notes in a recent email, on a busy site where you have sufficient load/memory pressure the code in my original pattern can cause inconsistent behavior because the item can actually be removed from the Cache in-between adding the item to the Cache and returning it at the end of the method.

Thanks Steve!

posted on 3/6/2006 5:15:14 PM ( 2 Comments )


Friendly URL's for SUB

In this post Brendan Kowitz talks about how he managed to implement friendly URL's for SUB - very cool!  He also pointed out that even though I had a FormatURL method that was initially created to do all of URL formatting in the application that I hadn't done a very good job at using it - too true!  My mistake there I'm afraid. 

There should be another release of SUB coming out in the next fortnight which will have some bug fixes and I'll try to include the cool stuff that Brendan has done for formatting friendly URL's into the core source code.

posted on 3/5/2006 9:08:06 PM ( 0 Comments )


SUB Perf Issues

Recently I noticed that my blog was running really slowly even though SUB was running at a fine clip on my own development machine. In addition to the general application slowness, Mitch and I discovered that when we went to import the BlogML for his NotGartner site that we experienced some unhandled exceptions relating to file locks on the XML index files.

My suspicion is that as the size of the XML files gets larger that the time to acquire and release file locks is taking longer to the point where my logic becomes fragile and unstable. I'm going to have to revisit the FileHelpers class and refactor it to ensure that files are handled in a much more error resistant manner. FileHelpers has always been in need of a good refactoring and some Health Monitoring code so taking the time to go through that code should do it the world of good I suspect.

During the refactoring I'm going to normalize the architecture of the file writing api's so that I have a more normalized structure of a business logic wrapper which calls through to a data storage engine. Architecture diagrams and details pending :-)

NOTE:
If you are suffering from these performance issues then I can advise you to check out Brendan Kowitz's new SQL Lite Data Provider for SUB.  This should speed things up a whole heaping lot:

    http://www.kowitz.net/Posts/Post.aspx?postId=34

posted on 3/5/2006 8:24:53 PM ( 0 Comments )


Health Monitoring and Instrumentation - Prescriptive Guidance

As ASP.NET developers we are all familiar with the concept of writing trace statements to the Trace log so that we can use that information later at runtime to assist us with diagnosing problems in our applications.  For example, writing exception messages to the Trace log can help understand why things are not working as we expect - especially when our code is layered and finding the root cause of small inconsistencies may not be easy to detect by simply viewing the output of a web page.

As for prescriptive guidance about where to place tracing statements within an application’s code, the obvious strategic targets that are most likely to cause problems at runtime should be targeted so that we can work out how to diagnose those errors when they occur.  At a minimum I would suggest instrumenting the following code:

  • Exception handling blocks
  • Calls to external systems which may be expensive so that we can monitor how long those operations are taking
  • Calls to complex business logic operations to help detect erroneous logic

Writing trace statements is useful for diagnosing problems that already exist in our applications but wouldn't it be nice to be alerted to potential problems before they actually occur so that we can do something to remedy them before they start causing our application to fail.  In this way we can be proactive to potential problems rather than always being reactive.  The activity of and detecting certain types of issues before they become problems is known as “Health Monitoring” and involves keeping track of performance counters in our code and viewing these vital statistics periodically to keep a look-out for things that might be going wrong. 

ASP.NET 2.0 contains an event based health monitoring system known simply as “Health Monitoring” that we can tap into to keep track of the health of our applications.  We can use the Health Monitoring system to monitor the health of our applications and send notifications as thresholds for certain types of events are reached.  For example, periodically the ASP.NET process will be forced to recycle which will cause an application restart to occur.  Most of the time these restarts are to be expected, such as when an administrator makes a change to the web configuration file an application restart will occur.  However there are other times when application restarts indicate that an application is experiencing extreme difficulty and we would very much be interested in receiving notifications about these events to let us know that everything is not fine.  As an example, large numbers of application restarts are a typical symptom that a denial-of-service attack is taking place.  Using the Health Monitoring service we could configure our application to listen for application restarts and configure a rule that would cause a notification to be sent after a certain threshold is breached within a given time.

The Health Monitoring system comes with a large number of standard events that are raised during the lifecycle of the application and also some standard providers (Sinks) that are used to log the event notifications.  The standard provders include an Email provider for sending email, a SqlWebEventProvider for logging notification information into a SQL Server database, and a WMIEventProvider that maps ASP.NET health-monitoring events to Windows Management Instrumentation (WMI) events.

The Health Monitoring system is highly configurable and so we can easily create our own events and providers to record information about certain types of events and have them forwarded to a store of our choosing.  For example, we might want to send an SMS to an application administrator whenever the time to make web service calls to external sites exceeds a certain time threshold - such as 3 seconds.

Here are some excellent articles that will help you get started with implementing Application Health Monitoring in your ASP.NET applications:


PAG : How To instrument Code
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag2/html/paght000016.asp

PAG: How to use Health Monitioring
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag2/html/PAGHT000011.asp

Link to an excellent article which demonstrates how to create custom Events and Providers
http://msmvps.com/blogs/gbvb/archive/2004/09/15/13578.aspx

posted on 3/5/2006 7:57:56 PM ( 9 Comments )


Subtext 1.0 "Nautilus" Lives

Late last year when BlogML was a shiny new object I started to look around the blogging universe for potential blogging engines to target.  One of the people that I contacted was Phil Haack who I knew was involved in an open source blog called SubText.  SubText is a branch of the the old .Text codebase.  This all happened in early October last year.

This morning when I synch'd up my aggregator I was very pleased to read this announcement from Phil:

    http://haacked.com/archive/2006/03/02/Subtext1.0NautilusEditionReleased.aspx

SubText 1.0 Nautilus

I get a great feeling when I see projects like SubText come to life; it keeps me believing in the dream that I had when I started coding. 

Anyways, because these guys have implemented BlogML, all of you suckers who have installed SUB can go to your Administration page and dump out your SUB blog into BlogML and then import it into "Nautilus"!   

Well done guys, enjoy the glory!

posted on 3/4/2006 2:19:35 AM ( 0 Comments )


Favour to ask...

Up until the weekend I had really only heard about Feedburner but hadn't taken the time to go and see what it's all about but after seeing this post I got interested in enough to move my RSS feed over.  So now I have a favour to ask.  If you are subscribed to my feed could you please change the URL that you use to my new Feedburner address:

  http://feeds.feedburner.com/Markitup

This will help me to better understand how many people are subscribed to my blog and will also hopefully help me to ultimately produce better content.

Thanks! 

 

posted on 3/3/2006 2:32:22 AM ( 9 Comments )