Friday, February 05, 2010

Marker Kentico Business library released

The Marker Kentico Business library helps hardcore Kentico developers do things better
Friday, February 05, 2010 3:05:58 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Wednesday, November 04, 2009

SSL Host Headers in IIS 7 with Test SSL Certificate

Contrary to popular believe you can actually run multiple ssl sites on an IIS 7 box which only has one ip address (It's easier if you have multiple ip addresses but not impossible if you don't).

This is very useful for development and test boxes running a test ssl cert but can also be used in production environments if all secure sites run under a super cert (e.g. *.mydomain.com)

Follow the guide here

http://www.sslshopper.com/article-ssl-host-headers-in-iis-7.html

However, for the certificate you can easily use a test one in non live environments

http://weblogs.asp.net/scottgu/archive/2007/04/06/tip-trick-enabling-ssl-on-iis7-using-self-signed-certificates.aspx

I recommend you install a single TestSSL certificate on a development machine and apply this process for any new SSL enabled sites in development.

The key I discovered is to assign the certificate to the first site in IIS before running the command line to enable the host headers for other sites.

Wednesday, November 04, 2009 9:51:35 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, October 22, 2009

Enabling a Fully Qualified Domain Name (FQDN) in Team Foundation Server 2010 (TFS 2010)


EDIT: Please see Aaron Block's excellent guide to understanding TFS communiciation architecture along with tips to set this up. I have just added my thoughts in here on top now that i have found this doc:

Organisations may wish to expose their Team Foundation Server resources (including SharePoint Team Sites) using fully qualified domain names (FQDNs) both internally and externally. This document provides (almost) complete guidelines on how to do this, with particular focus on the TFS and SharePoint configuration to support FQDNs.

Install TFS 2010 Beta 2. This guide assumes a single server installation, but could easily be interpreted to work with multiple application tiers.

Set up your FQDN. For internal access, it's recommended that you update your DNS Server internally (e.g. Forward Lookup Zone for tfs.yourcompany.com) to ensure that the FQDN points to an internal IP Address when users are connected to the network (to avoid having to route out to the internet and back).

For external access, add an A record for the FQDN to the DNS zone file for your domain (via your ISP’s control panel normally). You will need to configure your perimeter network appropriately to route public 80 and 8080 (or 443 if you are going secure, not covered here) traffic through to your TFS server which is not covered here. (Although I intend to post separately on doing this with ISA 2006 soon).

Ensure your FQDN is working internally and externally as expected before continuing to configure TFS and SharePoint.

Disable the Loop Back Check on your TFS Server. http://support.microsoft.com/kb/926642. This is required otherwise the TFS Admin Console will throw errors as it won't be able to access your FQDN

Restart your server

Add your FQDN to the alternate access mapping of SharePoint for the TFS Web Application  using SharePoint 3.0 Central Administration > Operations >Alternate access mappings (use 'Add Internal Urls').

Change the RS & WSS locations by directly editing tbl_LocationMapping table in the TFS Configuration database, adding your FQDN in. (Aaron has advised this is definitely not necessary, as these urls can be altered in the TFS Admin Console, see below)

Restart IIS 7.0

Open TFS Admin Console, select Application Tier, then click on Change URLS.

Put your FQDN in the Public Url field and change the Server Url to continue to use the netbios machine name and then click OK. and click OK

Select Application Tier > SharePoint Web Applications, then select the top row in the list within the SharePoint Web Applications list box. Click 'Change SharePoint Web Application' and put your FQDN in the Friendly Name and Web Application Url fields and click OK.

Select Application Tier > Reporting and click Edit. Ensure that your FQDN is used for the Warehouse Database, Analysis Services Database, Report Server Url and Report Manager url.

Start all services again once this is completed.

Within the TFS Admin Console, select Extensions for SharePoint Products, then select the top row in the list within the list box.

Click Modify Access, and ensure the FQDN is added to the URL for Team Foundation Server and click OK.

Note! Excel Reports on the SharePoint sites don't work unless you open ports for Analysis Services (link to follow...)

You should now be ready to go!

Credits
This post builds on the work done in the post below, but is updated for Beta 2 and also includes additional configuration.
http://www.euri.com/Blog/tabid/85/EntryId/38/Changing-the-URL-of-Team-Foundation-Server-TFS-2010-Beta-1-to-a-FQDN.aspx

Thursday, October 22, 2009 9:47:11 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Monday, September 21, 2009

Net OAuth Sample — Working with Justin.TV

How to use OAuth, with .Net when working with Justin.TV
Monday, September 21, 2009 5:02:13 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Tuesday, September 08, 2009

Tech Ed NZ Session List (in one nice big list)

Despite asking, i wasn't able to get this from the tech ed organisers and was fed up with the god awful ajax scrolling nonsense

Hopefully this will make your session planning a little easier.

Word Session List

Excel Agenda

Tuesday, September 08, 2009 10:55:11 AM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, June 29, 2009

KandaAlpha now on codeplex

kandaalpha a go go
Monday, June 29, 2009 11:34:59 AM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, June 01, 2009

Kentico CMS 4.0 and Bounded Box Image Resizing

This article has code specifically for Kentico CMS 4.0 and can be used in a scenario where you have an image’s dimensions and want to ensure that the image fits into a known bounded box.

With Kentico CMS you retrieve images using a call to a handler at /CMSPages/GetFile.aspx. That page accepts parameters Height, Width and MaxSideSize. Height and Width can be fixed and specifying one and not the other will retain aspect ratio. MaxSideSize allows a single value to bound the height and width.

However, if you have a given bounded box on the page (e.g. say a 400 * 300 space) and you want to make sure an image fits inside that space whilst retaining aspect ratio there is no way to do this.

I’ve emailed this code to the Kentico support team to allow MaxHeight and MaxWidth properties so that we can do this. In the meantime this hack/fix within GetFile.aspx.cs code behind file will allow you to supply negative values for height and width which then act as a bounding box!

// HACK - Interpret MaxHeight and MaxWidth via negative Height and Width values (line 599)
if (this.Height < 0 || this.Width < 0)
    ApplyBoundingBox(atInfo.AttachmentImageHeight, atInfo.AttachmentImageWidth);

