Ian Blackburn

March 2008 Entries

Silverlight and FriendFeed

Since FriendFeed has produced an api I thought it would be fun to produce a little Silverlight app or control that could consume it.

I thought this would be as simple as the digg example given in the Silverlight Quickstart - and it should be!

Unfortunately the guys at FriendFeed have not added a crossdomain.xml or  clientaccesspolicy.xml which stops Silverlight (and Flash for that matter) from making cross boundary calls to their api.

Took me a while to figure it out, so hope this helps someone.

Moreover I hope FriendFeed fix this one quick snap!

Cheers

Ian

Linq to SQL Nulls

The way Linq to Sql deals with nulls had me scratching my head initially. 

At first things seemed simple - for example the following does exactly what you would expect (Mike Taulty goes into more details on why here):

Customers.Where(c => c.Region==null)

This resolves to the following SQL:

SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address], 
       [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax] FROM [Customers] AS [t0] WHERE [t0].[Region] IS NULL

Notice that the Where clause uses IS NULL rather than = null which is correct.  However if I pass a null parameter to the query then the SQL is resolved incorrectly.  For example:

string region=null;

Customers.Where (c => c.Region==region);

This resolves to the following SQL which will never return any records when the parameter is null because it uses = instead of IS:

SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address], 
       [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax] FROM [Customers] AS [t0] WHERE [t0].[Region] = @p0

The Answer is Object.Equals

The answer is to use the static Object.Equals method in the Linq expression:

string region=null;

Customers.Where (c => Object.Equals(c.Region,region))

Which causes the SQL to be correctly created again:

SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address], 
       [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax] FROM [Customers] AS [t0] WHERE [t0].[Region] IS NULL

 

Cheers

Ian

Technorati Tags: ,,

Silverlight 1.0 Image Rotator with Ajax

Silverlight 2.0 might be all the fashion but 1.0 is released and out there, so there is value in using it purely for the wider reach and acceptance of users who are happier to  install the released plugin.

So here is a easy little app you can write your self to give you an image rotator with click through and whatever logic you want for the weighting of the images.

It fits together as follows:

  • A Silverlight Xaml page with some JavaScript to control it
  • An Asp.Net web page with the Script manager from the Ajax Extensions
  • A simple asmx web service that returns the next image to show.

The Silverlight Xaml

The following is a small bit of Xaml that has an image, a textblock and an storyboard that fades the image in and out using the opacity property:

 

<Canvas
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="420" Height="452"
    Background="#00000000"
    x:Name="Page" >
  <Canvas.Resources>
    <Storyboard x:Name="Storyboard1">
                    <DoubleAnimationUsingKeyFrames AutoReverse="True" 
                         BeginTime="00:00:00" Storyboard.TargetName="image"
                         Storyboard.TargetProperty="(UIElement.Opacity)" > <SplineDoubleKeyFrame KeyTime="00:00:01" Value="0"/> <SplineDoubleKeyFrame KeyTime="00:00:03" Value="1"/> <SplineDoubleKeyFrame KeyTime="00:00:04" Value="1"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </Canvas.Resources> <Image Cursor="Arrow" Opacity="0" Width="420" Height="452"
       x:Name="image" Canvas.Left="8" Source="images/viewdemo.png"/> <TextBlock x:Name="textBlock1"></TextBlock> </Canvas>

The Web Service

This is a simple asmx web service.  Remember to mark it as a script service by adding the following attribute to the service class:

[System.Web.Script.Services.ScriptService]

You can do whatever you want in the web service of course.  I decided to return a custom type called BannerImage with a few useful properties:

[WebMethod]
  public BannerImage GetNextImageUrl(int lastId)
  {
      //of course in the final code this will return 
//new details each time (from an xml file on the server perhaps)
return new BannerImage() { Url = "images/HappyPhonePeople.png",
                               NavigateUrl = http://www.bbc.co.uk,
                               ImageId=lastId+1 }; }

BannerImage looks like this:

public class BannerImage
{

    public string Url { get; set; }
    public string NavigateUrl { get; set; }
    public int ImageId { get; set; }

}

The JavaScript

The JavaScript does all the work of controlling the interaction with the Silverlight Xaml and calling the web service.  The code below hooks up various events and calls the web services as required (see the next section for detail on how the web service proxy was created) 

if (!window.ImagesRotation)
    ImagesRotation = {};

ImagesRotation.Page = function() 
{
}

