# Tuesday, April 01, 2008

VB.NET - I know I shouldn't care but I just don't like it!

Aaargh! I thought to myself for the umpteenth time as I looked through my inherited VB.NET web site (it's bad enough that it was a web 'site' with dodgy auto-generated (i.e. NO) namespaces), but the following things are now officially going on my list of reasons I choose C# over VB.NET.  I know I shouldn't care as it all compiles to the same thing, but (just from this project) -

  • VB.NET still allows you to dodge the Option Strict and Option Explicit (definitely a 'Web Site', as there's no option in the property pages like for any other standard .NET project).  This means that you happily declare untyped variables, and do all sorts of dodgy late binding.  Some people obviously like this facility, but it's one of the things that holds VB programmers back in the world of object-oriented design.
  • Modules still exist!  OK you could argue this is just a public class with everything marked as static, but it's still 'global', and you don't need to reference the module name when you access a method or variable.  This often leads to the 'where the hell is that defined?' question
  • Variants still exist.  This is obviously an extension of the first one, but it's a big enough annoyance that people use to get themselves out of a (I don't know how to implement this properly using object-oriented techniques) hole
  • Syntax 'feel' - e.g. Me vs this, and MyBase vs base - it feels a bit 'Mickey Mouse'.
  • Verbose syntax causing RSI:
    • #Region "String Constant" vs #region whatever you like without having to put quotes around (C# regions can also be indented with the code unlike VB)
    • Global functions instead of operators like TryCast instead of 'as', CType instead of (Mytype)variable.  CStr, Cint etc still exist.  Not only is this more typing in many cases as you need to enter two or more parameters, it also feels like yet more 'baggage' from the bad old days, as you can still pass in your objects to generic 'library' functions rather than use methods on the object themselves (like ToString()).  Many VB programmers will lap this up because the language still allows them and they don't have to learn something new.
  • Case insensitivity.  OK I'll give you this one as it was one of the 'speed' things in VB6.  It does lead you back to the horrible pseudo-hungarian thing (for some people) though as you get naming conflicts with properties and variables if you follow the general pascal/camel C# standard (can't remember whether there's an option to switch that off though).  The alternative to the pseudo-hungarian notation is the _ prefix for class variables, but even that seems like too much of a concession.
  • Methods can still look like properties.  Call a method in VB without parameters and it will happily let you write MyMethod.  This just feels like inconsistency.
  • Tool support and productivity. 
    • VB.NET simply doesn't have the same support in Visual Studio or refactoring addins (ReSharper's only catching on to VB.NET now) This isn't the language's fault, but it's easier to be more productive through tools with C#.  (I know this is improved with every release of VS).
    • The default VS 2005 refactoring capability (limited but present in some form) for C# is basically non-existent for VB.NET.  Maybe Microsoft think VB programmers don't need refactoring support?
    • Intellisense is also generally rather lacking for VB.NET
    • XML Documentation comments (just now catching up, but was really lacking)
  • Angle brackets <> look uglier than square brackets [] for attributes (OK that's a bit picky!)

The bottom line is that VB.NET lets you be sloppy, like VB always did.  The problem is that a fair percentage of those who migrate from VB to VB.NET (not all I agree - don't shoot me!) take the same shortcuts that they always did - because they still can.  

My opinion is that on average you'll find more elegant design, better formatted and more object-oriented code from C# programmers as they're more likely to have come from a C++ or Java background.

Did I mention that I was a VB programmer for years, and have only dabbled a bit in Java and not really ever C++.  I loved VB6 (at the time) as I could get systems written quickly and well.  What I didn't love was how much backwards-compatible support it kept leaving in with each new version, just so people could upgrade their crap legacy code.  I've seen some very clear, consistent, well formatted and commented VB.NET code, but I've seen an awful lot more that's not.  The flip side is that C# coders often think they're great just because they're writing in C#.  I've seen plenty of horror stories there too, but the 'bad' percentage is much lower (sorry - it just is).

VB unfortunately doesn't encourage discipline in programmers, whereas C# benefits from a clean slate without the historical baggage.  I believe the slightly more formal language specification of C#, and the fact it attracts more 'OO' coders, tends to lead people to think a little more about design rather than just skipping straight to implementation (which is where the 'real' problem is :-) ).  You can write the same crap code in any language you like.  VB unfortunately just makes it easier.

posted on Tuesday, April 01, 2008 5:16:51 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Comments [0]

Setting up SubVersion with Apache and Windows Group authentication

I found many links tell ing me how to do 'most' of this, but like lots of others, just couldn't put together all the pieces.

My requirements were:

  1. Set up SubVersion to run with a remote repository (on a network drive that's backed up)
  2. Run with Windows Authentication for all clients (tortoise, browser etc) and hook into the domain
  3. limit access to Windows Groups (not specific users) - to allow a single change to control everything (adding a user to a group that has access to the network resource).

Fact #1.  SubVersion only supports Windows Authentication through Apache.  There may be some hoops you can jump through to get that going with svnserve, but don't go there.

Fact #2.  SubVersion does not support any Windows AD 'group' authentication through its config files, and so you have to do this through Apache.  It supports 'custom' groups that you can add domain users to.

The process.

Right, we now know you need to install SubVersion, Apache, and some other bits and pieces to allow Windows Authentication.

1. Install the main components (Follow all instructions on Trumpi's blog).  This will set up SubVersion, Apache and the necessary modules to do Windows Authentication.

2. Change the 'Location' section at the bottom of the Apache httpd.conf to reflect your setup:  I've left in some commented lines to show some of the alternatives:

<Location /svn>
DAV svn
#SVNParentPath d:\LocalApp
#SVNPath D:\LocalApp\SVN
SVNPath //myserver/myshare$/SVN #NOTE the // rather than \\ in the UNC path name - you don't have to use a mapped drive!!!

#User Authentication Policy
AuthName "Subversion"
AuthType SSPI
SSPIAuth On
SSPIAuthoritative On
SSPIDomain mydomain
SSPIOfferBasic On #Essential for TortoiseSVN to access the repository as it doesn't support Windows integrated authentication
SSPIUsernameCase lower #allows you to type your username in lower case
SSPIOmitDomain On #allows you to just type your username without the domain\ qualifier

# our access control policy enforced by mod_authz_svn
#AuthzSVNAccessFile "D:\LocalApp\SVN\svnaccess.conf" #you shouldn't need this

#SSLRequireSSL #Look at http://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-serversetup.html#tsvn-serversetup-apache-5 if you need it
#require valid-user #User this line if you don't need to limit to a group - i.e. any domain user

require group mydomain\mydomaingroup #here's the magic for your group authorisation.  This limits access to the virtual directory
</Location>

3. Run the Apache2 service as a 'generic' domain user that is in your windows group (above).  This should also be part of the local administrators group on the web server (you can probably tweak this I was a bit lazy).  Access to the repository is then through the Apache user's credentials, and each user will simply be authorised based on their group membership at the Apache level.

posted on Tuesday, April 01, 2008 10:28:02 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Comments [0]
# Wednesday, March 26, 2008

Data Dictionary from within SQL Server

I knew you could do this, but never took the time to find out exactly which sys... table the comments got stored in.  sysProperties is what you want, and this article on SQLServerCentral tells you how...

The easiest way to get them 'in' is in Enterprise Manager, and someone posted a slightly amended version of the code to get them out (I also added IsNullable)...


DECLARE @TableName VARCHAR(128)

SET @TableName 'Catalogue'

SELECT 
    
T.table_name AS TableName,
    C.ordinal_position 
AS ColumnOrder,
    C.[column_name] 
AS ColumnName,
    
ISNULL(P.value, ''AS ColumnDescription,
    C.DATA_TYPE 
AS DataType,
    
COALESCE(numeric_precision,character_maximum_length,0AS Length,
    
COALESCE(numeric_scale,0AS DecimalPos,
    C.is_nullable 
AS IsNullable,
    
ISNULL(C.COLUMN_DEFAULT, ''AS DefaultValue  
    
FROM information_schema.tables T 
        
INNER JOIN information_schema.columns C 
            
ON T.table_name C.table_name 
        
LEFT JOIN ::FN_LISTEXTENDEDPROPERTY(N'MS_Description'N'user',N'dbo',N'table', @TableName, N'column'null) P 
            
ON C.column_name P.objname
    
WHERE T.table_name @TableName

Colorized by: CarlosAg.CodeColorizer
posted on Wednesday, March 26, 2008 8:46:43 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Comments [0]
# Thursday, March 20, 2008

Criteria for buying a Coffee

I experienced some (momentary) guilt the other day as someone at a coffee shop near work (offering concessions to staff) caught me with another shop's coffee!!  Aargh, gasp.  I was with a group so managed to convince them I was 'along for the ride' with them.  Ridiculous stuff, but it made me think - what makes us go to different coffee shops? 

Well, I'm in the 'coffee capital of Australia', so people take it a little seriously here (I'm easier to please), and don't take kindly to the 'big boys' from the US.  Here's my list of criteria.  A 'yes' answer gains a point, and a 'no' answer deducts a point:  Some questions overlap, but sometimes you just have to peel the onion :-)

  • Company is owned and run by someone in the shop
  • Company is owned and run locally (city or country) 
  • Coffee is sourced from ethical suppliers
  • The staff 'care', and smile
  • There's a shared tips jar
  • Location is convenient (this is thrown in because all other points may be good, but you're not going to walk forever just to get a coffee!)
  • You can be 'in and out' in less than 4 minutes (on average) - i.e. queues
  • The price is reasonable (based on the scores for the above - a bit subjective)

You might even apply your own weighting for each point - i.e. ethical supply may be something you're not prepared to compromise on, so give that 5 points (you get the idea).

Let's just say apart from the coffee tasting like water, It'll be a long time before I go to Starbucks!

posted on Thursday, March 20, 2008 8:37:03 AM (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

Top 10 Application Design Mistakes

Got sent this from a usability guy I sit next to.  Looks very interesting and a lot rings true.

 

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

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]