/// <summary>
   /// Custom Hack to interpret negative height and width values as setting bounding box
   /// </summary>
   private void ApplyBoundingBox(int imageHeight, int imageWidth)
   {

       if (this.Height >= 0 && this.Width >= 0)
           return;

       int maxHeight = 0;
       int maxWidth = 0;
       float ratio = 0;

       if (this.Height < 0)
       {
           maxHeight = this.Height * -1;
           this.Height = imageHeight;
       }

       if (this.Width < 0)
       {    
           maxWidth = this.Width * -1;
           this.Width = imageWidth;
       }

       if (maxHeight > 0 && this.Height > maxHeight)
       {
           ratio = (float)this.Height / (float)maxHeight;
           this.Height = maxHeight;          
           this.Width = (int)((float)this.Width / (float)ratio);
       }

       if (maxWidth > 0 && this.Width > maxWidth)
       { 
           ratio = (float)this.Width / (float)maxWidth;
           this.Width = maxWidth;
           this.Height = (int)((float)this.Height / (float)ratio);
       }

   }

Monday, June 01, 2009 11:43:47 AM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Saturday, May 23, 2009

asp.net development on a mac

Well, sort off…

The idea is that you have designer types who hate windows and will get ill with prolonged usage. So as to make sure you have an adequate supply and flow of decent mark up coming your way as a developer it’s in your best interests to ensure designer type is safely ensconced within the comfort zone of single button mice and strange looking speakers.

We use team foundation server, otherwise known as TFS, which helps us to manage the source control of all our development efforts. In addition, it helps us manage work items (tasks and bugs) during software projects.

If you are on a Mac and are working with TFS, you need this:
http://www.teamprise.com/products/explorer/

OK, so you can work with source control and work items, big deal, how do you actually run an asp.net website?. Well, thanks to the wonders of virtualisation you simply run a windows vm with an iis website as required and give it an appropriate host header such as macdebug.projectname.mycompany.net. Ensure FTP server is running on your windows vm with an appropriate login so that you can copy files to this website via ftp from your Mac.

Now, back on your good old macintosh, you create a TFS workspace and get latest on your lovely TFS solution to have the files locally on your mac. You use your favourite text or html editor and work on the files, checking them out and in as required, and doing all your work items, great. Obviously visual studio is the tool of choice for .net development but if all your tasks are around working with content assets, mark up and styling related files then you don’t really need all that overhead.

All you need to do is ensure that for each change you make that you have an action to FTP the file that has been changed across to the IIS website via FTP automatically. This ensures that you have the IIS website running off your latest changes.

Last thing you need to do is create a hosts file entry on your mac to point macdebug.projectname.mycompany.net to the IP address of your windows vm. Then you can fire up safari and browse to http:macdebug.projectname.mycompany.net to see your asp.net website!

I’ll post up some visuals and details on the tools we’re using on the mac when I have them.

Saturday, May 23, 2009 6:41:29 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, May 22, 2009

Expression for Arts Sake

Friday, May 22, 2009 10:14:59 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Saturday, May 16, 2009

Where is my mind Wolfram?

image

Saturday, May 16, 2009 2:46:27 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Saturday, May 02, 2009

IE8 Customisation – Moving Stop and Refresh Icons next to Back and Forward

I just started playing with Windows 7 RC1 and thought, i know i’ll try IE8 again, see if they’ve fixed up the main usability thing that was always annoying me which was the way the Stop and Refresh icons were on the other side of the browser from the back and forward icons.

After struggling with the Tools menu i came across this blog post.

http://blogs.msdn.com/ie/archive/2009/04/20/customization-in-ie8.aspx

Right-click IE8 command bar then select Customise > 'Show Stop and Refresh Icons before Address Bar’

If you remove all the toolbars you get a really clean interface with all the navigation buttons next to one another.

 

image

Saturday, May 02, 2009 2:29:09 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Saturday, April 18, 2009

IIS7 Extensionless Urls and Kentico CMS 4.0

Disclaimer: This post contains unsupported guideline for configuring your Kentico CMS 4.x to utilise extensionless urls with IIS 7.0. Use with care!

Base System Requirements: IIS 7.0 with .net 3.5 SP1 on a Windows Vista dev machine or Windows 2008 server to utilise extensionless urls.

Firstly, install the marvellous IIS 7.0 URL Rewrite Module
Get it here: http://www.iis.net/downloads/default.aspx?tabid=34&g=6&i=1692
Learn about it here: http://learn.iis.net/page.aspx/460/using-url-rewrite-module/

Now, make sure Kentico is configured not to interefere with things…

Kentico automatically applies a filter to the form tags. You need to disable this here:

  • Site Manager > Settings > Output Filters >
  • Ensure the ‘Excluded output form filter URLs’ value is set to a single forward slash.. /
  • Site Manager > Settings > Urls>
  • Ensure the Friendly Url Extensions value is blank

There is currently no way of ensuring that automatically generated urls from Kentico contain a trailing slash. The user must set the Document UrlPath for each page in Page > Properties > Urls to include the trailing slash. However the trailing slash is enforced via in IIS 7 rewriting rule. It is hoped that a future version of Kentico will allow for this to avoid the extra 301 redirect.

Now apply the following website configuration….

Place the following code in the Page_Load of your master page.
            // ensure we fix up the form action if required
            if (!String.IsNullOrEmpty(Request.ServerVariables["HTTP_X_ORIGINAL_URL"]))
            {
                form1.Action = Request.ServerVariables["HTTP_X_ORIGINAL_URL"];
            }

This ensures that Asp.Net postback and ajax work correctly with the IIS7 URL Rewrite Module

Now all you need to do now is apply whatever special rewriting rule syou like within the web.config, utilising the IIS Rewrite Module’s capabilities as you need them. (Note that you don’t need to do anything within IIS, you can manage everything within the web.config and simply deploy it out to target servers without worrying about any additional configuration).

For example, the EnforceTrailingSlash rule below will ensure that a trailing slash is added to all urls without extensions, performing a 301 redirect in the process. This is so to avoid multiple urls (ones with and without slashes) returning the same content which isn’t ideal from an SEO perspective.

The TrailingSlashToAspx rule below will ensure that a trailing slash is rewritten internally to .aspx, so that the kentico rewriting engine can take over. Note that the Kentico CMS folders are ignored (ones starting with CMS..)

