# Thursday, June 17, 2010

Use SQL Server Trusted Connections with ASP.NET on Windows 2003 without impersonation

Access control and troubleshooting 401 errors must be one of the most annoying and recurring issues with configuring IIS.  One of the problems is that it's often quite a long time between issues, and you simply forget how you solved something last time.  This time I decided to write it all down as I set things up.

Target Scenario
My target scenario is a local intranet, where you want to use a 'service account' to access SQL Server, directly from your 'trusted' web application, removing the need for impersonation. 

The benefits of this are of course that you can take advantage of connection pooling, but also removing the need to configure passwords in web.config for SQL users (or specific, impersonated domain users).  This also removed the overhead of configuring specific domain users and their SQL Server permissions.  It may also be that you just want to simplify your security model to work only on Windows authentication across the stack.  

SQL Server
  1. Create a new role in the database you're accessing, for the purposes of your application
  2. Add your service domain user account to the role in SQL Server
  3. Assign permissions to objects, stored procedures etc to the role (not directly to the user)
IIS/Web Site
  1. Set up your web site/application as you would normally - one way to do things....
    1. Create your web application root folder on the web server
    2. Copy your files (or use your deployment tools/scripts to do this)
    3. Create a new application pool to house your new web application (probably model this from the default web site).  This is important as this is where the credentials will be set
    4. Create the new IIS web application against the root folder (if not already done as part of step 2)
    5. Associate the new IIS application with the new application pool
    6. Set the ASP.NET version of your IIS application appropriate (may need to restart IIS here)
  2. Ensure 'Integrated Security' is set ON in the Directory Security tab, and 'Anonymous' access is switched OFF
  3. Set the application pool's 'identity' to the domain user you want to run the application (and connect to SQL Server) as
  4. Open a command window and Go to the windows\Microsoft.NET\Framework\vXXXXX folder
    1. run aspnet_regiis -ga <domain>\<user> to grant necessary access to the metabase etc for the service account (as per http://msdn.microsoft.com/en-us/library/ff647396.aspx#paght000008_step3 )
    2. In the command window go to the inetpub\adminscripts folder, and set NTAuthenticationHeaders metabase property as per instructions at http://support.microsoft.com/kb/326985.  you can also use MetaEdit from the IIS Resource Kit to change this.  If you're fully configured to use Kerberos then you can potentially skip this step, as it's all about making IIS use NTLM authentication.
  5. Navigate to 'Web Service Extensions' in IIS Manager, and ensure that the ASP.NET version you're targeting is 'allowed'.  e.g. ASP.NET 4.0 is 'prohibited' by default.
Summary
So here we've circumvented the need to use impersonation by running the ASP.NET application as a specific domain user that is configured as a SQL Server Login, and granted the right access by means of a SQL Server role.  The main work is the plumbing to get IIS to work happily with that user in standard NTLM authentication (you may be able to use Kerberos depending on your network configuration).

Other background on creating service accounts can be found at http://msdn.microsoft.com/en-us/library/ms998297.aspx

posted on Thursday, June 17, 2010 11:15:53 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
# Thursday, March 04, 2010

Web Visitors vs Users, Impatient vs Bored and how they affect Website Change Management

Why are users on your site?
  • To look around?
  • To do or achieve something?
I pondered this question after reading Gerry McGovern's discussion on Impatient vs Bored.  He suggests that people using (or rather choosing 'not' to use) websites are actually more likely to be impatient than just bored with your content.


I think we need to explore the different types of sites and people visiting them to understand this a bit more.

Different types of sites

IT people have traditionally used the rather woolly terms of Web Site and Web Application to differentiate between something simple and something more sophisticated.  There’s no official classification here.  There’s usually some characteristics that point more to one than the other.

Characteristics of a Web Application

  • Dynamic content.  This could be driven from a database or external source
  • User interaction.  Users can register/update information, upload, download.  They can ‘do’ useful things on the site.
  • Commerce.  Users can buy things

Users and Visitors

People accessing the web can also be classified.
 
You could say that a visitor is
"someone who has a passing interest in your site, looking to find some information or browsing around for comparison purposes." 
A user is
"someone with a longer term association or affiliation who potentially logs into the site, or gains knowledge of the structure and becomes expert in achieving their tasks." 
It’s reasonable to assume that users are subset of visitors.  Visitors and users will also access both types of sites. This means that whether someone is a visitor or a user depends on the specific context of their goal at the time of access, and their past history on the site.  (phew - almost drew a venn diagram there!).

Impatient and Bored

Impatience is something more likely to be experienced by a user who’s trying to complete a meaningful task – i.e. they have a certain expectation of how a site will work and perform.  Casual browsers are more likely to switch off from the site if they don’t like what they see.
If you want a huge generalisation then:
“Users with an affiliation to a site (web application) are likely to become impatient if their progress is impeded, and casual visitors to a site (web application or content site) are more likely to become bored if the content is not engaging or visually appealing.”

Underlying Factors

There’s a couple of factors that underpin all types of web access:
  • Information Architecture (IA) – the structure of the information, sections and pages on the site.
  • Usability – the ease with which people can achieve their goals on the site.
IA is equally important to simple and sophisticated sites, as a visitor to a company brochure site needs to know that they can get around speedily and find what they’re looking for without undue delay.  Bad IA on a larger site is likely to grate with users over time and people will find themselves frustrated because their navigation around the site isn’t logical.

A good and logical IA is often a matter of being consistent with de facto standards.  For example many web users now have subconscious expectactions that company sites have ‘Contact Us’, ‘About Us’ etc.  Going against the grain here leads to impatience.

Usability is the detail in every interaction.  The sections and pages on the site may be completely logical, but if the developers have produced a whizz-bang Flash product catalogue widget that takes over a minute to load, then you’ll be getting some impatient users.  The effect will be similar if the flow of a page or workflow tries to go against simple and accepted interface design principles.  This could include using non-standard form elements on a page, or collecting information in a strange order just because it suits a back-end system (but not the user).

Functionality vs Visual Design

For the most part, functionality wins over visual eye candy with users.  Business users routinely put up with desktop applications that do what they need without swooping curves, dripping in glass buttons and subtle gradients.  There is however a growing expectation of a minimum level of visual design on the web.  Maybe this  makes up for the fact that sites still rarely deliver everything a user wants.

The Pressure to Redesign

Creative agencies will often suggest a site’s poor performance is down to the visual design not being up to scratch – as they want to perform that job.  This takes advantage of the (still) general lack of understanding about the web amongst company decision-makers. This surprisingly includes a lot of marketing departments who still only think 'print'. 

The other extreme is marketers on a constant rebranding trip, constantly quoting ‘market risks’, effectively keeping themselves gainfully employed.

The model of development on the web over the years has been largely evolutionary, with change coming without warning, and largely without consultation with users.  This was OK in previous times (I refuse to say web 1.0), when user expectations were low, and the level of engagement with any one site was also low.  This is still true for many small sites.

The price of Success

With community sites becoming more mainstream and popular, companies now often elicit feedback to work out where to go next.  Sometimes when big changes are made (Facebook) with little or no communication, things can get a little heated with petitions and protests galore.
 
Just imagine if Microsoft significantly changed the interface to Word on the millions of computers around the world without notice.  It just wouldn’t happen! 

Sites like Facebook have learned the hard way that success on the web also breeds greater responsibility to change with regards to your users.  Users of free services can simply vote with their feet, and increasingly do.  Facebook has flooded the social web space and so hangs on to many users as they’ve become the de facto standard. 

Very few sites can rely on such a situation.

Managing Change

So how can you manage change on websites?  When do you need a lick of paint, and when do you need a complete redesign?

The following isn’t an exhaustive list, but gives some thoughts on some tools and approaches to consider.

Understand your user base.

Use web stats tools like Google Analytics to understand where your users come from and where they go on the site.  Set up goals to see how successful things like your payment workflow is – i.e. what percentage of people add something to a cart, and subsequently complete the transaction?

Analyse the paths into your site so see if there’s any opportunities for SEO improvement, like better keywording, extra landing pages etc.

Make the right changes

Sometimes it’s appropriate to do some field research to work out the right changes to make on the site.  This could be from a variety of sources.  The key is to remain light-footed throughout the process so you can react to changes as they (inevitably) occur:
  • Business Requirements.  This is typically what drives most change, but internal people are not the only people in the equation.  They don’t use the site the way external users do.
  • Usability testing with the current site and a group of users can be quite revealing to find gaps that explain poorly performing site areas, and also give rise to new ideas.
  • User surveys can be effective, but asking questions of users needs to be offered sparingly, and in an optional way.  Keep things small and succinct to get the best return of ‘take home’ points.  Consider offering some reward for completing the survey.

Design it right and Try before you Buy

In order to react to change, and feedback you need to get people looking at your intended changes as quickly as possible.  The following is an example of an iterative approach from detailed design to implementation for a complex change that will affect a large number of users:

WireFrame

Wireframe development is a great place to start by designing layout and visualising key elements and interactions on the site.  This is specifically tackled before any detailed visual design to test the concepts with business people and prospective users.

Prototype

This can be created from the wireframes to put some more meat around the concept built in the wireframes.  This could be as simple as page images with hyperlinks to allow clicking through the flow, to a slim ‘actual’ prototype in place on the site.  You’d typically build a ‘proper’ prototype if you’ve got some technical risk to overcome – e.g. proving a technical solution is possible for a given situation.  Some tools like Axure exist to facilitate wireframes and prototypes in one. 

Prototype testing

This is then performed either with a control group of users, and or with business users to assess the viability of the solution and also to get valuable feedback and other ideas. 

The wireframes and prototype would then be updated again with further rounds of testing as required to get to a point where things are formalised enough to start development. 

Visual design may also creep into this area, as some people simply can’t say ‘yes’ until they see ‘exactly’ how something’s going to look, but try and limit this.  This is where you hope for a programmer who’s design-savvy. 

This phase ends with the wireframes being signed off by the business.

Visual design

This will no doubt continue to evolve as it's the tangible stuff that businesses can 'feel', but should be tied down as early as possible.  The business should sign off completed mockups (e.g. from Photoshop), based on the approved wireframes.

Completing the Job

The rest of the job is standard develop/test/implement etc, but developing small chunks and testing early, and implementing often is always a good way to go.

If the original prototype  was actually ‘functional’, then you might be able to go fairly quickly to some internal or public A:B testing and with a bit of work you could find yourself finished. 

Whether you’re catering more for visitors or users, the first step to any change is putting yourself in their shoes.



posted on Thursday, March 04, 2010 2:13:32 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Comments [0]
# Monday, June 15, 2009

Using JQuery with DotNetNuke 4.x

I'm currently doing a project using DotNetNuke, and we're using JQuery plugins to achieve certain content rotation and scroller functionality.  All was 'amost' good as I'd found a way to inject the JQuery script to the page header on a per-skin basis, but in 'edit' mode the actions button wasn't showing up at the top of containers in FireFox and was causing JavaScript errors in IE.

I'd already gone through the hoops of declaring jQuery.noConflict(), but it still appeared to be conflicting with the dnn:actions (solpartactions) control.  I'd read somewhere else about Solpart code being incompatible with JQuery.

I tried one last thing, adding the noConflict() call in the JQuery library script file itself - rather than running as a fragment on page load.  This fixed everything, as something else was obviously getting in and hijacking in the meantime.  Apparently with V5 this will all be fixed as JQuery's more integrated with the framework.  Anyway, for those interested here's what I had to do to get JQuery (and associated plugins) talking nicely whilst still allowing the actions menu to pop up on my containers...

  1. Amend the JQuery library (jquery.1.x.x.min.js) by adding the following line at the bottom...

    jQuery.noConflict();

  2. Amend the skin you want to load the jquery library (and plugins) in (we've got it only in specific skins to avoid the overhead where it's not required).  You could also do this in the module by checking 'if loaded', but here's the code for a skin (in ascx file)...

    <script runat="server">
        Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
            'add a script reference for Javascript to the head section
            AddScript("/js/jquery.scrollable-1.0.2.min.js")
            AddScript("/js/jquery.mousewheel.js")
            AddScript("/js/jquery-1.3.2.min.js")
        End Sub
       
        Private Sub AddScript(ByVal fileName As String)
            Dim oLink As New HtmlGenericControl("script")
            oLink.Attributes("language") = "javascript"
            oLink.Attributes("type") = "text/javascript"
            oLink.Attributes("src") = fileName
            Dim oCSS As Control = Me.Page.FindControl("CSS")
            If Not oCSS Is Nothing Then
                oCSS.Controls.AddAt(0, oLink)
            End If
        End Sub
    </script>


    The order is important, as we're adding the scripts to the 'top' of the scripts each time.  JQuery needs to be the first referenced.
  3. Make sure that anywhere you use jQuery you use the jQuery(xx) syntax, and not $(xx).
That's it.

posted on Monday, June 15, 2009 3:41:01 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
# Tuesday, April 28, 2009

ASPNETCOMPILER The Target Directory could not be deleted. Please delete it manually or choose a different target - SubVersion

I'd added some projects to SubVersion today and later on added a CruiseControl.NET build.  I then started getting build failures due to the following:

ASPNETCOMPILER The Target Directory could not be deleted. Please delete it manually, or choose a different target

After a bit of looking around with the SysInternals Process Monitor I couldn't find anything weird (e.g access denied due to someone locking the folder) and then saw that my output folder from the project (ASP.NET Web Deployment Project) was under SubVersion control (below)



Whoops! - after a swift delete of the folder (also in SubVersion) normality was resumed.  That's another good reason not to put binaries into source control!
posted on Tuesday, April 28, 2009 9:24:03 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]
# Wednesday, April 08, 2009

