Thursday 28 June 2007

Adding a .NET kicks link to a Blogger blog

Here's how you can add a link to .NET kicks on a blogger hosted blog:

Go into your blog settings and select to edit the template. You will need to check the checkbox to expand custom widgets first. Then find the <data:post-body/> section and insert the following code afterwards:

<div class='post-body'>
<p><data:post.body/></p>
<div style='clear: both;'/> <!-- clear for photos floats -->
<!-- dotnetkicks BEGIN -->
<p><a expr:href='"http://www.dotnetkicks.com/kick/?url=" + data:post.url'><img border='0' expr:src='"http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=" + data:post.url'/></a></p>
<!-- dotnetkicks END -->
</div>

Thursday 21 June 2007

OpenID in ASP.NET

I found a helpful ASP.NET OpenID control that lets you implement an OpenID login on your website. The instructions are a little weak so I thought I'd post a quick how-to here.

First you need to download the binaries and copy them into the bin folder of your web application.

  • Boo.Lang.dll (because JanRain is written in Boo)
  • JanRain.dll (an OpenID library for .NET)
  • Mono.Security.dll
  • NerdBank.Tools.dll (contains the ASP.NET control)

Then you simply register the assembly at the top of your aspx page:

<%@ Register Assembly="NerdBank.Tools" Namespace="NerdBank.Tools.WebControls" TagPrefix="nb" %> 

And then insert the control:

<nb:OpenIdLogin ID="openIdLogin" runat="server" 
        RequestEmail="Request" RequestTimeZone="Request" RequestNickname="Request" 
        PolicyUrl="http://mysite.com/PrivacyPolicy.aspx" />

Here I have requested the email, timezone and nickname. I could also say Require for these if I absolutely must have them. You should also provide a privacy policy URL, or else the user will be warned that it is missing.

The control itself provides a Register link that is customizable, allowing users to sign up with an Open ID provider such as www.myopenid.com.

When you login, if you have entered a valid OpenID URL, you will go to your OpenID provider who will ask for your password if necessary, confirm whether you want to allow that site to log you in once, always or never, and ask you what persona you want to use.

On a successful login, you can retrieve the OpenID URL as well as anything from the persona that has been made available. Here's some sample code-behind.

protected void Page_Load(object sender, EventArgs e)
{
    Uri openIdUri = Session["OpenIdUri"] as Uri;
    if (openIdUri == null)
    {
        openIdLogin.LoggedIn += new EventHandler<NerdBank.Tools.WebControls.OpenIdTextBox.OpenIdEventArgs>(openIdLogin_LoggedIn);
        openIdLogin.Visible = true;
    }
    else
    {
        openIdLogin.Visible = false;
        Response.Write("Welcome " + openIdUri.ToString() + "<br />");
        Response.Write("Email: " + Session["openIdEmail"] + "<br/>");
        Response.Write("Nickname: " + Session["openIdNickname"] + "<br/>");
        Response.Write("TimeZone: " + Session["openIdTimeZone"] + "<br/>");            
    }
}

void openIdLogin_LoggedIn(object sender, NerdBank.Tools.WebControls.OpenIdTextBox.OpenIdEventArgs e)
{
    Session["OpenIdUri"] = e.OpenIdUri;
    Session["OpenIdEmail"] = e.ProfileFields.Email;
    Session["OpenIdNickname"] = e.ProfileFields.Nickname;
    Session["OpenIdTimeZone"] = e.ProfileFields.TimeZone;
}

As you can see, it is pretty simple. I still need to work out how I am then going to integrate the OpenID login with my own site login database. The control itself also has a few limitations. In particular, entering an invalid URL causes an unhandled exception. It also doesn't give you an event for login failure (although there is a "logging in" event which I am not sure what it is for).

Identity or UniqueIdentifier (GUID) for Database Key?

Jeff Atwood posted an interesting article on whether to use GUIDs or integers for primary keys in databases. Its been a while since I did any database design, and this issue has come up in a new ASP.NET project I have recently begun.

I'm not particularly bothered about the disk space / performance issues. I suspect the difference is not all that great and in any case, my database is not likely to be huge.