ImagesRotation.Page.prototype =
{
    handleLoad: function(control, userContext, rootElement) 
    {
        this.control = control;
        this.storyboard1 = control.content.findName("Storyboard1");
        this.image1 = control.content.findName("image");
        this.textBlock1 = control.content.findName("textBlock1");
        this.bannerImage = null;
        this.GetNextImage(0);
        this.storyboard1.addEventListener("Completed",
                    Silverlight.createDelegate(this, this.storyboard1Completed)); this.image1.addEventListener("MouseLeftButtonUp",
                    Silverlight.createDelegate(this, this.imageClick)); }, storyboard1Completed: function(sender, eventArgs) { var id = this.bannerImage.ImageId; this.GetNextImage(id); }, GetNextImage: function(id) { //BannerImages is the web service proxy created us by the
// scriptmanager when we add a service reference
BannerImages.GetNextImageUrl(id,Silverlight.createDelegate(this,this.onSuccess),
                      Silverlight.createDelegate(this,this.onFailure)); }, imageClick: function(sender, eventArgs) { location.href = this.bannerImage.NavigateUrl; }, onSuccess: function(result) { this.bannerImage = result; this.image1.source = this.bannerImage.Url; if (this.bannerImage.NavigateUrl != "") { this.image1.cursor = "Hand"; } else { this.image1.cursor = "Arrow"; } this.storyboard1.Begin(); this.textBlock1.Text = this.bannerImage.ImageId.toString(); }, onFailure: function(result) { this.textBlock1.Text = "error: " + result.get_message(); } }

The Aspx Page

The final piece is the Aspx page that hosts the Silverlight control and adds a client side service reference.  First the ScriptManager.  Here I have 3 script references to Silverlight.js (the standard silvelight 1.0 file), Page.Xaml.Js - which is where I have the code listed above, and what I have called master.js which has the standard createSilverlight method in it.  This is the code that gets generated for you by Blend or VS2008.  I also have a service reference to the BannerImages.asmx web service detailed above:

<asp:ScriptManager ID="ScriptManager1" runat="server">
        <Scripts>
            <asp:ScriptReference Path="~/js/master.js" />
            <asp:ScriptReference Path="~/js/Page.xaml.js" />
            <asp:ScriptReference Path="~/js/Silverlight.js" />
        </Scripts>
        <Services>
            <asp:ServiceReference Path="~/WebServices/BannerImages.asmx" />
        </Services>
    </asp:ScriptManager>

All that is left to do now is to host the Silverlight control on the page somewhere:

<div id="silverlightControlHost" style="float:right;
            height: 300px; width: 300px;">
         <script type="text/javascript">createSilverlight();</script> </div>

 

Hope this helps someone!

Cheers

Ian

 

IE8: Principles vs Pragmatism

Joel Spolsky has an entertaining and thought provoking read on why IE8 renders Google maps and live maps so poorly.  Actually it is much more than that and Joel does a great job of explaining the battle between having IE8 default to the new "standard" rendering model, or to the old IE7 one.  He concludes:

You see? No right answer.  As usual, the idealists are 100% right in principle and, as usual, the pragmatists are right in practice. The flames will continue for years. This debate precisely splits the world in two. If you have a way to buy stock in Internet flame wars, now would be a good time to do that.

IE8 has a tough job ahead, that's for sure, and a lot depends on web developers recognising the changes that it will bring.  As Joel points out, a major problem is how different browsers interpret the CSS standards.  CSS 2.1 is very complex and not always clear, and it is no surprise that we have browsers that interpret it differently. 

Perhaps the most significant part of IE8 release then is the development by Microsoft of CSS 2.1 Test Pages  which they have submitted to the W3C for inclusion into the W3C’s CSS Working Group Test Suite.  This is good news for all if adopted, because a test suite is exactly what we need and the current one by the W3C's working group is by their own admission "woefully incomplete and contains many incorrect tests".  Having a full and complete test suite for CSS 2.1 brings pragmatism to the principles, and if adopted by all browser venders, means those shares in the flame wars will have been money down the drain.

Cheers

Ian

Technorati Tags: ,,,

Learning Linq with LINQPad

If you are getting into LINQ - then this free, copy and run app, is a great way to play with it.

It's a companion to C# 3.0 in a Nutshell but it is valuable without the book, and comes with 200 samples!

Recommended!

 

Cheers

 

Ian

Technorati Tags: ,,,

Multiple Administrators for Windows Live Domains

