Getting Silverlight 3 Service References to work in Visual Studio 2010 Beta 2

I just downloaded and installed Visual Studio 2010 Beta 2 and decided to roll over a large Silverlight project I was working on to see how things would go.

Here are a few gotcha’s I encountered:

  1. Server side Unit Tests  were working with Membership providers but I was getting an error saying that these have been forwarded to System.Web.ApplicationServices.  What I didn’t realise is that for all the marketing guff around multi-targeting, your out of luck if you actually have unit tests in .NET 3.5, because unit tests have to be upgraded to .NET 4.  Thankfully it seems this can be easily worked around by leaving all the projects except the Unit Tests in .NET 3.5 and adding a reference to System.Web.ApplicationServices for the unit test project.
  2. Silverlight 3’s Service References were completely broken by Visual Studio in the upgrade process, so much so that I was getting errors and warnings about the service references. I think this might have had a little to do with the custom service host I had developed, but the only way I could fix it was to completely delete the Service References and then add them again, unfortunately for some reason I couldn’t use Visual Studio to delete some of the Service References. Click Delete –> nothing happens, the only way I could do it was to do this:
    1. Manually delete the service reference folder in Explorer.
      image
    2. Go to Visual Studio and exclude all the files under the service reference folder:
      image
    3. Then delete the empty folder from Visual Studio.
      image
    4. I was then free to add the Service Reference again to my Silverlight project via the Add Service Reference dialog and everything was fine.

Hope this helps someone else!

Leave a comment

Super Light Weight Multi-threaded code with ExclusiveSection

Something that has always bugged me about the .NET Base Class Library is the absence of a threading lock that would reliably tell me whether another thread was already doing something, and if so, not to block and wait for it, but just to continue on as if nothing has happened.

This becomes super useful in many multi-threaded situations, one of the main ones being User Interface threading where the foreground thread is requesting some data via an asynchronous call. Typically in this scenario, if the user makes a selection from the UI, you want the request to be sent, but if a request is already running, to ignore the user’s selection until you’re done getting the previous requests data, then at the end you can check if there was a contention and re-execute if necessary. This results in the UI remaining responsive (as in there are no locks to wait for on the foreground thread) but still ensuring the application stays in sync with the users requests.

The example I’ll give is a Windows Forms application (although it could just as easily be a WPF or Silverlight application) that searches the web and displays the html result in a textbox. I want this to be super responsive so I’ve made the application search as the user types.

Now a simple way of approximating the threading behaviour I’m after is just checking a boolean and then setting it, like so:

Code Snippet
  1.         private bool _isSearching = false;
  2.         private void SearchQueryTextBox_TextChanged(object sender, EventArgs e)
  3.         {
  4.             SearchWebAsync(SearchQueryTextBox.Text);
  5.         }
  6.         private void SearchWebAsync(string searchText)
  7.         {
  8.             if (!_isSearching)
  9.             {
  10.                 _isSearching = true;
  11.                 WebClient client = new WebClient();
  12.                 Uri searchUrl = new Uri("http://www.google.com/search?q=" + searchText);
  13.                 client.DownloadStringCompleted += WebClient_DownloadStringCompleted;
  14.                 client.DownloadStringAsync(searchUrl);
  15.             }
  16.         }
  17.         private void WebClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
  18.         {
  19.             if (!e.Cancelled && e.Error == null)
  20.             {
  21.                 SearchResultsTextBox.Text = e.Result;
  22.             }
  23.             _isSearching = false;
  24.         }

The problem with this code is that it can’t tell me whether the user changed their text and clicked again while the WebClient was still performing the first search and it isn’t particularly thread safe if I wanted to fire off the search from a background thread.

What’s wrong with Monitor.TryEnter?

There are a few things that have bugged me about Monitor.TryEnter, the main one being that the thread that calls Exit must be the thread that originally called TryEnter. This is all well and good in some scenarios, but in the above example it would mean I would have to call SearchWebAsync always from the UI thread. The other obvious point about Monitor.TryEnter is it doesn’t track how many times TryEnter has been attempted for a particular lock object. Not to mention it uses locking and not Interlocked statements (which are faster so I’m told although I’ve yet to see any benchmarks which say just how much faster).

Enter the ExclusiveSection class (or should I say TryEnter?)

An ExclusiveSection is used similarly to a lock in that you create an instance and then attempt to enter that section, when you do so, the ExclusiveSection.TryEnter method will return whether you were successful or not, if not you can then simply exit, knowing that the ExclusiveSection has remembered that you asked to do so.