10 Essential Checks before releasing a Web Site

More goodness from Smashing Magazine

This is all fairly well known stuff, but it's amazinf how often I've seen sites go live without 'most' of these.  Now of course every website's different, but this is a great list for reference and for learning.

posted on Wednesday, April 08, 2009 8:02:57 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
# Monday, March 16, 2009

ASP.NET Data Binding - Accessing a parent data item from within a nested repeater

I'm maintaining an app at the moment that uses quite a few nested repeaters, and found that headers were being output when there was no data present.  It was found that the header was being written in the ItemTemplate of an 'outer' repeater, rather than as the HeaderTemplate of the 'inner' repeater.  The next problem was how to reference the outer repeater from the 'inner' HeaderTemplate...

The following will bind to a field called HeaderDescription.

<%# DataBinder.Eval(Container.Parent.Parent, "DataItem.HeaderDescription") %>

The parent of the inner item is it's repeater, so you have to go to it's parent to get the right RepeaterItem.  Why don't you just do the following you ask?

<%# DataBinder.Eval(Container.Parent.Parent.DataItem, "HeaderDescription") %>

..'cos it doesn't work - The Eval method expects a 'Control' as its first parameter.  There's other ways to do this server-side, but the first option is probably the easiest.

To complete the picture and only show when there's data you can add the following to the 'inner' repeater declaration