<system.webServer>
        <rewrite>
            <rules>
                <rule name=”EnforceTrailingSlash”>
                    <match url=”^(.*)$” ignoreCase=”false” />
                    <conditions>
                        <add input=”{REQUEST_FILENAME}” matchType=”IsFile” negate=”true” />
                        <add input=”{REQUEST_URI}” negate=”true” pattern=”(.*)\.([a-zA-Z]+)(\?.*)?$” />
                        <add input=”{REQUEST_URI}” negate=”true” pattern=”(.*)/$” />                       
                    </conditions>
                    <action type=”Redirect” url=”{R:1}/” redirectType=”Permanent” />
                </rule>

                <rule name=”TrailingSlashToAspx”>
                    <match url=”^(.*)/$” />
                    <conditions>
                        <add input=”{REQUEST_FILENAME}” matchType=”IsFile” negate=”true” />
                        <add input=”{REQUEST_URI}” negate=”true” pattern=”/cms(.*)$” />
                        <add input=”{REQUEST_URI}” negate=”true” pattern=”^(.*)/\.aspx[#\w=\|\&amp;%-]*$” />
                    </conditions>
                    <action type=”Rewrite” url=”{R:1}.aspx” />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>

And so there you have it, a relatively painless way to get yourself all SEOd with IIS 7.0 and Kentico CMS 4.0.

Saturday, April 18, 2009 10:06:50 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Friday, April 10, 2009

Yellow Maps now live

We’ve just launched another brand spanking new website for Yellow in Yellow Maps. It gives you the ability to do general map and direction searches a la Google but also do specific yellow business listing searches. You can layer on points of interest and see these pop up on your directions from one place to another.

The site was built using Kentico CMS 4, .Net 3.5 SP1, JQuery and the Yellow and Google APIs. Thanks to Calvin, Darren, Campbell and late night pizza from Hell we made it!

Friday, April 10, 2009 1:25:21 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [4]  |  Trackback
 Wednesday, March 18, 2009

Marker and Yellow partner to bring IE 8 first in New Zealand

My good friend Nigel Parker over at Microsoft beat me to the post with this excellent blog post on Marker Studio's new search site for Yellow and customised IE8 browser experience:

http://blogs.msdn.com/nigel/archive/2009/03/17/yellow-blackcaps-first-to-build-and-deploy-on-ie8-in-new-zealand.aspx

The launch has been very successful with over 10,000 downloads of the Yellow IE8 browser in the first 2 days!

To add a bit of technical detail to Nigel's post we made heavy usage of the Google Search Ajax APIs. I kind of wish they still had the SOAP apis as it would have been easier in many respects using .net to bind the results using server side asp.net rather than be forced to work primarily with the ajax apis. Also, the ajax apis come with handy code snippets http://code.google.com/apis/ajaxsearch/ but they assumed things like ajax calls for paging requests which means the user can't book mark the urls. Aside from that a few workarounds here and there got us enabling Google integrated search quite easily. I would like people to note that the Live Search apis were superior in terms of the range of ways one could consume and make use search services and relevance in my book is very comparable between the two.

We made use of Linq to XML when consuming the core Yellow listings api which is REST based. This made the consumption and binding of the search results to the page using a standard asp.net repeater much easier. In fact, i cringed to think of the additional effort that was involved before Linq for XML in navigating XML Documents with the .net 2.0 xml apis which I never found particularly intuitive.

There is also some Salesforce integration for helping to manage competition entries where we created custom lead objects in Salesforce. It's kind of nice to have the ability to regenerate the wsdl for the web service after you make changes in the gui to core field information. It would be even nicer to have this discoverable at runtime so i could just regenerate proxies using a url rather than having to download the wsdl and re-run svcutil across the wsdl locally.

And let's not forget our good friend JQuery, and loving that Intellisense support in Vs.Net 2008;) Also a shout to facebox for those obligatory modals with rounded corners.

Oh, and the whole thing is powered by Kentico CMS. Kentico CMS is a powerful, flexible and affordable content and document management system that i have been personally recommending to all and sundry since i first came across it in 2005. At Marker  <shamelessPlug>we have a great team of experienced Kentico developers should be looking in this direction. Please give me a yell if you would like to discuss further</shamelessPlug>.

Wednesday, March 18, 2009 8:44:56 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [5]  |  Trackback
 Monday, March 09, 2009

New Marker Website

We just launched a brand spanking new website at http://www.markerstudio.com/ go take a look.
Monday, March 09, 2009 6:39:46 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, January 29, 2009

Twitter Feed and Friend Feed

I just realised there exists today more helpful free software than i could ever possibly imagine. A few years back I remember it being hard to find good little utilities to do even the most basic things like FTP in a reliable usable way.

TwitterFeed.com

Anyways...I've resuscitated my usage of Twitter by using www.twitterfeed.com. Essentially, this allows me to automatically prefix and post up tweets from RSS Feeds.

In my case, i'm automatically tweeting from Google Reader shared items (i simply click a share item in Google Reader, and a tweet is imminent..) and from this blog.

FriendFeed.com

In addition, i thought i would blabber a bit about www.friendfeed.com which is essentially an aggregation portal for your online activity.

I've integrated friendfeed activity directly into my blog (on the right hand side panel) which should make some of the things i'm doing without the need for formal blog posts.

You *could* if you wanted have twitter feed pull from all your online activity via freidn feed, but you would have to exclude twitter from friendfeed to avoid a nasty infinite loop of friendfeed/twitter posts;)