As I see it the reasons for me to use GUIDs are:

1) The auto-generated ASP.NET 2 user database already uses uniqueidentifier, thus my instinct is to use it in all my tables as well for consistency.

2) Easier to copy records to other tables / import into other databases without breaking relationships. (however, there appears to be a SET IDENTITY_INSERT command in SQL Server which means that this is also possible with IDENTITY fields)

There is however one significant drawback, which may move me back to using integers. The issue is that of URLs. I want users of my site to be able to generate links to individual records in the format:

www.mysite.com/View.aspx?id=104

With a GUID, this becomes a lot more unwieldy and much more likely to encounter problems with line-wrapping truncating the URL.

www.mywebsite.com/View.aspx?id=015B34D5-A301-4543-AE1A-16708B19F602 (yuck!)

I did consider adding another integer column alongside the GUID which would act as the URL key, but this seems ridiculous to have two keys in the table.

Some people however have complained that IDs should never be present in a URL, as it allows people to randomly choose other IDs and perhaps get to pages they shouldn't. For my purposes this isn't a big deal. I have a 'private' field in my database that I will be checking before displaying an item to a user.

Constructing a URL out of an items textual description can make for nicer URLs in some cases:

www.mysite.com/View.aspx?an-example-item

But this introduces an artificial constraint on the description being unique (e.g. why can't I have two blog entries with the same title?), and also can result in messy URLs if the description is long and contains punctuation or unusual characters.

So it looks like I may be heading back to integers, unless someone has a clever idea of how to make friendly URLs when the key is a GUID.

Wednesday 20 June 2007

CSS Layout - Columns, Headers and Footers

Most websites these days seem to have a standard layout. There is a header at the top, a footer at the bottom, and then one or two thin bars of links or adverts down either side. Using tables, this is relatively simple to do - it's a table with three rows and three columns:

<table border="1">
<tr>
    <td colspan="3"><b>Header</b></td>
</tr>
<tr>
    <td width="20%">Left Column</td>
    <td width="60%">Centre Column</td>
    <td width="20%">Right Column</td>
</tr>
<tr>
    <td colspan="3"><i>Footer</i></td>
</tr>
</table>
    <td colspan="3">Footer</td>
</tr>
</table>

But this is seriously out of fashion these days. You are now expected to use CSS, which can be a bit frustrating to learn at first. Here's how to generate a three column layout in CSS, which will expand in width to use your whole browser window.

The first thing to do is ditch the table and use div tags:

<div id="header">Header</div>
<div id="left-col">left column</div>
<div id="right-col">right column<br/>link</div>
<div id="centre-col">centre column</div>
<div id="clear"></div>
<div id="footer">footer</div>

This is all fairly straight-forward, except the need for the clear div, which ensures the footer stays at the bottom of the page.

Now we need to write the styles. For the most part, they are simple to understand.

#header {
border:solid thin gray;
text-align:center;
font-size:x-large;
font-weight:bold;
margin:5px;
}

#left-col {
border:solid thin gray;
margin:5px;
width=150px;
float:left;
}

#right-col {
border:solid thin gray;
margin:5px;
width=150px;
float:right;
}

#centre-col {
border:solid thin gray;
margin:10px 160px 5px 160px;
min-height:400px;
}

#footer {
text-align=center;
border-top:dashed thin gray;
margin:5px;
font-style:italic;
}

#clear {
clear:both;
}

Points of interest:

  • The centre column has to provide left and right margins wide enough not to obscure the left and right columns.
  • The min-height property ought to ensure that the page does not appear artificially squashed if there is no content. However, I am not sure this is working in all instances.
  • Borders and margins can be used together to create a much nicer looking separation of sections than can be achieved simply with tables.
  • You have to put the right column before the centre column for layout to work correctly.

 

Monday 11 June 2007

XAML Football Pitch

Here's a XAML football pitch, potentially the beginnings of a Silverlight football application. I've used metres as coordinates, and drawn a pitch of the maximum allowed size. For the second penalty area, I just reflected the first one. Unfortunately there is no simple way of reusing the same item twice in the same XAML file.