OnItemDataBound="ItemDataBound" Visible="false"

then..

        protected void ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Item)
            {
                if (!e.Item.Parent.Visible)
                    e.Item.Parent.Visible = true;
            }

        }


This will ensure that you'll only show if you've bound a 'data' item (remember you're doing binding in the HeaderTemplate too).  You could also hook similar things into other events, but it's generally more convenient to put these things into events that relate to the actual control (pre_render's probably another good candidate as it will only get called once and you can check the count in the DataSource).


Technorati Profile
posted on Monday, March 16, 2009 10:28:27 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Comments [0]
# Thursday, February 05, 2009

Make JQuery and Prototpye coexist and play together with a GreaseMonkey User Script

I've been playing with Greasemonkey scripts recently - for Redbubble.com, and wanted to use JQuery with GreaseMonkey.  This is pretty well documented, but I discovered an incompatibility with my script and the host site, as it uses the Prototype Javascript library (must admit I didn't know much about it).

Prototype (like JQuery) uses the $ notation, and so by default any GreaseMonkey User Script loaded will hijack the $ object, meaning that stuff on the original site may stop working.

I thought I was sunk but it turns out JQuery just gets better, and it can gracefully give back control of the $ to whichever library originally loaded it.  Just call..

jQuery.noConflict();

You then have to use jQuery instead of $ (e.g. jQuery("#myID") instead of $("#myID") ), but hey - that's a small price to pay when the alternative is rewriting the whole thing long-hand.

posted on Thursday, February 05, 2009 9:14:44 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Comments [0]
# Thursday, December 04, 2008

Removing the scrollbar Page Shift from Firefox

This had bugged me for a while.  A lot of sites (including some of the ones I develop) tend to have a fixed width layout these days and some browsers (IE particularly) 'always' has a visible scrollbar.  This means that the available screen width is constant whether the page scrolls or not. 

Firefox on the other hand (and Chrome/Opera/Safari) seem to have this off by default.  This of course seems reasonable until you have a fixed width, centred layout that 'shifts' when you switch from a non-scrolling to a scrolling page.  It's just a bit off-putting.

Fortunately Firefox is configurable and the following will fix that up for you. (I'm sure the other browsers are capable of something similar but I'm not using them much :) )

  1. Find your profile directory (it's bound to be the 'default' one unless you're developing Firefox addons.  You'll normally find it in c:\documents and settings\username\application data\Mozilla\Profiles\xxxxx.default\
  2. Go to the 'chrome' subfolder and create a file called userContent.css (you'll probably find there's a couple of 'example' files there already.
  3. Add the following (Firefox-specfic) line to the file:

    html { overflow: -moz-scrollbars-vertical !important; }

  4. Save the file, exit Firefox and start her up again.  You should now have a permanent scrollbar which eliminates the page shift. 

posted on Thursday, December 04, 2008 10:51:55 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Comments [0]
# Thursday, November 20, 2008

Removing references to HttpModules from ASP.NET SubFolders in web.config

If you have ASP.NET applications that live as subfolders of a larger site, you may find yourself with issues when it tries to find assemblies and httpmodules that are referenced in the parent's web.config.

Fortunately this is something you can work around.  Matthew Nolton goes through how you 'remove' these references at the subfolder level using the <remove> element.

This is all fine until you get an even tastier situation like I encountered the other day...

ASP.NET application 'A' lives as subfolder 'B' of both parent site 'C' and 'D'.  The configuration of 'C' and 'D' is slightly different (modules, handlers, assemblies etc).  Why is this a problem you ask?  We were trying to be a bit clever (and failed :) ) by only deploying application 'A' once.  Virtual directories in site 'C' and 'D' both point to the same physical 'A' folder.  This effectively means that the stuff that needs to be removed from 'A' varies depending on which parent site you're accessing.