Windows Live Domains is an easy way for you to get free "Hotmail" type accounts for a domain you own.  You simply visit domains.live.com and follow the instructions.  This will eventually open up an Admin Centre that you can use to manage accounts, set-up co-branding, and generate a sign-up module.  You authenticate as an administrator for the domain via an existing live id account, and by making a change to DNS for the domain you want to manage (thereby proving you own or manage it)

Since this authentication is tied to an existing live id, this seemed to imply that only one administrator account could be created.  However the help file offers another solution:

You can have multiple administrator accounts for your custom domain. Each administrator must register the domain on the Admin Center website and enter the MX record (An MX record specifies which server in your domain should receive incoming e-mail.) that's associated with that administrator at your registrar's (A company that is accredited to sell Internet domain names.) or DNS (The DNS (Domain Name System) helps your computer find other computers and websites on the Internet. A domain may provide a website (such as www.wingtiptoys.com) and e-mail (such as me@wingtiptoys.com), among other services.) provider's website.

Seems like a rather strange way of allowing multiple admins, and you will be at the mercy of your DNS provider allowing multiple MX records for your domain (www.zoneedit.com allows a maximum of 5 for example), but it does work.

UPDATE: Turns out ZoneEdit does support more than 5 MX entries - but only 5 priorities, which is fine for this.

Alternatively you do have the Api which you can use to manage your domain accounts, so if the MX entries is too limiting that would have to be the route to take.

Cheers

Ian

Expression Web 2 - some nice new features

Gary Pretty has a detailed post on some of the new features in Expression Web 2  - I hadn't realised there was so much goodness in it! 

 Gary lists the following:

  •  PHP Support - PHP Intellisense and syntax highlighting, and previewing of PHP sites locally, without the need for a separately installed web server
  • ASP.Net & AJAX Controls  - full support for the standard ASP.Net Ajax controls to simply drag and drop them into your page
  • Silverlight 1.0, Windows Media & Flash -  drop your Silverlight 1.0 applications straight into your site using Expression Web 2
  • Photoshop Support - import any PSD (Photoshop) file and convert it to an optimised image file format

Some neat stuff there!

Cheers

Ian

 

Exporting GeoRSS from a Virtual Earth Collection

There is currently no api method for turning a Virtual Earth Collection from maps.live.com into a GeoRss file.

However there is a workaround that you can use as follows:

  1. Open your collection on maps.live.com
  2. Click the Share button and select either "Send in e-mail" or "Copy to clipboard" - what you want is the URL for the collection
  3. Visit the URL in the clipboard or the e-mail - it will be something like: http://maps.live.com/?v=2&cid=FB8B852EF1AB0B35!519&encType=1 
  4. When the collection is displayed you will see a Subscribe link at the top of the collection items in the left panel.  Click on that to open the GeoRss feed.
  5. IE will open it and format it, but you can view source or save it to file to get the raw GeoRss data.

With thanks to Derek (MSFT) for originally posting this on the VE Forum back in October last year - I recently needed to do this again, and searched for the comment.  I thought a blog post might help people find it more easily in the future...

Cheers

Ian

 

UPDATE:  In VE 6.1 this is now a feature of the UI at maps.live.com, just select Export from your collections Action menu - so no need for this procedure any more!

Technorati Tags: ,,

Code Samples and Resources

MSDN Code gallery: http://code.msdn.microsoft.com

I wasn't aware of this until someone pointed it out in a presentation at Mix this year.

It is a growing set of code samples and resources created by and for the community.  There is already a lot of good stuff there: 

Here are a few that have caught my eye:

 

Cheers

 

Ian

Technorati Tags: ,

Virtual Earth JavaScript Intellisense

Virtual Earth has a great api, better than Google Maps IMHO, but JavaScript is PITA if you have no editor support.  VS2008 has brought Intellisense to many JavaScript scenarios, but not to VE development - up until now that is.

A Code Plex project (that I had the pleasure to be involved in, though in a tiny tiny way, because the project was completed so quickly! - I expect to be more involved in future iterations) has made it easy to have JavaScript Intellisense for VE in Visual Studio.

The Virtual Earth: An Evangelist's Blog has a good write up but here's a screen shot to wet your appetite, and some step by step installation instructions to get you started:

image

Using the Example Solution

To get started and use the provided solution:

  1. Download the VE JavaScript Intellisense Helper zip file
  2. Unzip the files and you will get a folder with a VS2008 solution.  You can open this solution up directly in VS 2008 and start writing JavaScript in Default.aspx.js straight away - you will get the Intellisense automatically.

 