Code Snippet
  1.     public sealed class ExclusiveSection
  2.     {
  3.         private long _entryAttempts;
  4.         /// <summary>
  5.         /// Returns true if there was more than one call to TryEnter before exiting
  6.         /// </summary>
  7.         public bool HasContention
  8.         {
  9.             get
  10.             {
  11.                 return (Interlocked.CompareExchange(ref _entryAttempts, 0, 0) > 1);
  12.             }
  13.         }
  14.         /// <summary>
  15.         /// Ensures the caller was the first to enter the Exclusive Section (Thread-safe)
  16.         /// </summary>
  17.         /// <returns>Returns True if the Exclusive Section was entered</returns>
  18.         public bool TryEnter()
  19.         {
  20.             return (Interlocked.Increment(ref _entryAttempts) == 1);
  21.         }
  22.         /// <summary>
  23.         /// Attempt to exit, useful when exits and enters are called abitrarily,
  24.         /// ensures only one exit ever succeeds.
  25.         /// </summary>
  26.         /// <returns>Returns True if the caller was the last to exit (based on the
  27.         /// number of TryEnter calls that were made)</returns>
  28.         public bool TryExit()
  29.         {
  30.             long result = Interlocked.Decrement(ref _entryAttempts);
  31.             if (result == 0)
  32.             {
  33.                 return true;
  34.             }
  35.             else if (result < 0)
  36.             {
  37.                 // Someone beat us to the punch, reset to the counter
  38.                 // to Zero to ensure we are able to enter again properly
  39.                 ExitClean();
  40.                 return false;
  41.             }
  42.             return false;
  43.         }
  44.         /// <summary>
  45.         /// Exits an Exclusive Section immediately regardless of how many calls
  46.         /// had previously been made to TryEnter and returns true if there
  47.         /// was no contention.
  48.         /// </summary>
  49.         /// <returns>Returns True if there was no more than one call to
  50.         /// TryEnter before the call to ExitClean was made</returns>
  51.         public bool ExitClean()
  52.         {
  53.             return (Interlocked.Exchange(ref _entryAttempts, 0) == 1);
  54.         }
  55.     \

The Final Result

Now I can change my code so that it uses an Exclusive Section to ensure the code only ever performs a single query at a time, and but the most recent text query entered by the user is always respected.

Code Snippet
  1.         private ExclusiveSection _searchSection = new ExclusiveSection();
  2.         private void SearchQueryTextBox_TextChanged(object sender, EventArgs e)
  3.         {
  4.             SearchWebAsync(SearchQueryTextBox.Text);
  5.         }
  6.         private void SearchWebAsync(string searchText)
  7.         {
  8.             if (_searchSection.TryEnter())
  9.             {
  10.                 WebClient client = new WebClient();
  11.                 Uri searchUrl = new Uri("http://www.google.com/search?q=&quot; + searchText);
  12.                 client.DownloadStringCompleted += WebClient_DownloadStringCompleted;
  13.                 client.DownloadStringAsync(searchUrl);
  14.             }
  15.         }
  16.         private void WebClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
  17.         {
  18.             if (!e.Cancelled && e.Error == null)
  19.             {
  20.                 SearchResultsTextBox.Text = e.Result;
  21.             }
  22.             if (!_searchSection.ExitClean())
  23.             {
  24.                 SearchWebAsync(SearchQueryTextBox.Text);
  25.             }
  26.         }

Interestingly the call to SearchWebAsync can now be made from any thread, and will remain thread safe, (as long as the WebClient_DownloadStringCompleted event performed an Invoke on the UI thread to access the Windows Forms controls). This could be useful if you wanted to add a timer thread that fires off a call to refresh the search results every 30 seconds or so.

This kind of threading class is extremely useful in Silverlight where only asynchronous calls to get data are allowed.

Hope you find the ExclusiveSection class as useful as I do!

http://cid-17124d03a9a052b0.skydrive.live.com/embedrowdetail.aspx/Public/ExclusiveSectionDemo.zip

Leave a comment

Uploading multiple files from Silverlight using an ASP.NET Compatible HTTP POST

I was recently trying to make Silverlight upload multiple files to an ASP.NET page using a valid HTTP form POST. It was important that the HttpContext.Request.Files property worked correctly. Little did I realise just how finicky ASP.NET is with HTTP requests. It is critical that TWO line feeds are added between the content-type header in the boundary and the binary data, and ONE line feed must be included after the data prior to the next boundary.

Here’s the Silverlight code:

public static class HttpHelper
{
    public static void UploadFilesAsync(Uri address, IEnumerable<FileInfo> files, Action<string> onCompleted)
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(address);
        request.Method = "POST";
        string boundary = "-----------------------------" + Guid.NewGuid().ToString().Substring(0, 8);
        request.ContentType = "multipart/form-data; boundary=" + boundary;
        request.BeginGetRequestStream((getRequestResult) =>
        {
            using (Stream requestStream = request.EndGetRequestStream(getRequestResult))
            {
                IEnumerable<FileInfo> uploadFiles = (IEnumerable<FileInfo>)getRequestResult.AsyncState;
                foreach (var uploadFile in uploadFiles)
                {
                    using (Stream fileStream = uploadFile.OpenRead())
                    {
                        WriteText("--" + boundary + Environment.NewLine, requestStream);
                        WriteText(@"Content-Disposition: form-data; name=""fileUpload""; filename=""" + uploadFile.Name + @"""" + Environment.NewLine, requestStream);
                        WriteText(@"Content-Type: application/octet-stream" + Environment.NewLine + Environment.NewLine, requestStream);

                        WriteData(fileStream, requestStream);

                        WriteText(Environment.NewLine, requestStream);
                    }
                }
                // Output the final closing boundary
                WriteText("--" + boundary + "--" + Environment.NewLine, requestStream);
            }
            
            request.BeginGetResponse((getResponseResult) =>
                {
                    var response = request.EndGetResponse(getResponseResult);
                    string responseText = null;
                    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                    {
                        responseText = reader.ReadToEnd();
                    }
                    onCompleted(responseText);
                }, null);
        }, files);
    }

    private static void WriteText(string input, Stream output)
    {
        var bytes = UTF8Encoding.UTF8.GetBytes(input);
        output.Write(bytes, 0, bytes.Length);
    }

    private static void WriteData(Stream input, Stream output)
    {
        byte[] buffer = new byte[4096];
        int bytesRead;
        while ((bytesRead = input.Read(buffer, 0, buffer.Length)) != 0)
        {
            output.Write(buffer, 0, bytesRead);
        }
    }
}

You can then use this helper in your code like so:

OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "All Files (*.*)|*.*";
ofd.Multiselect = true;
if (ofd.ShowDialog().GetValueOrDefault())
{
    HttpHelper.UploadFilesAsync(new Uri("ReadFiles.ashx", UriKind.Relative), ofd.Files,
        (responseText) =>
        {
            Console.WriteLine("Response was: " + responseText);
        });
}

For the ASP.NET code I added a generic handler called ReadFile.ashx and just as proof that it works, I wrote out the number of files that were uploaded.

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class ReadFile : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/xml";
        context.Response.Write("<Result>" + context.Request.Files.Count + 
            " Files Uploaded</Result>");
    }
}

Hope this helps someone else out.

Enjoy!

Leave a comment

Fast Enum.TryParse implementation

I recently saw a post asking why there wasn’t an Enum.TryParse in .NET. I’ve forgotten where the post was, but I found myself needing this so I implemented it myself. It notably doesn’t use a try { } catch { } block so performance should be pretty good.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public static class EnumExtensions
{
    public static bool EnumTryParse<T>(this string enumText, out T enumValue) 
        where T : struct
    {
        enumValue = default(T);
        if (Enum.IsDefined(typeof(T), enumText))
        {
            enumValue = (T)Enum.Parse(typeof(T), enumText);
            return true;
        }
        return false;
    }
}

Usage:

string unparsedEnumText = "SomeText";
MyCoolEnum parsedEnum;
if (unparsedEnumText.EnumTryParse(out parsedEnum))
{
    Console.WriteLine("Parsed OK as " + parsedEnum.ToString());
}

Note: .NET doesn’t allow for System.Enum to be defined as a type constraint so be careful!

Enjoy!

Update: Changed to use Enum.IsDefined instead of Enum.GetNames

2 Comments

Flexible and Easy to Build Data Entry Forms in WPF

One of the things I find I’m often building in a WPF app is a nicely laid out Data Entry Form, with Label: TextBox combinations all down the page.

So usually you might build a form like this:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <TextBlock
        Text="First Name: " />
    <TextBox Grid.Column="1"
        Text="{Binding Path=FirstName}" />
</Grid>

The problem with this comes when you need to add another field you can’t just add it to the bottom, you have to add Row Definitions to the grid and manually specify the row for each TextBlock and TextBox.

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <TextBlock
        Text="First Name: " />
    <TextBox Grid.Column="1"
        Text="{Binding Path=FirstName}" />
    <TextBlock Grid.Row="1"
        Text="Last Name: " />
    <TextBox
        Grid.Row="1"
        Grid.Column="1"
        Text="{Binding Path=LastName}" />
</Grid>

Now imagine you have 20 fields in this form, and you need to insert Middle Name between First and Last name… You’d have to re-number the rows for EVERY TextBlock and TextBox in the grid!!

The Better Way

What you’d like to be able to do is just add these Label/Field combinations in wherever and they all get stacked on top of each other.

So why not use a StackPanel? Well the problem with having all of your TextBLock and TextBox combinations in a StackPanel is the column widths no longer align. Here’s how you get around that:

<StackPanel
    Grid.IsSharedSizeScope="True">
    <StackPanel.Resources>
        <ControlTemplate
            x:Key="LabelledTextBox"
            TargetType="{x:Type ContentControl}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition
                        SharedSizeGroup="Label"
                        Width="Auto" />
                    <ColumnDefinition
                        SharedSizeGroup="Content"
                        Width="*" />
                </Grid.ColumnDefinitions>
                <TextBlock
                    Text="{TemplateBinding Content}" />
                <TextBox
                    Grid.Column="1"
                    Text="{Binding Path=.}" />
            </Grid>
        </ControlTemplate>
    </StackPanel.Resources>
    <ContentControl
        Template="{StaticResource LabelledTextBox}"
        Content="First Name: "
        DataContext="{Binding Path=FirstName}" />
    <ContentControl
        Template="{StaticResource LabelledTextBox}"
        Content="Last Name: "
        DataContext="{Binding Path=LastName}" />
</StackPanel>

Now if you need to add a Middle Name you just have to insert a content control where it belongs. These even gives you the flexibility to have different templates for different field types e.g. a LabelledDropDownList template could be added.

Enjoy!

Leave a comment

Find a control in a WPF/Silverlight Visual Tree by name

Here’s a handy function for finding a specific child in a visual tree. This is useful for finding PART_ elements defined in a style by a ControlTemplate or DataTemplate etc.

public static T FindVisualChildByName<T>(DependencyObject parent, string name) where T : DependencyObject
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
    {
        var child = VisualTreeHelper.GetChild(parent, i);
        string controlName = child.GetValue(Control.NameProperty) as string;
        if (controlName == name)
        {
            return child as T;
        }
        else
        {
            T result = FindVisualChildByName<T>(child, name);
            if (result != null)
                return result;
        }
    }
    return null;
}

3 Comments

First Impressions of the Windows 7 Beta

I installed Windows 7 beta a couple of days ago and, so far so good, first impressions are that it is a very nice operating system. I think this because Vista is a nice operating system (once you got to know it) and Windows 7 is very, very similar. Sure there’s some taskbar eye candy, some nice cleaning up of areas but it is essentially just a step up.

User Account Control

What User Account Control? Honestly once your Vista machine was setup you hardly ever saw the UAC prompts anyway, but in Windows 7 you almost never see them by default, especially when doing things like changing Control Panel settings, and showing all processes from Task Manager. This is sensible to me, fair enough ask me for admin rights when installing an application, but when I’m running Window’s own Control Panel and changing a setting I don’t want to be prompted. After all if we can’t trust the operating system what can we trust?

Control Panel

Control Panel has fixed a few things like you can actually search for programs found under Administrative Tools, want to access the Services MMC just search for services… it used to piss me off no end that it wouldn’t search Administrative Tools.

Libraries

Windows now has what are known as Libraries, which are essentially aggregated searches across local and remote folders (and even removable drives such as USB sticks). I think this will hopefully be an area that will be expanded upon in the future, as it has great potential not just for making it easier to find stuff, but for making it easy to tell applications where to find stuff. Example Windows Media Player and Windows Media Center both use the libraries to know where all your media is at. This is cool. No more telling all your media apps where you music is at. I just hope that they can do this for things like Contacts and favourites and everything else, essentially allowing users to tell apps to find my files by category.

The bad thing about libraries is they have replaced the “My ????” folders in explorer.

image 

This is sort of good, but it makes my initial setup a bit more painful. Normally I point all my user and public folders from my C:\Users folder where windows is installed and point them to my D:\Users folder. I do this to make it easy if I decide to wipe the OS drive and install a new operating system such as, say, oh I don’t know, Windows 7 for example. This way I have one drive that has all my personal files on it. Libraries made this process a little more painful because at first I thought, hey cool, I don’t need to do this anymore, I just add the D:\Users folders to my libraries… But then I realised that the “My ????” Folders are still used by other apps etc. and while libraries are great for finding things, they’re not so great for saving to.

Windows Media Center

I love Windows Media Center in principle, but the reality of it pains me. Don’t get me wrong the new UI is nice and neat and I love the fact that plays DIVX out of the box. But oh my god it is painful to get working with Xbox 360 Media Extender. I believe this has to be a Beta issue, but I had to go into Services and enable all the Windows Media services, and then I was getting networking and firewall issues and it was timing out. For a long time I could only manage to get the Xbox 360 setup as an extender, but not successfully connect, it just sat at the “Contacting….” screen and would eventually time out. I have had it start once or twice on me but it was very flaky. Another cause of this could my wireless network.. time to upgrade to Wireless+N I think…

Leave a comment