OK - I could just fix this by duplicating the installation, and varying the configuration but....

You can also remove all modules by adding a 'clear' element as follows...

<httpModules>
     <clear/>
</httpModules>


This is fine, BUT if you're using Session State or any other in-built features that are implemented as httpModules then you'll get exceptions as ASP.NET will give you a 'null' session for instance.

The following is probably a safe list of modules you'd normally need (maybe even only the session for simple apps), so just add them back in after the 'clear'....

<httpModules>
     <clear/>
     <add name="OutputCache" type="System.Web.Caching.OutputCacheModule"/>
     <add name="Session" type="System.Web.SessionState.SessionStateModule"/>
     <add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule"/>
     <add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule"/>
</httpModules>


This is nicer for a couple of reasons
  1. It shows what dependencies the application has on ASP.NET/external features, and...
  2. It gives you the power back to have the application consumed by multiple sites as you've effectively decoupled yourself from the parent's dependencies.

posted on Thursday, November 20, 2008 3:07:59 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Comments [0]

Minify your Javascript using JSMin to minimise client downloads

This isn't a new thing, but I just came across a C# console app class, ported from JSMin to help with 'minifying' (or uglifying) your Javascript.  You can find it here.

Just create a new C# console app, pass in the 'input file' and 'output file' and away you go...

posted on Thursday, November 20, 2008 11:16:10 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Comments [0]
# Thursday, October 09, 2008