<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="525" Height="400" Background="#00b000">
    <Canvas x:Name="Pitch" Canvas.Left="20" Canvas.Top="20" >
        <Canvas.RenderTransform>
            <ScaleTransform ScaleX="4" ScaleY="4" />
        </Canvas.RenderTransform>
        <!-- http://en.wikipedia.org/wiki/Football_pitch -->
        <!-- dimensions in metres -->
        <Polygon Points="0,0 120,0, 120,90, 0,90 " Stroke="White" StrokeThickness="1" />

        <Canvas x:Name="PenaltyArea" Canvas.Top="24.85" >
            <Polyline Points="0,0 16.5,0 16.5,40.3, 0,40.3" Stroke="White" StrokeThickness="1" />
            <Polyline Points="0,11 5.5,11 5.5,29.3, 0,29.3" Stroke="White" StrokeThickness="1" />
            <Polyline Points="0,16.5 -2.44,16.5 -2.44,23.8, 0,23.8" Stroke="White" StrokeThickness="1" />
            <Ellipse Canvas.Left="2.15" Width="18.3" Height="18.3" Canvas.Top="11" Stroke="White" StrokeThickness="1" Clip="M 14.35,0 h 10 v 20 h -10 Z" />
            <Ellipse Canvas.Left="10.5" Width="1" Height="1" Canvas.Top="19.65" Fill="White" />
        </Canvas>

        <Canvas x:Name="PenaltyArea2" Canvas.Top="24.85" Canvas.Left="120" >
            <Canvas.RenderTransform>
                <ScaleTransform ScaleX="-1.0" />
            </Canvas.RenderTransform>
            <Polyline Points="0,0 16.5,0 16.5,40.3, 0,40.3" Stroke="White" StrokeThickness="1" />
            <Polyline Points="0,11 5.5,11 5.5,29.3, 0,29.3" Stroke="White" StrokeThickness="1" />
            <Polyline Points="0,16.5 -2.44,16.5 -2.44,23.8, 0,23.8" Stroke="White" StrokeThickness="1" />
            <Ellipse Canvas.Left="2.15" Width="18.3" Height="18.3" Canvas.Top="11" Stroke="White" StrokeThickness="1" Clip="M 14.35,0 h 10 v 20 h -10 Z" />
            <Ellipse Canvas.Left="10.5" Width="1" Height="1" Canvas.Top="19.65" Fill="White" />
        </Canvas>

        <Ellipse Canvas.Left="50.5" Width="19" Height="19" Canvas.Top="35.5" Stroke="White" />

        <Line X1="60" Y1="0" X2="60" Y2="90" Stroke="White" StrokeThickness="1" />
    </Canvas>
</Canvas>

Thursday 7 June 2007

Basic Web Service Access From C#

I recently wrote a small plugin for Windows Live Writer, which allowed you to enter a Bible reference, and it would either create a link to Bible Gateway, or insert the text in the English Standard Version.

To get the ESV text, I needed to call a web service in C#. It was the first time I had done this, and it turned out to be surprisingly simple. First I needed to construct the URL to call. This was simply a case of constructing the ESV Web Service API documentation. The only slight complication is the need to add a reference to System.Web so you can call HttpUtility.UrlEncode.

StringBuilder url = new StringBuilder();
url.Append("http://www.gnpcb.org/esv/share/get/");
url.Append("?key=IP");
url.Append("&passage=");
url.Append(System.Web.HttpUtility.UrlEncode(reference));
url.Append("&action=doPassageQuery");
url.Append("&include-passage-references=false");
url.Append("&include-audio-reference=false");
url.Append("&include-footnotes=false");
url.Append("&include-subheadings=false");
url.Append("&include-headings=false");

Once you have the URL with the search parameters, then you simply pass it to a web request, get its ResponseStream() and read it to the end.

WebRequest request = WebRequest.Create(url.ToString());
StreamReader responseStream = new StreamReader(request.GetResponse().GetResponseStream());
String response = responseStream.ReadToEnd();
responseStream.Close();
return response.ToString();

