PowerShell Coalesce and PowerShellASP Query String Parameters

I had fun initially with PowerShellASP, but its sealed classes prevented me from doing much useful with it in SharePoint. I really need to take a look at Andre de Cavaignac‘s PowerShellPages project, though the GPL license is a bit restrictive for my taste. Maybe I’ll just build my own…

Anyway, I actually had a practical use for PoShASP today, and in working with it I decided there needed to be a better way to handle QueryString values. The resulting function is fairly straight-forward, and supports typed and optional parameters:

<% QSParam w x,int,10 y,double z,zzz %>
w = <%= $w %>
x = <%= $x %>
y = <%= $y %>
z = <%= $z %>

With no query string, we get the following:

w =
x = 10
y =
z = zzz

However, if I use a query string like w=42&x=oops&y=3.14&z=pi, the valid values fall through:

w = 42
x = 10
y = 3.14
z = pi

Since ‘oops’ isn’t an [int], we get the default. But first…

PowerShell Coalesce

One of the most underused C# operators is the coalesce operator (??), which evaluates to the right-hand value if the left-hand value is null. PowerShell doesn’t include such an operator (to my knowledge), but we can certainly build a function to do the job. I found an implementation contributed anonymously in the comments here:

function Coalesce-Args {
    ([object[]]($args | ?{$_}) + ,$null)[0]

Which can be simplified to this:

function Coalesce-Args {
  (@($args | ?{$_}) + $null)[0]
Set-Alias ?? Coalesce-Args

The array subexpression @( ... ) always returns an array, to which we append $null in case the array is empty. Taking the first element yields the desired result. I also define an alias (??) for an easily remembered shorthand, though the usage is different from the binary C# operator. With our new function, my original QueryString pattern:

if( !($n = $Request.QueryString["n"] -as [int]) ) { $n = 10 }

Can be rewritten as:

$n = ?? ($Request.QueryString["n"] -as [int]) 10

QSParam Function

Now that we have Coalesce-Args, we can implement QSParam:

function QSParam {
  $QueryString = $Request.QueryString
  $args | ForEach-Object {
    $arg = @($_)
    $varName = $arg[0];
    $varType = $arg[1] -as [type];

    $qsValue = $QueryString[$varName]
    if ($varType -eq $null) {
      $varValue = Coalesce-Args $qsValue $arg[2] $arg[1]
    } else {
      $varValue = Coalesce-Args ($qsValue -as $varType) `
                                ($arg[2] -as $varType)

    Set-Variable $varName $varValue -Scope script

If  PowerShell can’t cast the second value as a type, we use it as a default value. If a third value is specified, that takes priority over the second value (which is how you can specify a default value that would otherwise be confused for a type: QSParam rhymesWithSquid,$null,guid). Finally, we assign the result to a script-scoped variable so we don’t have to dot source the function call.

And in case you don’t follow the PowerShell team blog (or missed the post), Channel 9’s Expert-to-Expert with Erik Meijer and Jeffrey Snover is definitely worth watching if you’re at all interested in the language internals and other geeky stuff. Jeffrey’s enthusiasm for the language is infectious.