Serving SSL from localhost on IIS 5 on Windows XP using Self-Signed certificates

I've probably glossed past this a few times, but it turns out getting SSL working on your dev machine is less painful than you'd think...

  1. install iis60rkt.exe from http://www.microsoft.com/downloads/details.aspx?FamilyID=56fc92ee-a71a-4c73-b628-ade629c89499&DisplayLang=en on your local machine. It's intended for IIS 6.0 but it works in IIS 5.1.
  2. Select custom install if you only want to use SelfSSL. Otherwise, install all.There's a lot of other useful stuff there.
  3. Select Programs --> IIS Resources --> SelfSSL --> SelfSSL command prompt
  4. In the command prompt, you'll see a list of all possible command parameters..
    1. Type 'selfssl.exe /V:60'     This indicates the certificate is valid for 60 days
    2. Type Y to answer the question "Do you want to replace the SSL settings for site 1 (default website) ?
    3. Type 'iisreset' to restart IIS.
If your browser prompts something like 'Certification Authority not recognised' (in Firefox), just put the url in the exception list or override the warnings when viewing the page.

Thanks to Ricky for getting this info together.

posted on Thursday, October 09, 2008 9:56:33 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Comments [0]
# Monday, September 29, 2008

More reasons to love JQuery

I've only recently started using JQuery, but needless to say - it rocks!

for those that don't know it's a Javascript library that's basically revolutionising how you write client-side code.  My reasons to love JQuery.

  1. It's open source, well tested and an open design.  This means you write less code and you can rely on functionality just 'working' in different browsers - or gracefully failing if something's not right.
  2. It's really light (especially when 'packed' - 31kb)
  3. It's got a strong community with lots of really cool plugins (just take a look before you start developing that 'widget' in flash)
  4. It plays well with other libraries and code.  you just use it for what you need and plugins sit with other plugins.
  5. It's obviously gaining momentum, as Scott Hansleman announced Microsoft are going to ship it with ASP.NET MVC and Visual Studio (that's a pretty amazing move from Microsoft).
If you're just getting started with it, and you're familiar with Javascript already I'd start with the tutorials.  Some are better than others, but run through the first couple to understand how it works, then scan down the list to find something related to what you need to do.  Typically you'll be wanting to write a plugin, so I found this one quite good for starters.

You should find everything you need in the Documentation

you'll then spend most of your time in the API section, looking for specifics on how to do things. 

posted on Monday, September 29, 2008 11:21:34 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
# Monday, September 15, 2008

Using CSS Frameworks to do the heavy layout lifting

CSS is great, until you're faced with a deadline and a broken IE6 layout.  You get the cowboy gear out and - 'Welcome to Hacksville!'  

There's been a growing trend of CSS frameworks recently as people are obviously crying out for 'something' to save them from the madness. 

I'm trying out the 960 grid system at the moment, as it's not too prescriptive and gives me the flexibility I need.

There's a great review of the best frameworks on adactio.  I'm sure there's one to suit almost every need.  Remember they're just the starting point if you're doing serious design, but they'll take most of the pain away, because the heavy 'hack' lifting is done for you...   

Also - more on Wikipedia (Update: 17/09) - BlueTrip's the way to go - best of several worlds - nice.

posted on Monday, September 15, 2008 8:30:41 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
# Monday, July 28, 2008

Favicon Browser Support Chart. How different browsers support the Favourites Icon

At last I've found a good reference on which browsers support which types of icons/png's etc for the Favicon.  I guess the news is that you need more than one approach if you're wanting to serve a favicon to the most potential users.

posted on Monday, July 28, 2008 9:16:08 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
# Wednesday, July 09, 2008

Who needs Internet Explorer when you can use it in Firefox?

I love Firefox and its addons, although I still habitually use Internet Explorer.  IE6 at work (which always provides some nice CSS challenges!) and IE7 at home.

I'm a bit slow off the mark with using firefox, but the latest addon that someone sent me yesterday may have tipped the balance.

The IE Tab addon actually uses the IE rendering engine to render in a new tab in Firefox.  It's quite amusing when you right-click and get the IE context menu.

The really great thing about this is that you can then use the power of the other Firefox addons to develop for IE.  Here's my list of 'must haves'.

  • Firebug.  This is quite simply the best addon.  Hit F12 and you can instantly see (and manipulate) all sorts of things in the comfort of your own browser.
  • YSlow.  Great Javascript profiler
  • FireCookie. See and change your cookies (for development purposes of course! - Good to test the security of your apps)
  • Web Developer.  Bit of overlap with Firebug but some cool features.

The IE Developer Toolbar is still a pretty good tool, but Firebug just gives you more info when you're debugging CSS (which is inevitable with IE).

 

posted on Wednesday, July 09, 2008 12:24:40 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
# Friday, June 13, 2008

Installing Multiple versions of Internet Explorer with Multiple_IE

I don't have the time, inclination or grunty machines to play around with Virtual machines just so I can test a website in IE6 (after IE7 'magically' appeared).  When I say 'test', I actually mean hack an IE-specific CSS together with some box-model workarounds.  I digress...