Obviously there are more complicated types of web service than this, which require construction and parsing of XML, but I was still impressed with how few lines of code were actually involved in my first web service call.

Creating a Hatched / Patterned Brush in WPF

I recently wanted to create a patterned brush in WPF. Of course, WPF is more than capable of doing hatching patterns, but it took me a little while to work out how to do it, especially since the MSDN2 website seems to have lost all example XAML snippets at the moment.
The approach I chose is to use a VisualBrush, although a DrawingBrush would probably work equally well. In the Visual property of the VisualBrush you add your graphics. So for my examples I have one which just has a circle, allowing you to fill an object with dots, and one with two diagonal lines, to create cross-hatching. Then you need to set some additional properties on the VisualBrush:

  • TileMode would be set to Tile as this is a repeating pattern
  • Stretch is set to None
  • The ViewBox rectangle specifies a window onto the Visual allowing you to select just a part of it. Both my fill pattern visuals were 10x10, but I made the ViewBox for the dot fill 12x12 which effectively added some spacing between the dots.
  • The ViewPort rectangle gives more flexibility by specifying the position and dimensions of the first "tile". Normally you would simply set this to the same as the ViewBox, but you could use it to scale the tiled image in X or Y dimensions, or effectively slide the tiles across.

Here's some example XAML:

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:sys="clr-namespace:System;assembly=mscorlib" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
  <VisualBrush 
    x:Key="DotFillBrush" 
    TileMode="Tile" 
    Viewport="0,0,10,10" 
    ViewportUnits="Absolute" 
    Viewbox="0,0,12,12"
    ViewboxUnits="Absolute">
    <VisualBrush.Visual>
      <Ellipse 
        Fill="#00C0FF" 
        Width="10" Height="10" />
      </VisualBrush.Visual>
    </VisualBrush>      
    <VisualBrush 
      x:Key="HatchBrush" 
      TileMode="Tile" Viewport="0,0,10,10" 
      ViewportUnits="Absolute" Viewbox="0,0,10,10"    
      ViewboxUnits="Absolute">
      <VisualBrush.Visual>
        <Canvas>
           <Rectangle Fill="Azure" Width="10" Height="10" />
           <Path Stroke="Purple" Data="M 0 0 l 10 10" />
           <Path Stroke="Purple" Data="M 0 10 l 10 -10" />
        </Canvas>
      </VisualBrush.Visual>
   </VisualBrush>      
</Page.Resources>

<Canvas>
<Rectangle Canvas.Top="20" Canvas.Left="20" 
  Width="80" Height="40" 
  Fill="{StaticResource DotFillBrush}"/>
<Rectangle Canvas.Top="20" Canvas.Left="120" 
  Width="80" Height="40" 
  Fill="{StaticResource HatchBrush}"/>
<TextBlock Canvas.Top="80" Canvas.Left="20" 
  Text="Hello" FontSize="80" 
  Foreground="{StaticResource DotFillBrush}"/>
<TextBlock Canvas.Top="80" Canvas.Left="220" 
  Text="World" FontSize="80" 
  Foreground="{StaticResource HatchBrush}"/>
</Canvas>
</Page>

And here's what it looks like:

WPF Patterned & Hatched Brushes

Tuesday 5 June 2007

Orcas Beta 1 - Not ready for the Prime time

I've had Visual Studio Orcas Beta 1 installed on a Virtual PC for a while now, and have mainly been using it to do some Silverlight 1.1 development. For the most part it has worked OK, although I've had a few niggles with it:
  • Doesn't let me step through JavaScript (despite turning on Script debugging in IE)
  • Insists on covering up part of the code with a toolbar window whenever I run in debug mode.

But today I tried to develop a WPF application in it, instead of simply using Visual Studio 2005 with the .NET 3.0 extensions. The experience was painful. The designer regularly threw exceptions, and Visual Studio itself crashed a few times.