To avoid this, you can filter the friendfeed rss by service, but you can only select one service;( i wanted to create a feed for everything apart from twitter but couldn't do this.

This is why i'm manually adding feeds to twitterfeed.

Have fun!

Thursday, January 29, 2009 8:24:29 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [669]  |  Trackback
 Thursday, December 04, 2008

MCPD at last

And one more exam to get the web developer certification. This adds 3 points to our Microsoft partnership, only a few points left for gold! Some less boring posts soon i promise...

MCPD(rgb)_504

Thursday, December 04, 2008 9:44:43 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [5]  |  Trackback
 Tuesday, December 02, 2008

MCTS certification achieved

Another exam another certification, one more for MCPD and then i can retire safe in the knowledge I have contributed handsomely to the development and continuance of one of the world's largest corporations.

MCTS(rgb)_513_530

Tuesday, December 02, 2008 12:02:56 AM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, November 27, 2008

Entity Framework supported mappings

Just found a really really useful whitepaper on Entity Framework mapping possibilities. If you're doing any work with EF this will certainly come in useful.

http://download.microsoft.com/download/b/3/3/b333d63e-0df2-4d43-978a-1ce9d2f39801/EntityFrameworkMappingWhitepaper.pdf

Thursday, November 27, 2008 5:45:13 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, November 21, 2008

string shuffle in one line

shuffling strings
Friday, November 21, 2008 4:49:09 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, November 07, 2008

MCTS - Officially a Genius

MCTS

I am now officially a genius after scoring 929/1000 in my Moss (SharePoint) configuration exam. Thank you.

Friday, November 07, 2008 10:18:54 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Saturday, August 16, 2008

Entity Framework - Key Extension Methods

We created the following extension methods for entity framework to avoid code bloat in consuming applications when working with these key types. I hope you find them useful if you are working with the Entity Framework.

 

EntityObject

/// <summary>
/// Extension methods for EntityObject
/// </summary>
public static class EntityObjectExtensions
{

    /// <summary>
    /// Gets the original value for a modified entity object's property
    /// </summary>
    /// <returns>the value before the property was modified</returns>
    public static T GetOriginalValue<T>(this EntityObject entityObject, string propertyName)
    {
        if (entityObject == null)
            return default(T);
        if (entityObject.EntityState == EntityState.Modified)
        {
            ObjectContext context = [YOUR OBJECT CONTEXT]
            ObjectStateEntry stateEntry = null;
            context.ObjectStateManager.TryGetObjectStateEntry(entityObject, out stateEntry);

            if (stateEntry != null)
                return (T)stateEntry.OriginalValues.GetValue(stateEntry.OriginalValues.GetOrdinal(propertyName));

        }

        // return the value of the property
        return (T)entityObject.GetType().GetProperty(propertyName).GetValue(entityObject, null);
    }

EntityCollection<T>

/// <summary>
   /// Extension methods for EntityCollection
   /// </summary>
   public static class EntityCollectionExtensions
   {
       /// <summary>
       /// Loads the entity collection if it hasn't already been loaded
       /// </summary>
       /// <typeparam name="T">Type of entity collection</typeparam>
       /// <param name="entityCollection">Entity collection to potentially load entities into</param>
       /// <param name="entitySource">The source entity which has the entity collection relationship (modified or unchanged only)</param>
       public static void EnsureLoaded<T>(this EntityCollection<T> entityCollection, EntityObject entitySource) where T : class, IEntityWithRelationships
       {
           if (entitySource != null && entityCollection != null && !entityCollection.IsLoaded )
           {
               if (entitySource.EntityState == System.Data.EntityState.Modified || entitySource.EntityState == System.Data.EntityState.Unchanged)
               {
                   entityCollection.Load();
               }
           }
       }

       /// <summary>
       /// Returns the collection as a queryable type
       /// </summary>
       /// <typeparam name="T">Type of entity collection</typeparam>
       /// <param name="entityCollection">Entity collection to return as a queryable object</param>
       /// <param name="ensureLoaded">Flag to determine if to load the collection if it has not been done so already</param>
       /// <returns>Queryable object for the in memory collection</returns>
       public static IQueryable<T> AsQueryable<T>(this EntityCollection<T> entityCollection, bool ensureLoaded, EntityObject entitySource) where T : class, IEntityWithRelationships
       {
           if (ensureLoaded)
               EnsureLoaded(entityCollection, entitySource);
           return entityCollection.AsQueryable();
       }

 

EntityReference<T>

 

/// <summary>
   /// Extension methods for EntityReference
   /// </summary>
   public static class EntityReferenceExtensions
   {

       /// <summary>
       /// Loads the entity reference or its value if it hasn't already been loaded.
       /// </summary>
       /// <typeparam name="T">Type of entity reference</typeparam>
       /// <param name="entitySource">The source entity which has the entity reference relationship (added, modified or unchanged only)</param>
       public static void EnsureLoaded<T>(this EntityReference<T> entityReference, EntityObject entitySource) where T : class, IEntityWithRelationships
       {
           if (entitySource != null && entityReference != null && !entityReference.IsLoaded && entityReference.EntityKey != null)
           {
               if (entitySource.EntityState == System.Data.EntityState.Added) // add the value directly as load will throw
               {
                   if (entityReference.Value == null)
                       entityReference.Value = LoadByKey<T>(entityReference.EntityKey);
               }
               else if (entitySource.EntityState == System.Data.EntityState.Modified || entitySource.EntityState == System.Data.EntityState.Unchanged)
               {
                   entityReference.Load();
               }
           }
       }

privateT LoadByKey<T>(object entityKey)
{
    if (entityKey == null)
        throw new ArgumentNullException("Supplied entity key is null, unable to load entity", "entityKey");
    // make sure the object is loaded in the object context
    ObjectContext objectContext = [YOUR OBJECT CONTEXT];
    EntityKey key = (EntityKey)entityKey;
    ObjectStateEntry entry;
    if (!objectContext.ObjectStateManager.TryGetObjectStateEntry(entityKey, out entry) || entry.Entity == null)
    {
        return (T)objectContext.GetObjectByKey(key);
    }
    return (T)entry.Entity;
}

       /// <summary>
       /// Whether or not the entity reference has an entity key with a value present
       /// </summary>
       public static bool HasEntityKeyFirstValue<T>(this EntityReference<T> entityReference) where T : class, IEntityWithRelationships
       {
           return entityReference != null && entityReference.EntityKey.HasFirstValue<int>();
       }

       /// <summary>
       /// Get entity key with a value present
       /// </summary>
       public static int GetEntityKeyFirstValue<T>(this EntityReference<T> entityReference) where T : class, IEntityWithRelationships
       {
           if (entityReference != null)
               return entityReference.EntityKey.GetFirstValue<int>();
           return 0;
       }

 

EntityKey

 

/// <summary>
   /// Extension methods for EntityKey
   /// </summary>
   public static class EntityKeyExtensions
   {

       /// <summary>
       /// Gets the first entity key value
       /// </summary>
       /// <returns>the first entity key value</returns>
       public static T GetFirstValue<T>(this EntityKey entityKey)
       {
           if (entityKey != null && entityKey.EntityKeyValues != null && entityKey.EntityKeyValues.Length > 0)
               return (T)entityKey.EntityKeyValues.First().Value;
           return default(T);
       }

       /// <summary>
       /// Sets the first entity key value
       /// </summary>
       public static void SetFirstValue<T>(this EntityKey entityKey, T value)
       {
           if (entityKey != null && entityKey.EntityKeyValues != null && entityKey.EntityKeyValues.Length > 0)
               entityKey.EntityKeyValues.First().Value = value;
           return;
       }

       /// <summary>
       /// Whether or not the entity key has a first value
       /// </summary>
       public static bool HasFirstValue<T>(this EntityKey entityKey)
       {
           var firstValue = GetFirstValue<T>(entityKey);
           var defaultValue = default(T);
           return (!firstValue.Equals(defaultValue));
       }

Saturday, August 16, 2008 3:26:05 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, July 04, 2008

Entity Framework Lazy Loading - A quick alternative with extension methods

I saw the following code on a customer object which made me think about affording a better way to query domain relationships without the extra methods, extension methods come to the rescue!

I realise transparent lazy loading a la Nhibernate is another option, but i think that this way keeps the spirit of explicitly loading from the database, but reduces the amount of code clutter on the client side so you are not forever checking whether a relationship is loaded or not, you simply request an IQueryable from the EntityCollection<T>.

        /// <summary>
        /// Finds a customer account with the specified ID
        /// </summary>
        /// <param name="customerAccountID">ID of the customer account to find</param>
        /// <returns>Customer account with the specified ID</returns>
        public CustomerAccount FindAccount(int customerAccountID)
        {
            if(!this.CustomerAccounts.IsLoaded)
            {
                this.CustomerAccounts.Load();
            }

            var query =
                from ca in this.CustomerAccounts
                where ca.CustomerAccountID == customerAccountID
                select ca;

            return query.FirstOrDefault();
        }

I added a static class with the extension methods for the EntityCollection type as follows:

public static class EntityCollectionExtensions
    {
        public static EntityCollection<T> EnsureLoaded<T>(this EntityCollection<T> entityCollection) where T : class, IEntityWithRelationships
        {
            if (!entityCollection.IsLoaded)
                entityCollection.Load();
            return entityCollection;
        }

        public static IQueryable<T> AsQueryable<T>(this EntityCollection<T> entityCollection, bool ensureLoaded) where T : class, IEntityWithRelationships
        {
            if (ensureLoaded)
                entityCollection = EnsureLoaded<T>(entityCollection);
            return entityCollection.AsQueryable();        }
    }

This allows you to do the following, which will only go to the database if the relationship is not loaded.

            var query =
                from ca in this.CustomerAccounts.AsQueryable(true) // ensure the relationship is loaded and return a queryable on it
                where ca.CustomerAccountID == customerAccountID
                select ca;
    return query.FirstOrDefault();

Friday, July 04, 2008 8:44:57 AM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Tuesday, June 24, 2008

A vote of confidence for the Entity Framework

I saw a post from the alt.net community here saying the EF was crap basically....http://efvote.wufoo.com/forms/ado-net-entity-framework-vote-of-no-confidence/

The core complaints raise some important issues, but i really don't think we need to go ballistic, and in some cases the concerns are just plain wrong. Time would be better spent finishing the Linq for NHibernate provider don't you think??

I've been working solidly with EF since the SP1 beta came out and can honestly say it's holding up very well across a large, enterprise data model structure, and alongside usage of a repository pattern and dependency injection to factor out most of the direct dependencies on the EF ObjectContext, we have a system that can move towards POCO over time with relatively little refactoring.

Here's some of my responses:

The design of the framework entities is that they are data only, causing issues in maintainability and making it difficult or impossible to implement business objects or more “real-world” objects. 
Wrong, you use partial classes to extend the generated aspects of the entities. This is explicitly encouraged and we use it a lot for core business rules and validation. There is nothing to stop you adding new non persistent properties or methods, or indeed new classes that are used alongside the entities.

The design of the framework entities is that they cannot be persistence ignorant, so things like unit testing become next to impossible because you cannot test the model without the database (for instance).
There are (admittedly difficult) ways to get close to POCO. Rather than tear your hair out, we used the repository pattern around the EF and avoid using the object context directly. You are then only dependent on EntityObject, EntityReference and EntityCollection on your entities. If you are sensible about it and don't work on object context, your refactoring when vnext comes along will be significantly reduced. This is a happy compromise for us and works well.

Lazy loading is not supported at all and requires a lot of extra code to make work.  This confuses me.  I thought I saw "lazy-loading" demoed internally but I might be mistaken.
KP > 'By design';) but honestly pretty easy to wire it up, not really a "lot of extra code". I have worked for years with NH too, and the time saved using the designer with EF more than makes up for it:)

Shared, canonical models contradict software best practices.  This appears to be related to using a single shared model for multiple contexts in the EF, rather than multiple models, one for each individual context. 
KP > Well, it may be a criticism of the vision of EF (the more than just an ORM story), but not of its core ORM functionality. Our clients are interested in the reporting aspects on their entity models without writing excessive code. It remained to be seen how this will pan out, but surely this is not a reason to pledge a vote of no confidence in a piece of technology?

Excessive merge conflicts with source control.  Apparently, since the diagram contains the model and the visualization, it causes tons of merge conflicts when a team is using it.
A somewhat moot point for most teams. We've settled on having a 'domain master', not a biggy for most teams? shared design on the database, entities and relationships would get messy in the best of worlds, i don't think this is a biggy.

Tuesday, June 24, 2008 5:22:28 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [6]  |  Trackback
 Thursday, May 29, 2008

Polymorphic Repository for ADO.Net Entity Framework

Wow, what a sexy title!

This post shows how you can have a repository pattern with the entity framework .

So, here we have a generic repository interface through which you can do all the nice things. You would normally use Castle Windsor (or similar Dependency Injection tool) to configure the Repository implementation (such as EFRepository) so you then just have a dependency on the interface, which is nice. Here's a snippet of how to configure the EFRepository to be used for all requests for IRepository from Castle Windsor. Note the ability to change object contexts and even the repository implementation, as long as IRepository is supported, the application won't care.

<castle>
    <components>

         <component id="objectContext" type="YourObjectContext"  ></component>
      <component id="iEFRepository" service="YourIRepository" type="YourEFRepository"
        <parameters>
          <objectContext>${objectContext}</objectContext>
        </parameters>
      </component>
    </components>
  </castle>

Note the reflection in the EFRepository implementation which allows you to query and work with all types in a hierarchy. By default you can't work directly with sub types in EF, you have to do extra work to get to them. The reflection gets the base type before communication with the ObjectContext to ensure minimal fussing about for the developer. Note i don't understand why this isn't built in to be honest, perhaps they ran out of time!

The whole point of this is that you avoid using your application's ObjectContext explicitly and only work with the core business entities that are then managed by the Entity Framework. This allows us to have a good separation of concerns between the various layers (although our entities are not pure POCO sadly). Note that i have only exposed the most widely used features of ObjectContext, you can extend your Repository interface and implementation to expose more advanced parts of the ObjectContext implementation if needs be.

In the future, EF may move towards greater persistence ignorance, but in the mean time structuring your application working off a Repository interface will mean minimal changes as EF changes moving forwards.

IRepository interface

public interface IRepository
  {

      /// <summary>
      /// Return reference to an underlying repository context
      /// </summary>
      /// <returns>the repository context</returns>
      object GetRepositoryContext();

      /// <summary>
      /// Return strongly typed IQueryable
      /// </summary>
      IQueryable<T> GetQuery<T>();

      /// <summary>
      /// Load entity from the repository or store if necessary
      /// </summary>
      /// <typeparam name="T">the entity type to load</typeparam>
      /// <param name="where">where condition</param>
      /// <returns>the loaded entity</returns>
      T Load<T>(Expression<Func<T, bool>> whereCondition);

      /// <summary>
      /// Mark entity to be deleted within the repository
      /// </summary>
      /// <param name="entity">The entity to delete</param>
      void Delete<T>(T entity);

      /// <summary>
      /// Add entity to the repository
      /// </summary>
      /// <param name="entity">the entity to add</param>
      /// <returns>The added entity</returns>
      void Add<T>(T entity);

      /// <summary>
      /// Updates entity within the the repository
      /// </summary>
      /// <param name="entity">the entity to update</param>
      /// <returns>The updates entity</returns>
      void Update<T>(T entity);

      /// <summary>
      /// Save all changes from repository to store
      /// </summary>
      /// <returns>Total number of objects affected</returns>
      int SaveChanges();

  }

Now we have our proper EFRepository.......

EFRepository implementation

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

public class EFRepository : IRepository, IDisposable
  {
      private ObjectContext _objectContext;

      private Type GetBaseType(Type type)
      {
          Type baseType = type.BaseType;
          if (baseType != null && baseType != typeof(EntityObject))
          {
              return GetBaseType(type.BaseType);
          }
          return type;
      }

      private bool HasBaseType(Type type, out Type baseType)
      {
          Type originalType = type.GetType();
          baseType = GetBaseType(type);
          return baseType != originalType;
      }

      public EFRepository(ObjectContext objectContext)
      {
          _objectContext = objectContext;
      }

      public ObjectContext ObjectContext
      {
          get
          {
              return _objectContext;
          }
      }

      public object GetRepositoryContext()
      {
          return this.ObjectContext;
      }

      public IQueryable<T> GetQuery<T>()
      {
          Type baseType;
          if (HasBaseType(typeof(T), out baseType))
          {
              return this.ObjectContext.CreateQuery<T>("[" + baseType.Name.ToString() + "]").OfType<T>();
          }
          else
          {
              return this.ObjectContext.CreateQuery<T>("[" + typeof(T).Name.ToString() + "]");
          }
      }

      public T Load<T>(Expression<Func<T, bool>> whereCondition)
      {
          return this.GetQuery<T>().Where(whereCondition).First();
      }

      public void Add<T>(T entity)
      {
          this.ObjectContext.AddObject(GetBaseType(typeof(T)).Name.ToString(), entity);      
      }

      public void Update<T>(T entity)
      {
          EntityObject entityObject = entity as EntityObject;
          ObjectContext objectContext = this.ObjectContext;
          objectContext.ApplyPropertyChanges(
              GetBaseType(typeof(T)).Name.ToString(),
              objectContext.GetObjectByKey(entityObject.EntityKey)
          );
      }

      public void Delete<T>(T entity)
      {
          this.ObjectContext.DeleteObject(entity);
      }

      public int SaveChanges()
      {
          return this.ObjectContext.SaveChanges();
      }

      public void Dispose()
      {
          if (_objectContext != null)
          {
              _objectContext.Dispose();
          }
      }

  }

Thursday, May 29, 2008 4:13:14 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Tuesday, May 20, 2008

FriendFeed is cool

http://friendfeed.com/kpatton contains a list of all my online activity, essentially blog posts, youtube, flickr and twitter stuff. Nice idea, although there seems to be a new social networking site every 5 minutes and i'm struggling to keep up!

Tuesday, May 20, 2008 7:07:04 AM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Wednesday, March 05, 2008

MOSS 2007 64 bit virtual development environment

Moss 2007 64 bit virtual development environment build documentation
Wednesday, March 05, 2008 3:56:41 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Thursday, February 28, 2008

Moss 2007 with SP1 together

Lots of people are obviously intending to install the office service pack 1 onto their Moss installations. However, what's the advice if you are (like me) creating a new multi-server moss farm and you want to ensure you rollout moss 2007 with SP1 applied?

Well, looking at the official documentation just didn't look like it was easily possible, and there was conflicting advice on the web around when to install SP1.

e.g. Configure your whole farm or just the SSP? Run the updates after the initial installation but don't run the config wizard? etc. etc.

This is until that is you realise that you can use the /Updates folder on the root of the Moss installation files, which is what the folder is for, to provision updates/patches.

So follow these five steps to Moss 2007 with SP1 install heaven:

1. Copy the contents of the MOSS 2007 CD to your hard drive (e.g. C:\MossWithSP1)

2. Download WSS 3.0 SP1 and Office 2007 SP1 (e.g C:\MossSp1)

3. Extract the contents to the Updates folder within your locally copied Moss installation by running the following at the command prompt: 

C:\MossSp1\Wssv3sp1-kb936988-x86-fullfile-en-us.exe /extract:c:\MossWithSP1
C:\MossSp1\Officeserver2007sp1-kb936984-x86-fullfile-en-us.exe /extract:c:\MossWithSP1

4. Use ImgBurn to burn the C:\MossWithSp1 back to an iso or to cd.

5. Use this disc on all future new Moss farms you build to avoid the need to upgrade to SP1

Now why on earth didn't Microsoft do this for new installations and make it available on MSDN!!??

Thursday, February 28, 2008 9:32:00 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, January 31, 2008

Moss 2007 Development Environment Setup - Update

DC with NAt mode best way to run a smoo 2007 development vm
Thursday, January 31, 2008 12:28:47 AM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, December 27, 2007

Managing and publishing media with Windows Live Photo Gallery

It's not often i gush about windows software, particularly considering how utterly vista has failed to capture the imagination of the ordinary user. Included with vista was the nice Windows Photo Gallery which was really an IPhoto equivalent built into the OS.

Now, Windows Live Photo Gallery (wikipedia: http://en.wikipedia.org/wiki/Windows_Live_Photo_Gallery, download: http://get.live.com/photogallery/overview) is available for XP and Vista users which is essentially an upgrade to this vista application with some lovely new features that i think should make it an essential download for any blogger or user who publishes images and videos to the web on a regular basis.

First off, the name, Windows Live Media Gallery anyone?

I think MS made a mistake in calling the application Windows Live Photo Gallery, instead it should be Windows Live Media Gallery because it handles the tagging, previewing, burning, playing and publishing of video content just as gracefully as photo media. I suspect this was to avoid confusion with the Windows Media Player application. Perhaps the whole interface should be merged who knows...

Importing Media

When you import photos and videos into Windows Live Photo Gallery you get very granular control over where the files go and crucially the auto-tagging of the files. In the base version of Windows Photo Gallery on vista, you could only tag in an all or nothing way for all imported files. So, getting stuff in and organising your import is a breeze.

Tagging and Publishing Media

Creating, organising and assigning media to tags is easy, with drag and drop support throughout. Best of all, tags are retained when publishing media. A new Publish menu item appears at the top of the main interface, allowing you to publish images to MSN Spaces AND Flickr. I highly recommend Flickr and it's great to see MS support a 3rd party service out of the box like this. Tagging is preserved when publishing to Flickr and Flickr has officially announced support for Windows Live Photo Gallery.

Unfortunately, the only thing that lets down the Publish option is that for video only MSN Video is supported, although i hope YouTube support will be forthcoming perhaps in a future release. MSN Video is fine and dandy and free, but i have all my videos at YouTube and really want to publish there with full tagging integration a la Flickr support. In the meantime, i simply utilise the YouTube multi file upload interface and manually re-assign tags not a biggy as i don't have as many videos as photos.

Windows Live Writer

Whatever blog you use, you should really use Windows Live Writer as an excellent editor for publishing to your blog. It will work with almos any blog out there and is easy to set up as long as you have your blog's home page url, username and password. I find it much nicer to write up blog posts rather than having to login to my blog website each time.

It is also a highly extensible little applicaiton and already has plugins such as a Flickr Plugin to support selecting one or more images from your Flickr stream.

You can also easily insert videos you have posted to YouTube, Google Video or MSN Video.

There is a site, Windows Live Writer plugins, where you can view even more useful plugins for this essential blogging tool.

Thursday, December 27, 2007 10:26:54 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, December 24, 2007

Alt TV Interactive Txt

Congrats to Andy, Teresa, Chris et al at Hyro NZ for getting this up and running. Despite many obstacles this is now a New Zealand first which i've been helping Andy get up and running for months. I think this'll take off once the other channels eye ball it and i wish the team all the very best of luck with this over the coming months.

Check it out on Sky Channel 65, txts only $0.99 each!

23122007057

Monday, December 24, 2007 12:00:47 AM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Saturday, December 22, 2007

Twitter stream now in operation

twitter.
Saturday, December 22, 2007 8:44:47 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, December 17, 2007

Fring is the Future

fringing awesome
Monday, December 17, 2007 12:22:37 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Tuesday, December 11, 2007

Nokia N95

new mobile phone/camera/video thingy
Tuesday, December 11, 2007 3:12:34 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Wednesday, October 31, 2007

AVJennings Website Goes Live

We've been working on this one for a while, finally goes live, http://www.avjennings.com.au. Built using www.kentico.com our favourite CMS.

Wednesday, October 31, 2007 9:02:03 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, September 13, 2007

Garmin Forerunner 305

Woohoo! My GPS wristwatch thingy has arrived. It measures distance, speed, elevation, heart rate, calorie count as you run. Even allows you to race against your previous runs and export the runs to google maps!

cf-lg

https://buy.garmin.com/shop/shop.do?pID=349 

Thursday, September 13, 2007 11:23:21 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Monday, August 20, 2007

Moving Offices

movin on up
Monday, August 20, 2007 8:29:18 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Saturday, August 11, 2007

MOSS 2007 Demonstration Machine Setup

MOSS 2007 Demonstration Machine Setup
Saturday, August 11, 2007 11:32:10 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, July 23, 2007
 Monday, July 16, 2007

Technorati Profile

Hi, Pointless little post to ensure my technorati profile gets set up ok.

 

 

Technorati Profile
Monday, July 16, 2007 7:52:52 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, July 13, 2007

MOSS 2007 Development Environment - Virtual Server Set Up

Take a deep breath, the complete guide to setting up a MOSS 2007 Development Virtual Machine
Friday, July 13, 2007 9:18:59 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Friday, June 29, 2007

MOSS 2007 Development - Virtual Server Set Up

MOSS 2007 Development Virtual Server Set Up
Friday, June 29, 2007 1:19:48 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, June 04, 2007

Geni Rocks

I just had to blog about a really great website i just found for building family trees called www.geni.com. It really is one of the most easy to use websites i've ever seen, have a try. It also doubles as a handy birthday reminder tool and you can store family photos etc.

Monday, June 04, 2007 8:36:12 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Friday, June 01, 2007

Steve and Bill Chinwag

Steve Jobs and Bill Gates in a very, very rare interview together.

http://d5.allthingsd.com/20070530/steve-jobs-and-bill-gates-together-part-1-of-7/

Friday, June 01, 2007 11:38:13 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, May 31, 2007

It's all about perception

working in software is so much fun;)

Thursday, May 31, 2007 10:06:32 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, May 13, 2007

Quero to the rescue!

I posted previously about the truly awful UI experience in IE7, particularly the fact that it is not customisable.

Well, glory be the wonderful free add on Quero makes IE 7 worth using again as it groups all the navigation options (back, forwards, refresh, stop and home) where they should be, next to each other!

There are also some other nifty features such as search highlighting, themes and the ability to put the main menu navigation back where it shoudl be, at the top of the window!

Sunday, May 13, 2007 9:26:00 AM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Wednesday, March 14, 2007

Vista Ultimate DreamScene

I just downloaded the latest updates for windows vista to find some lovely little videos you can setup as the background for your desktop environment.

DreamScene on my PC (2.5MB, MPG)
Wednesday, March 14, 2007 7:51:18 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, February 26, 2007

Firefox 2 Usability Trumps IE7

Now, let me state up front i am no LAMP or Firefox bigot. For better or worse i am an MS fan, already having converted my household to Vista and OneCare. However...having used IE7 since the early betas i'm afraid to say that Firefox is by far the most usable, quicker browser. Although my evidence is anecdotal (i work and consult with many other developers,project managers, business analysts who all for the most part corroborate my theory), IE 7 is confusing on a very basic level..

OK, i have a widescreen, so these screenshots look worse than on a normal monitor. But hey, wasn't Vista developed with widescreen in mind (sidebar gadgetry etc.)? Anyway, i've marked the key web navigation elements in red below. Note how in IE 7 the back and forward buttons are standalone, but if you want to Stop or Refresh the page you have to go to the right of the address bar. And if you want to go home, you have to go underneath to the tab level, mmm.

I won't even mention the fact that MS broke all previous design and decided to hide the menu navigation. OK, you can show it, but then it doesn't appear where you would expect it at the top, but strangely nestled between the address bar level and the tab level. It just looks well, awkward...

All this would be almost forgivable if like most MS applications you could tinker with the menus, but lo and behold for some strange reason you can't do diddly except hide and show things, the position of everything is fixed, damn!

IE7

 

Contrast this with Firefox, which places all the key navigation elements right next to each other, and logicall places the menu bar at the top were it belongs. You can drag stuff about levels and the whole experience (particularly on a widescreen) is so much more pleasant.

Firefox

Monday, February 26, 2007 10:40:08 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Wednesday, January 10, 2007

sky website - hunt the phone number

sky phone impossible
Wednesday, January 10, 2007 2:25:24 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [4]  |  Trackback
 Monday, January 08, 2007

spore - the best game ever?

new exciting game coming up
Monday, January 08, 2007 8:27:33 AM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, December 22, 2006

Annabel goes digital with the Nikon D200

new camera for annabel
Friday, December 22, 2006 9:13:56 AM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback

Telecom Broadband Loss of Synchronization Errors - Netgear DG834G solution

solution for broadband connection dropouts with telecom on netgear DG834G router.
Friday, December 22, 2006 9:00:34 AM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, December 08, 2006

new wii

wee wii
Friday, December 08, 2006 10:08:46 AM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Monday, October 30, 2006

My New PC 2006

good job i'm not into cars
Monday, October 30, 2006 1:13:20 AM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Wednesday, June 21, 2006

we are the champions

champions
Wednesday, June 21, 2006 5:51:18 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, June 02, 2006

user control libraries - interesting use of generics and proxy user controls with asp.net 2.0

user control libraries in asp.net 2.0
Friday, June 02, 2006 10:26:51 AM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Saturday, April 22, 2006

NHibernate transactions with .net 2.0 TransactionScope

using transactions with nhibernate
Saturday, April 22, 2006 2:49:24 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Saturday, March 18, 2006

accessing buttons in wizard stepnavigationtemplate and startnavigationtemplate areas

If you don't want to use a templated wizard step and have a custom navigation template using asp.net 2.0 wizard control, we've found a really quick way to get to the buttons inside the standard navigation templates to which you don't normally require programmatic access.

Namely:

Control container = wizUser.FindControl("StepNavigationTemplateContainerID") as Control;
Button btnSave = container.FindControl("btnSave") as Button;

StepNavigationTemplateContainerID is the magic string value that will get you a reference to your step navigation template.

Then you can use .FindControl to reference any control insite the wizard navigation template.

Have fun...

PS, CHRIS LAU IS DA MAN!

Saturday, March 18, 2006 3:06:24 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, January 16, 2006

get yourself ready for mBlog video over next few weeks

quicktime required for viewing mblog video
Monday, January 16, 2006 1:34:12 AM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Wednesday, November 16, 2005

branded gear website live

Here's one you can actually look at http://www.liongear.co.nz 

This is a site i've developed with the help of Mr Random (Chris Lau) that allows people in NZ to order all sorts of beer gear products from Lion Nathan. It's built off the code base for the 'award winning' online ordering site (www.lion.co.nz).

Have a play and feel free to buy stuff, i particularly like the Lion Red boxer shorts:

http://www.liongear.co.nz/Product.aspx?productID=190

Wednesday, November 16, 2005 10:18:07 AM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Friday, October 21, 2005

BLOGFLASH! ---- Award Winning Website!

we are the champions, my friend...
Friday, October 21, 2005 10:57:04 AM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Friday, September 16, 2005

online ordering project reaches nz award finals

Hoorah, my first big project at work has been shortlisted for the Tuanz e-vision awards, NZ's very own webbies! I designed and built the system so am very proud indeed...

http://www.tuanz.org.nz/tuanz/index.cfm?DE770585-E018-8BD1-32F6-D46DDBA21E3D

The project "online ordering" allows Lion Nathan customers to place their booze orders from across NZ and Australia. It's really cool and integrates with their internal accounts and inventory systems whilst retaining a simplicity and ease of use...blah blah blah.

www.lion.co.nz is the adress, but unfortunately it's a customer only site so you can only dream of the sublime functionality locked inside.

Fingers crossed, again! Results announced October 20th 2005.

Friday, September 16, 2005 12:34:51 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Wednesday, July 27, 2005

blank dvd media guide

blank dvd info
Wednesday, July 27, 2005 4:47:10 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Wednesday, July 13, 2005

irishman down under gaining in popularity

latest stats on the blog
Wednesday, July 13, 2005 11:11:48 AM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [1]  |  Trackback

msn messenger - clean and simple

remove the bits you can't normally reach from MSN
Wednesday, July 13, 2005 9:32:58 AM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Saturday, June 18, 2005

NHibernate Utility - Session Factory, Transaction and Http Module Utility

NHibernate Utility code
Saturday, June 18, 2005 12:01:11 AM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Saturday, June 04, 2005

Using dtSearch to index/crawl MCMS (Microsoft Content Management Server 2002) resources

Using dtSearch to crawl MCMS resources
Saturday, June 04, 2005 12:32:28 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Saturday, May 07, 2005

installing tiger on old imacs

target disk mode to install dvd content onto dvdless macs
Saturday, May 07, 2005 10:49:23 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [1]  |  Trackback

Spacemonger

visualise hard drive usage
Saturday, May 07, 2005 10:42:33 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, April 17, 2005

NHibernate - wot no database code?

object to database with little in between
Sunday, April 17, 2005 9:52:21 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Tuesday, March 01, 2005

image button groups

no more explicit event registration for image button rollovers, just add code snippet and fly!
Tuesday, March 01, 2005 4:33:14 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [1]  |  Trackback

Multiple event handler functions for javascript events

Ability to add multiple event handler functions for a single javascript event
Tuesday, March 01, 2005 12:20:43 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [3]  |  Trackback
 Thursday, February 24, 2005

upgraded blogging software

das blog 1.7
Thursday, February 24, 2005 9:33:04 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Wednesday, December 01, 2004

dvd collection online

what a sad geek!
Wednesday, December 01, 2004 7:14:00 PM (New Zealand Daylight Time, UTC+13:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Friday, September 24, 2004

New site for the blind in UK

RNIB Website goes live
Friday, September 24, 2004 7:32:06 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Saturday, September 11, 2004

html tables as master design grids - the parts css can't yet touch

heresy as a list of things css can't do or can't do easily is discussed
Saturday, September 11, 2004 2:02:05 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, September 10, 2004

Disability organisations fail to meet challenge on accessibility

Disability 50 Report from March 2004
Friday, September 10, 2004 1:44:23 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, September 09, 2004

CSS – Page layout and naming conventions

a stab at working towards conventions for designing with and using css layout
Thursday, September 09, 2004 12:40:28 AM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, June 18, 2004

Setting up dasBlog 1.6 blogging software

A guide to setting up dasBlog
Friday, June 18, 2004 1:42:38 AM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback

Write once, display everywhere - the making of an xml cv

Dynamic pdf generation Using XML, XSLT, XSL-FO and NFop.
Friday, June 18, 2004 12:44:12 AM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback