Silverlight
I was trying to get my Development Environment up & running the other day with Silverlight 4. It turns out that the Silverlight debug runtime isn't actually part of the standard client, or the Silverlight 4 Tools for Visual Studio.

Thanks to this thread I discovered

The "Silverlight managed debugging package" is part of the developer runtime, not the SDK or Tools. Make sure you have the latest version of the developer runtime installed (available at http://go.microsoft.com/fwlink/?LinkID=188039

On the plus side I did throw together this nice pretty clock just to test everything out.
There's probably a dozen ways to break this, but it covers the basic for autosizing the grid, limiting the dimensiosn with min height & max height sections, drawing lines & drawing ellipses & a small bit of math.



XAML

<UserControl x:Class="SlvrClock.Lib.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400" MinHeight="100" MinWidth="100">
    <Grid x:Name="LayoutRoot" Background="Black">
        <Line x:Name="lh" Stroke="Green" StrokeThickness="15" StrokeStartLineCap="Round" StrokeEndLineCap="Triangle" />
        <Line x:Name="lm" Stroke="Blue" StrokeThickness="10" StrokeStartLineCap="Round" StrokeEndLineCap="Triangle" />
        <Line x:Name="ls" Stroke="Red" StrokeThickness="5" StrokeStartLineCap="Round" StrokeEndLineCap="Triangle" />
        <Ellipse x:Name="el" Stroke="Yellow" StrokeThickness="5" />
    </Grid>
</UserControl>

C#

public partial class MainPage : UserControl
{
    private Storyboard timer = new Storyboard(); //timer
    private const double radian = Math.PI / 180; //radian
    private bool started = false;
    private double MaxHandLength { get; set; } //shorter length of width:height
    private Point CenterPoint { get; set; }
        
    public MainPage()
    {
        InitializeComponent();
        timer.Duration = TimeSpan.FromMilliseconds(50);
        timer.Completed += new EventHandler(Timer_Completed);
        timer.Begin();
    }

    protected void Timer_Completed(object sender, EventArgs e)
    {
        double aw2 = LayoutRoot.ActualWidth / 2, ah2 = LayoutRoot.ActualHeight / 2;
        if (!started || CenterPoint.X != aw2 || CenterPoint.Y != ah2)
        {
            //Reset the centerpoint & ratios on startup or if the window resizes.
            CenterPoint = new Point(aw2, ah2);
            MaxHandLength = Math.Min(CenterPoint.X, CenterPoint.Y);
            el.Height = el.Width = ((MaxHandLength - 10) * 2);
            lh.X1 = lm.X1 = ls.X1 = CenterPoint.X;
            lh.Y1 = lm.Y1 = ls.Y1 = CenterPoint.Y;
            started = true;
        }
        var now = System.DateTime.Now;
        //line hour - apply partial split for smoother transition and update more than onces per second.
        ChangeHand(lh, MaxHandLength - 80, 30 * (now.Hour + ((double)now.Minute) / 60));
        //line minute
        ChangeHand(lm, MaxHandLength - 60, 6 * (now.Minute + ((double)now.Second) / 60));
        //line second
        ChangeHand(ls, MaxHandLength - 40, 6 * (now.Second + ((double)now.Millisecond) / 1000));
        timer.Begin();
    }

    protected void ChangeHand(Line l, double r, double a) {
        //Calculate the point on the circumference based on Center, Radius & Angle.
        var i = a * radian;
        l.X2 = CenterPoint.X + r * Math.Sin(i);
        l.Y2 = CenterPoint.Y + r * -Math.Cos(i);
    }
}

Eoin Campbell

Config FunWe had a situation in work where we needed to make service installation a more configurable process.

So a very simple example, In order to install a .NET Windows Service we need to provide it with a username & password that the services will run as. We can either provide that information at installation time, or through the following properties in the ProjectInstaller.cs file for your service.

However in an environment where multiple developers are working on a service, particularly a service that requires elevated privileges and needs to run as a specific account, this can be a royal pain.

Razor View Engine, Looking Sharp
ASP.NET MVC 3 Beta & Enhancements to the Razor View Engine was announced by Scott Gutherie last week.

The Beta release also includes, New View Helpers, Unobtrusive JavaScript, Integration with the NuPack Package Manager and some other bells and whistles. So lets take a look inside and see what we can do.

Bad Luck
Server Time Mis-configured, Amazon Web Services S3 .NET SDK has a bug in it, Vague XMLExceptions that don't make sense.

Sometimes karma is just going to get you. There's no point fighting it. A series of events & issues just come together in cosmic bliss guaranteed to completely wreck your weekend.

We rolled out some new code for a new client last week. One of the "big stories" for both us and the client was a migration away from in-house content storage to a cloud based solution. We had opted to use Amazon S3 for the file storage part and after ~6 weeks of project development, rigourous QA & Regression testing, and a bit of a stressful production release we were good to go. Our Biz/Mkt team had seen it and they were happy. Last minute checks of the production service were done, all looked good, and home we went.

System.ApplicationException: Error Occured in S3Storage.Exists —> System.Xml.XmlException: Root element is missing. at System.Xml.XmlTextReaderImpl.Throw(Exception e) at System.Xml.XmlTextReaderImpl.ThrowWithoutLineInfo(String res)

Vague & unhelpful on a Saturday afternoon. After a visit to the office, many hours of debugging, testing on multiple servers & pcs with the most bizarre and unhelpful results, one bright spark noticed that the clock on the server was wrong. So we fixed the time.

And it "magically" started working.

*sigh* This kind of software voodoo drives me nuts so I took a few minutes today to figure out what the heck had actually happened.

So why would an incorrectly set system clock possibly manifest itself as a `Root element is missing` XmlException. A little context first. The exception was occuring in our code on the AWS SDK's S3Client GetObjectMetadata method

Note: some code omitted & replaced with "..." for brevity

var mdRequest = new GetObjectMetadataRequest() {
    BucketName = targetBucket,
    Key = targetFileName
};

//Exception Occurs Here
var mdResponse = s3client.GetObjectMetadata(mdRequest);

Time to break out .NET Reflector and go through the SDK Code.

public GetObjectMetadataResponse GetObjectMetadata(
	GetObjectMetadataRequest request)
{
    ...
    this.ConvertGetObjectMetadata(request);
    return this.Invoke<GetObjectMetadataResponse>(request);
}

private void ConvertGetObjectMetadata(
	GetObjectMetadataRequest request)
{
    ...
    this.AddS3QueryParameters(request, request.BucketName);
}

private void AddS3QueryParameters(
	S3Request request, string destinationBucket)
{
    ...
    webHeaders["x-amz-date"] =
        AmazonS3Util.FormattedCurrentTimestamp;
}

As we follow the chain of calls, we find this little gem, the webservice sets it's own custom header called x-amz-date with the current time from the local system running the App. Well that's some progress. Some quick googling and we find that this timestamp requirement is mandatory for REST calls to the service and that it must be within 15 minutes of the Amazon System Time when the request is received otherwise a RequestTimeTooSkewed error status will be thrown back.

http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTAuthentication.html

After some quick testing on my local machine, this does indeed seem to be case. 14 minute difference. No problem. 16 minute difference. Still the XML Exception. As a side note, it turns out our PDC was serving time to our entire production domain of about 14 minutes & 59 seconds out of whack with the real world and lost another second over the weekend. That's just bad luck.

Alas, the docs would appear to be incorrect (at least from the aspect of the the .NET Library behavior). In fact there's a pretty horrid bug in the internal exception handling of the AWS SDK for .NET. When attempting to call the GetResponse in the main invoke method, it throws an exception and dumps you down into the generic catch all WebExceptions block.

private T Invoke(S3Request userRequest) where T: S3Response, new()
{
    ...
    try
    {
        httpResponse = request.GetResponse() as HttpWebResponse;
    }
    catch (WebException exception)
    {
        using (HttpWebResponse response2 =
            exception.Response as HttpWebResponse)
        {
            flag = ProcessRequestError(request, exception,
                response2, requestAddr, out headers, this.myType);
	}
    }
}

private static bool ProcessRequestError( ... )
{
    ...
    using (StreamReader reader = new StreamReader(errorResponse.GetResponseStream(), Encoding.UTF8))
    {
        responseBody = reader.ReadToEnd();
    }
    ...
    if ((statusCode == HttpStatusCode.InternalServerError) || (statusCode == HttpStatusCode.ServiceUnavailable))
    {
        return true;
    }
    ...
    using (XmlTextReader reader2 = new XmlTextReader(
        new StringReader(Transform(responseBody, "S3Error", t))))
    {
        ...
        throw new AmazonS3Exception( ... ); 
        //without original WebException
    }
}

This is where it all goes pear shaped. The WebException thrown is actually a 403 Access Forbidden. But the ProcessRequestError method doesn't account for this. It'll trigger the retry flag on an InternalServerError or ServiceUnavailable status code but otherwise it will continue on, and attempt to parse the response body into an S3Error. In our case the response body is string.Empty, an XmlException gets thrown and the original WebException gets lost in the ether

*Wanders off to find a way to log bugs with the AWS for .NET Dev team*

Eoin Campbell

Generic Marketeer: Why do we need to shorten the URLs, people just click on them. It’s not like they have to memorize them; call them out to their friends

Me: Eh… no you’re right, but I do need to jam them into a SMS WAPPush along with some descriptive text, so I don’t have much room to play with

Generic Marketeer: Fine, as long as it doesn’t impact the project deadline

Cue, my good self scurying away to find a way to bang out a private URL Shortening service in as short a time as possible. The URL Storage itself was a piece of pie. But I did stumble across some nice code while I was at it. I started out with a int-to-base64 implemenation. but the + & / characters are fugly to deal with in URLs. I tried a Hex version as well but it just didn’t look bit-ly-y enough. Enter the baseAnything encoder. Just point it at any character set and it will encode/decode to that number of chars. The following extension methods convert longs to strings, and vice-versa

public static string ToBase(this long input, string baseChars)
{
    string r = string.Empty;
    int targetBase = baseChars.Length;
    do
    {
        r = string.Format("{0}{1}",
            baseChars[(int)(input % targetBase)],
            r);
        input /= targetBase;
    } while (input &gt; 0);

    return r;
}


public static long FromBase(this string input, string baseChars)
{
    int srcBase = baseChars.Length;
    long id = 0;
    string r = input.Reverse();

    for (int i = 0; i < r.Length; i++)
    {
        int charIndex = baseChars.IndexOf(r[i]);
        id += charIndex * (long)Math.Pow(srcBase, i);
    }

    return id;
}

I’ve been using it against the first character set below, but you could easily tweak it to remove any confusing characters, or any set for that matter.

private static string ALPHANUMERIC =
    "0123456789" +
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
    "abcdefghijklmnopqrstuvwxyz";

//Remove 0oO1iIl - Base52
private static string ALPHANUMERIC_ALT =
    "23456789" +
    "ABCDEFGHJKLMNPRSTUVWXYZ" +
    "abcdefghjkmnpqrstuvwxyz";
}

Now all I have to do is go write a Math Engine for it ;-)

Eoin Campbell