Enter Multiple_IE.  It's not perfect (it's a hack in itself), but it suffices in most cases so kudos for that...  You even get the nostalgia of IE3

posted on Friday, June 13, 2008 2:17:00 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
# Wednesday, June 04, 2008

When is XHTML not XHTML?

Well you may think it's just a matter of rendering some well-formed markup and setting your doctype...

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

right?  Wrong!

Different browsers render in different ways.  What's common however is that unless your response's content type is "application/xhtml+xml" then you may not pass go and pick up $200.  You can force the browser to recognise the content type in two ways (in addition to the DOCTYPE declaration above):

  1. Name your file with an .xhtml extension (not really a solution as IE says 'what?')
  2. Set Response.ContentType = "application/xhtml+xml" (See here for more info)

The DOCTYPE is really an additional information item and not something modern browsers do much with on its own.  So how different are the browsers'  XHTML implementations?

Internet Explorer for instance takes the 'all comers' approach and will do the best it can given the markup, whilst degrading gracefully if it encounters errors.  great! I hear you say - saves me from actually testing this thing!

Firefox on the other hand will use a completely different parser once it knows you want to serve well-formed markup.  The good thing about this is that you immediately see any errors and the page won't render if there's invalid markup.  IE meanwhile continues to let you believe you're an XHTML master (note: it doesn't recognise the xhtml extension).

Firefox has some good resources about supported features.  A common one that catches people out is Javascript's document.write.  This isn't allowed in XHTML as the string input can't be guaranteed to be valid XML. 

Safari's not quite as advanced yet as Firefox's support, but it too will properly validate your markup and report errors.

If you really want to stick your neck out then place a link on your site to validate against the W3C's standards.  You're likely to get plenty of errors - like this page!

Other things to watch out for are Content Management systems that allow you to enter non-compliant html in text editors, and simply not having JavaScript blocks in CDATA sections).

 

posted on Wednesday, June 04, 2008 10:43:12 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
# Wednesday, April 02, 2008

The best gmail Google Gadget

When I say 'best' - I mean one that allows you to use gmail where you'd otherwise be blocked.  This does everything within the one window rather than opening up gmail (and alerting the company web police).  This requires a bit of real estate so you might want to create another iGoogle tab with one column.

I can probably uninstall Gmail lite from my home box now...

Here it is

 

posted on Wednesday, April 02, 2008 1:40:55 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Comments [1]
# Thursday, March 13, 2008

ASP.NET Extender Control for Expiring Content

I recently had a specific requirement to 'expire' some content on a web site.  There's a million ways to do this, but my previous use of ExtenderControl in Windows Forms development sparked my interest when I noticed the Ajax toolkit supports this (mainly for client-side functionality). 

After downloading System.Web.Extensions, and about half an hour later I'd got the 'ExpiringExtender' Control that can be added to your ASP.NET (2.0+) page to allow content to phase in or out. 

The only down side to this approach is that your source code becomes littered with expired code like the Earth's orbit does with old satellites!  This was therefore a quick solution to a specific problem - not an approach I'd advocate if this is a core requirement (you need a good Content Management System with built-in scheduling).

Anyway - here's the class (chuck it into your App_Code folder if you're using a Web Site project - as in my example).  The code's pretty simple - just set a couple of properties (defaulting to min and max dates if not supplied) and the control's visible property gets set appropriately.

using System;
using 
System.Web;
using 
System.Web.UI;
using 
System.Web.UI.WebControls;


namespace 
CodeBureau.WebControls
{


    
/// <summary>
    /// This control works as a simple Extender to any server or html control to allow crude time-based 
    /// show-hide functionality.  NOTE This requires the Ajax Toolkit.
    /// </summary>
    
[TargetControlType(typeof(Control))]
    
public class ExpiringExtender : ExtenderControl
    {

        
#region Private Attributes

        
private DateTime showFrom DateTime.MinValue;
        private 
DateTime showTo DateTime.MaxValue;

        #endregion

        #region
 Public Attributes

        
/// <summary>
        /// Gets or sets the show from date.  This indicates that the control should be visible from this date/time
        /// </summary>
        /// <value>The show from.</value>
        
public DateTime ShowFrom
        {
            
get return this.showFrom}
            
set this.showFrom = value; }
        }

        
/// <summary>
        /// Gets or sets the show to date.  This indicates that the control should be visible to this date/time
        /// </summary>
        /// <value>The show to.</value>
        
public DateTime ShowTo
        {
            
get return this.showTo}
            
set this.showTo = value; }
        }

        
#endregion

        #region
 Event Handlers

        
/// <summary>
        /// Raises the <see cref="E:PreRender"/> event.
        /// </summary>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        
protected override void OnPreRender(EventArgs e)
        {
            
base.OnPreRender(e);

            
Control control FindControl(this.Page, this.TargetControlID);
            if 
(control != null)
            {
                DateTime now 
DateTime.Now;
                if 
(now < showFrom || now > showTo)
                {
                    control.Visible 
= false;
                
}
            }

        }

        
#endregion        

        
/// <summary>
        /// Gets the script descriptors.
        /// </summary>
        /// <param name="targetControl">The target control.</param>
        /// <returns></returns>
        