image

Including VE JavaScript Intellisense in an Existing Solution

To included the JavaScript Intellisense in an existing project:

  1. Copy the VEJS folder into the web site
  2. Create a JS file (a common naming convention is to use the AspxPageName.aspx.js though you can use whatever you want) and add a reference to the VE JavaScript Helper using the following syntax:image

    /// <reference path="VEJS/VeJavaScriptIntellisenseHelper.js" />
  3. In the page you want to use Virtual Earth on add a JavaScript reference to the VE control and to the JavaScript file you created in step 2.  You can either use the ScriptManager (if you are using Asp.Net 3) or normal script tags:

<script type="text/javascript" src="Default.aspx.js"></script>
<script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6"></script>




Or:
<asp:ScriptManager ID="ScriptManager1" runat="server">
    <Scripts>
        <asp:ScriptReference 
            Path="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6" />
        <asp:ScriptReference 
            Path="Default.aspx.js" />
    </Scripts>
</asp:ScriptManager>

Cheers

 

Ian

Automatically Scaling Content in Full Screen Mode in Silverlight 2

Technorati Tags: ,

Silverlight has great full-screen support, and it is a simple matter to switch to full screen by setting the IsFullScreen property of the content object as follows.  Note for security reasons this can only be done in response to user input; note also that this code has changed from version 1.1 alpha

 
//get the plugin content object
System.Windows.Interop.Content content =  Application.Current.Host.Content;


public Page()
{
    InitializeComponent();

    // wire up key down and full screen changed events
    this.KeyDown += new KeyEventHandler(Page_KeyDown);
    content.FullScreenChanged += new EventHandler(Content_FullScreenChanged);
    
}

void Page_KeyDown(object sender, KeyEventArgs e)
{
    // go full screen when F is pressed (esc will take us out of full screen)
    if (e.Key == Key.F )
    {
        content.IsFullScreen = true;
    }
} 
        

However Silverlight does not automatically scale your content automatically, so by default you will typically be left with a lot of empty space.  It turns out though that this is pretty easy to fix - we can simply hook up the FullScreenChanged event, work out the change in size and then apply a ScaleTransform to our control:

void Content_FullScreenChanged(object sender, EventArgs e)
 {
     //scale content if we are in full screen.
     if (content.IsFullScreen)
     {
         double heightRatio = content.ActualHeight / this.Height;
         double widthRatio = content.ActualWidth / this.Width;
         ScaleTransform scale = new ScaleTransform();
         scale.ScaleX = widthRatio;
         scale.ScaleY = heightRatio;
         this.RenderTransform = scale;
     }
     else
     {
         this.RenderTransform = null;
     }
 }

Cheers

 

Ian

.Net/Silverlight Tools and Versions Summary

Technorati Tags: ,,

I was recently asked to detail the various .net and Silverlight versions in a simple table - here's my attempt (this is all available at www.asp.net/downloads but I must admit I found it useful to try and summarise the essentials here)

Version Released Tools Summary Comments
.net 1.1 2003 VS 2003 You can only use Visual Studio 2003 to work with .net 1.1 apps
.net 2.0 2005 VS 2005/VS 2008 You can target .net 2 with VS 2008
.net 3.0 2006 VS 2005/VS 2008

You will need to install the .net 3 tool support for VS 2005 separately - it is included in VS 2008.

.Net 3 includes:

  • Windows Presentation Foundation (WPF)
  • Windows Communication Foundation (WCF)
  • Windows Workflow Foundation (WF)
  • Windows CardSpace

Tools for VS 2005:

.net 3.5 2008 VS 2008

Silverlight 1.0 2007 VS 2008 with tool Support for code.
Expression Blend 2 for UI design

Silverlight UI with XAML, JavaScript for interaction.  See Silverlight Feature Matrix for more details.

Silverlight 1.1 Alpha 2007 Discontinued - use Silverlight 2.0 Beta instead  
Silverlight 2.0
Beta
2008 VS 2008 with tool Support for code
Expression Blend 2.5 Preview
Silverlight UI with XAML, rich controls, managed code. 

See Silverlight Feature Matrix for more details.

Asp.Net 3.5
extensions
Preview
2008 VS 2008 with add-on

This preview adds new features for asp.net that sit on top of .net 3.5 (confusingly some of the assemblies in the preview are versioned as 3.6)

The new features include:

 

Hope this helps.

Cheers

Ian