More concerningly, the WPF designer itself seems very lacking in the basic functionality we have come to expect with Windows Forms. I am very enthusiastic about WPF, but if I am to persuade anyone at my work that using it would be a good idea, we need a much better experience for those who just want to create a Window and add controls and event handlers if they are to be tempted away from plain old Windows Forms.

  • You have to continually ask the designer to show you just XAML - it defaults to a split view with not enough space to see either the layout or XAML
  • Double-clicking a button in the designer doesn't add a handler
  • You can't choose font settings in a nice dialog - you just have to know what you can enter into FontFamily
  • You can't ctrl-click and drag to copy a control

So unfortunately, Orcas Beta 1 is very much a beta, and still a long way from being a release candidate. Hopefully there will be a beta 2 before too long, with a much enhanced WPF designer, and built-in Silverlight support.

Friday 1 June 2007

HOWTO: Make your Silverlight 1.1 Application Scriptable

Here's how to make your Silverlight application scriptable from JavaScript. I'll use my SilverNibbles application as an example, and we will make it so that you can start a new game by pressing an ordinary HTML button that calls into the Silverlight application.

This requires us to make our Page class scriptable. We will also make the NewGame function accessible to JavaScript. First we must mark both the Page class and the NewGame function with the Scriptable attribute, found in the System.Windows.Browser namespace.

using System.Windows.Browser;
...
namespace SilverNibbles
{
[Scriptable]
public partial class Page : Canvas
{
...

[Scriptable]
public void NewGame(int players)
{
...

The next step is to register a variable that JavaScript can use to access the instance of the Page class. We do this in the Page's Loaded event handler. We have chosen to call our instance, "SilverNibbles".

public void Page_Loaded(object o, EventArgs e)
{
...
WebApplication.Current.RegisterScriptableObject("SilverNibbles", this);

Now we will create some buttons in our main HTML page that will start a new game, along with some JavaScript that handles them. Notice I have set the focus to the Silverlight control which will ensure we have keyboard focus for the new game. Also notice that our registered scriptable object is referenced as a member of the Content property of the Silverlight control.

<script src="Silverlight.js" type="text/javascript"></script>
<script src="SilverNibbles.html.js" type="text/javascript"></script>
<script type="text/javascript">
function onNewGameClick(players) {
var silverlight = document.getElementById('SilverlightControl');
silverlight.focus();
silverlight.Content.SilverNibbles.NewGame(players);
}
</script>
...

<p>New game:
<input onclick="onNewGameClick(1)" type="button" value="One Player">
<input onclick="onNewGameClick(2)" type="button" value="Two Players">
</p>

Visual Studio Regions

Visual Studio has a really nice regions feature which allows you to mark off sections of a file so they can be collapsed in the editor.

#region Painting Functions
... code goes here
#endregion

Now it seems that at Microsoft, there is a growing tendency to group absolutely everything in a class up into groups such as:

  • Public methods
  • Public properties
  • Protected methods
  • Private methods
  • Events
  • Private data

And many developers who see this then go about implementing this in their own code, removing any regions already defined and moving things into new regions based on their accessibility.

But here is the issue I have. How useful an organization is this really? I like it when a class has all of its private data together (I prefer at the top, but some put this at the bottom), so that is fine. And it makes sense for the constructors to be kept together.

But grouping methods by whether they are private, protected or public makes about as much sense as organizing your house by putting all the tables in one room and all the chairs in another. Yes its very organized, and yes you will know exactly where to go when you want a chair, but its not much use when you want to sit down at the table and eat dinner.

Say I'm looking at some code and I see a call to a CalculateOffsets function. How should I know whether I will find it in the public, private or protected methods region?

Surely it makes more sense to group functions into regions by whatever logic the class does. A good example would be a region for the Dispose pattern which includes a public method, a protected method and a finalizer. Another example would be the implementation of an interface such as IComparable. In a Windows forms class, you might have a region that had event handlers for all controls on the form, or a region for just for dealing with one particularly complex control's events.

I'm not saying that the Microsoft way doesn't have benefits or should never be used. But its the one-size-fits-all approach that bothers me. I don't want to expand eight regions every time I open a file only to find most of them are empty or just have one item in each.