protected override System.Collections.Generic.IEnumerable<ScriptDescriptor> GetScriptDescriptors(Control targetControl)
        {
            
return null;
        
}

        
/// <summary>
        /// Gets the script references.
        /// </summary>
        /// <returns></returns>
        
protected override System.Collections.Generic.IEnumerable<ScriptReference> GetScriptReferences()
        {
            
return null;
        
}

        
/// <summary>
        /// Finds the given control (recursively).
        /// </summary>
        /// <param name="parent">The parent.</param>
        /// <param name="id">The id.</param>
        /// <returns>the control if found (else null)</returns>
        
private Control FindControl(Control parent, string id)
        {
            Control recurse
;
            if 
(parent.ID == id)
            {
                
return parent;
            
}

            
foreach (Control child in parent.Controls)
            {
                recurse 
FindControl(child, id);
                if 
(recurse != null)
                {
                    
return recurse;
                
}
            }
            
return null;
        
}

    }

}


Colorized by: CarlosAg.CodeColorizer

And to use it in a page (I've got it within a master page here) you just add the registration for the extender control (note the Assembly="App_Code" - I had to google for a while to find that.

You also have to add the ScriptManager control (an Ajax requirement), then just make sure the content you want to phase in or out has runat="server" (it should work for HTML or Server controls).

<%@ Register Assembly="App_Code" Namespace="Coles.WebControls"  TagPrefix="uc1" %>


<asp:Content ID="Content2" ContentPlaceHolderID="body" Runat="Server">
<asp:ScriptManager id="ScriptManager1" runat="server"></asp:ScriptManager>
    
<uc1:ExpiringExtender runat="server" ID="a" TargetControlID="header" ShowTo="13 March 2008 16:15:00"></uc1:ExpiringExtender>

<h1 id="header" runat="server">Hey - I turn into a pumpkin at 4:15...</h1>

Colorized by: CarlosAg.CodeColorizer
posted on Thursday, March 13, 2008 5:04:26 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Comments [0]
# Saturday, March 08, 2008

ASP.NET Open Source Content Management Systems

I'm producing a site for a client at the moment, and it quickly became apparent that I'd have a number requirements that would lead me down the CMS path:

  1. Client makes direct updates to the site (with approval/preview possibilities if possible)
  2. Built-in membership, security, roles etc (why write this yourself? - I've got 2 kids and just don't have the time or inclination!)
  3. Skinning capability (OK ASP.NET gives you that 'kindof' for free - but I throw it in anyway)
  4. CSS-driven layout (rather than tables) - This is a technical requirement for me rather than the client, but I want to make the site accessible and SEO-friendly
  5. Capability to customise  and add generic hooks to other office-based systems
  6. Quick time to market (building all the above from scratch would be 'fun' I'm sure, but would also take time)

To be fair to the customer I couldn't really suggest that I do everything from scratch when there's plenty of open source and commercial CMS's that can do the job very well. 

I do .NET - so I'm sure there's plenty of great CMS's for other platforms, but I'm not about to use this as a re-skilling exercise, charging a customer for the pleasure (as I need to do some more 'significant' development around the site, so will be using .NET for that).

What follows is a personal view based on my requirements and my experience (rather than extensive research into each product).

DotNetNuke

This was the first one I considered as I'd had dealings with it a few years ago (a dev 'community' site at a previous employer).  After playing with just about every module on the planet at the time ('cos you do), we realised we just needed a blog, so converted to Community Server as that seemed a bit less cluttered.  (BTW if you want to run .NET blog without SQL Server (like me) then DasBlog's what you want.

Pro's

  • Price (free)
  • Supports pretty much everything I need (open architecture, skinning, module development etc)
  • Familiar from previous use
  • Easy to use and administer - very WYSIWYG
  • Documentation's comprehensive (if a little focused towards the high-level architectural view). 

Con's

  • Slow (I thought I imagined this as my own dev machine's not a 'beast' and it's running SQL 2005 express, but part of this is potentially partly due to the caching mechanism (as noted on the MojoPortal site)
  • Table-driven by default (if you want your skin to be CSS-driven you've either got to muck around for ages finding a 'good' CSS skin (there's plenty of bad/really basic ones).  This extends to the DNN standard controls, and it takes an awfully long time (using Firebug and the IE Dev toolbar) to work out why you've still got fixed size fonts when you've gone to great length in your skin to make everything sizable.  (I'm sure again the better CSS skins address this, but you there always appears to be something that gets in the way because the original DD design uses tabular layout throughout).
  • It's written in VB.NET (OK this isn't a 'real' reason, as there's no difference - I know!  You also shouldn't need to do much (if anything) in VB.NET if you're a C#'er and you want to extend things - I think I'm just a bit miffed I've got to work with a bit of VB.NET at work at the moment :-) )
  • Not that keen on the actual logical structure, and the limited url-rewriting.  The whole anonymous tab thing out of the box.  It seems to me that DNN was designed before lots of newer features became available and it's had to bolt them on as time's gone by.
  • Lastly - it doesn't feel very open source.  It's clear that the business model has evolved to keep the output freely available whilst making money out of books, consulting and conferences (fair play to Shaun Walker - he deserves the kudos for the product).  I just feel that things went a little 'corporate' a while ago, which turned me off.  I bought an iRiver rather than an iPod for the same reason (too much marketing noise that turned me off, almost trying to bombard you so you don't even consider other products, and also trying to deter competition).  There's also many people now trying to make money out of skins (most of which aren't terribly good) - another indicator that the 'community' isn't very focused on open source development.

MojoPortal

Until a couple of days ago I'd not heard of this, but the performance discussion (above) sparked my interest.  It's clearly got less out-of-the-box functionality and community support than DNN and is lacking more in the documentation department, but if you're after a no fuss implementation then this might be the way to go.

Pro's (from the site - not my experience)

  • Free and open source
  • Multi DB support (just about any DB you'd care to use)
  • Approval/workflow support (although haven't looked into this yet)
  • Provides major functionality required
  • Skinning uses standard ASP.NET theme-based approach
  • Aligned relatively well with accessibility guidelines (CSS layout) - XHTML compliancy 

Con's

  • Download is actually a little confusing.  You've got a number of zip files and you're left to work out which one/s you need.  I downloaded a couple then reaslied I only needed the mssql release. 
  • Documentation a little lacking (although installation pretty easy once you've just changed a config setting). 
  • More of a 'developer' product - some understanding of .NET required.  This makes it more difficult for non-techy people to get it off the ground  

Jury's still out on this one as I've literally installed and that's it.  I need to get to grips with the integration and skinning support, as I want to change the default 3 pane layout and remove the left panel, so we'll see how that goes...

Others (That I don't know anything about)

Rainbow Portal (looks like it might be more worth a look in a year or two when there's a bit more support

Umbraco (not all versions free)

 

So what am I going to do now?  Install MojoPortal and see if it 'feels' nicer than DotNetNuke.  I'm not really too worried about future support, and upgrades as I'm providing a site to a client who will run with it once I'm done (based on what it does 'now' - and how stable it is 'now').

I'll post the results - or add to the list when I've come to a conclusion after some more research

posted on Saturday, March 08, 2008 3:46:56 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Comments [0]
# Thursday, February 21, 2008

Using print stylesheets with ASP.NET Themes

ASP.NET themes are great (in principle), and allow you to have lots of control on how your pages look with theme-specific skins, stylesheets, images etc.  The only thing that's a little bit annoying is that you can't specify (without codebehind) what media the stylesheet should apply to. 

If you add a new stylesheet to your theme folder called 'printer.css', ASP.NET will omit the 'media' attribute when it's output to the <head> section, and it will then be subject to the normal order of precedence rules, affecting your screen output.

There may be other easy ways to do this, but W3C generally think of everything, and then the world catches up - so just use the @media rule to surround all your media-specific styles.  The easiest way to organise this is obviously in different style sheets if you've got a complex layout.  My simple 'printer.css' is below (along with the stylesheet link generated by ASP.NET). 

This simply knocks out the left nav, right side bar and the footer (all divs of course), leaving a relatively clean page for printing. 

<link href="../App_Themes/corporate/printer.css" type="text/css" rel="stylesheet" />

 

posted on Thursday, February 21, 2008 8:32:01 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Comments [0]
# Wednesday, February 20, 2008

Do Web Sites need to look exactly the same in every browser?

It's on the internet so it must be right ;-)

http://dowebsitesneedtolookexactlythesameineverybrowser.com/

Does that mean I can go home now?

 

...but seriously, it does make you stop and think a little and get a bit of perspective

posted on Wednesday, February 20, 2008 7:52:20 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Comments [0]
# Wednesday, February 06, 2008

Programmatically add Meta Tags to ASP.NET Master Pages using a SiteMap

I hadn't really used SiteMaps before, but it's a useful feature of ASP.NET 2.0 (most people using them to drive BreadCrumb controls and site navigation).

After realising there was no support for design of the sitemap (apart from the default text editor) I found a simple (and functional) SiteMap editor here.

I then realised that I needed to add meta tags for each page in the site (NOTE: this is a simple 'content' site, so don't come running to me if you have the need to generate specific tags based on what colour trousers the user is wearing!).

You can add new attributes very easily to the sitemap, and access them programmatically.  The editor has a nice little grid to make this extra easy for you.  In my example here we've added a 'keywords' attribute. 

Assuming you're using a treeview (or something similar) for navigation on your site and you're binding to the SiteMap data source, then you'll get the context of the current site map node in your page (or master page).

You can then use it to set your meta tags as follows:

You can also set Page.Title from currNode.Title etc.

This is actually quite a neat way to drive things like other standard properties of your master page - e.g. subheadings. 

posted on Wednesday, February 06, 2008 4:46:54 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Comments [0]
# Sunday, May 15, 2005

CodeProject Article - Internet Explorer 5+ extensions

I've just added another article to offload some Javascript extensions I wrote a while ago for IE 5...

http://www.codeproject.com/jscript/ieextensions.asp

posted on Sunday, May 15, 2005 7:28:20 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]