background image
  logo  
Icon

In Defense of Portrait Mode

Tue May 11th 2010 by Brett
For years I wondered about the utility of running monitors in portrait mode. I tried it a couple of times an while reading websites was fantastic in this orientation there were many other applications that just didn't work well. Thanks to Visual Studio 2010 and multiple monitors I think I now have reached a state of nirvana.



One of the nice new features of VS 2010 is that it supports tearing off toolbars and code windows and positioning them outside of visual studio. In the screens above you can see that I have taken the tools window and moved it off to the left monitor - giving me enough width to see a full line of code. Without a second monitor things are just too narrow for this to be effective (unless you are a fan of the auto-hide features which I am not). Being able to see a huge vertical column of code definately reduces the aggravation of having to constantly scroll. I also like how much vertical room it leaves for the solution explorer, which leads to less expanding/collapsing of the tree to get to your files.

The leftmost monitor of course operates in landscape mode which in my mind is necessary to support apps that don't work well in portrait mode. Terminal services is a great example of this. I am constantly TS-ing into other boxes to perform updates/code pushes/etc and 1080 pixes of width on the portrait monitor just doesn't cut it.

Since I have adopted this setup I normally keep VS running on the right monitor maximized. The left monitor holds a half screen outlook and a half screen browser for reference purposes. When I am doing serious reading I use the Windows 7 window snapping shortcuts (Windows-Left/Right/Up) to move the browser to the portrait montior for some serious content absorption.



Of course this has me seriously considering a third landscape monitor for the right side....

0 Comments     follow

Login to post comments
Icon

ModalDialogManager - A simple approach to dealing with modal dialogs in MVVM

Wed Mar 3rd 2010 by Brett
The more I work with MVVM the more I like it. That being said when I started using the pattern early last year I would run into conceptual roadblocks that would halt my progress and kill productivity. One of those concepts that got me stuck was how to deal with modal dialogs. MVVM cleverly uses databinding to decouple the View from the ViewModel - and there is a lot you can do with databinding in WPF. Opening modal dialogs is not one of them.

The issue centers around the face that a Window in WPF cannot be added to a XAML document anywhere other than the root. This would prevent some kind of strategy where you inlined the window in the xaml and invoked the ShowDialog method via binding. (Aside from that - it would lead to some really huge and ugly XAML files.

I solved this problem by creating a Control called ModalDialogManager that I place in the View acting as the parent to the Modal dialog. This control has several properties - one of which called IsOpen which can be used to control the visibility of the dialog. There are also properties for controlling the size of the resultant dialog, resize mode, icon, and the ICommand to be called if the user clicks the Red X.
<Window>
     <Grid>  
          <Button HorizontalAlignment="Right" Command="{Binding ShowMessageCommand, Mode=Default}" 
             Content="{Binding ShowMessageLabel}" VerticalAlignment="Bottom" Margin="0,0,13,8">
          <Button Width="3" Height="0" HorizontalAlignment="Right" 
             Content="Button" VerticalAlignment="Bottom" Margin="0,0,-210,-256">  
 
          <!-- Define ModalDialogManager and wire up to ViewModel called MessageWindow --> 
          <local:ModalDialogManager Title="{Binding Title}" CloseCommand="{Binding OKCommand}" DialogResizeMode="NoResize"
             DialogWidth="300" DialogHeight="300" IsOpen="{Binding IsOpen}" DataContext="{Binding MessageWindow}" />  
          <TextBlock Margin="21,27,31,64" TextWrapping="Wrap" Text="{Binding Status, Mode=Default}"></TextBlock>  
     </Grid>  
</Window> 


There is one important thing that might not be immediately obvious - when the dialog is shown it will use the same DataContext as the ModalDialogManager. A content presenter at the Root of the modal dialog (Window) will be bound to the ViewModel. Therefore you have to use a DataTemplate to associate a View to this ViewModel. In the sample project I do this in App.xaml.

<DataTemplate DataType="{x:Type vm:MessageWindowViewModel}">
     <v:MessageWindow/>
</DataTemplate>
As soon as the MainViewModel invokes the IsOpen property on the MessageWindowViewModel the dialog will be show and code execution will be transferred to the MessageWindowViewModel. This is a boon, because setting IsOpen acts just like ShowDialog in that after the dialog is closed code excution will resume on the next line. Here are the interesting bits about how the ModalDialogManager class works.
        /// 
        /// This is invoked when the red X is clicked or a keypress closes the window - 
        /// 
        public ICommand CloseCommand
        {
            get { return (ICommand)GetValue(CloseCommandProperty); }
            set { SetValue(CloseCommandProperty, value); }
        }
        public static readonly DependencyProperty CloseCommandProperty =
            DependencyProperty.Register("CloseCommand", typeof(ICommand), typeof(ModalDialogManager), new UIPropertyMetadata(null));


        /// 
        /// This should be bound to IsOpen (or similar) in the ViewModel associated with ModalDialogManager
        /// 
        public bool IsOpen
        {
            get { return (bool)GetValue(IsOpenProperty); }
            set { SetValue(IsOpenProperty, value); }
        }
        public static readonly DependencyProperty IsOpenProperty =
            DependencyProperty.Register("IsOpen", typeof(bool), typeof(ModalDialogManager), new UIPropertyMetadata(false, IsOpenChanged));


        public static void IsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ModalDialogManager m = d as ModalDialogManager;
            bool newVal = (bool)e.NewValue;
            if (newVal)
                m.Show();
            else
                m.Close();
        }


        void Show()
        {
            if (_window != null) Close();

            Window w = new Window();
            _window = w;
            w.Closing += w_Closing;
            w.Owner = GetParentWindow(this);
            
            w.DataContext = this.DataContext;
            w.SetBinding(Window.ContentProperty, "");

            w.Title = Title;
            w.Icon = Icon;
            w.Height = DialogHeight;
            w.Width = DialogWidth;
            w.ResizeMode = DialogResizeMode;
            w.ShowDialog();
        }

        void w_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (!_internalClose)
            {
                _externalClose = true;
                if (CloseCommand != null) CloseCommand.Execute(null);
                _externalClose = false;
            }
        }

        bool _internalClose = false;
        bool _externalClose = false;

        void Close()
        {
            _internalClose = true;
            
            if (!_externalClose) _window.Close();
            _window = null;
            _internalClose = false;
        }

        Window GetParentWindow(FrameworkElement current)
        {
            if (current is Window)
                return current as Window;
            else if (current.Parent is FrameworkElement)
                return GetParentWindow(current.Parent as FrameworkElement);
            else
                return null;
        }

A sample project can be downloaded here. Sorry - no Silverlight version yet, but it is on the way.

2 Comments     follow

Hi,

This is by far the most clean and ingenious way I've yet seen to solve the problem of modal dialogs in MVVM. It took me quite some time to wrap my head around the way things work but now that I 'get' it, I find it a very clever way of maintaining a separation of the viewmodel and the view.

Thanks you for this. Maybe you could put up an article on CodeProject to give it more exposure?

Bye,
Steven
posted by Steven on Tue Mar 23th 2010 at 8:57 AM
Hi Steven-
Thanks for the feedback! Your right - I probably should post this on Code Project. I have actually made a couple of enhancements since this post to take into account dialogs that execute immediately upon launch (my use case was a cancellable progress dialog). I normally submit my Silverlight posts to Silverlight Cream, but I haven't been able to find a similar community for WPF. Code Project is probably the best bet.
Brett
posted by Brett on Thu Apr 1st 2010 at 1:43 PM
Login to post comments
Icon

SyncToy 2.1 - A very useful and free tool for syncronizing your files

Thu Feb 25th 2010 by Brett
I have a pretty common problem in my household - my wife and I need to share files, but also have access to them we take our laptops off the network. Up until this point we used Windows Offline files. I created shares on the network for all of our "My" folders (documents/pics/music/etc) and moved the location in our profiles to point to those locations. Windows automatically sets them up as offline folders and syncs the files back and forth. This allowed us to share things like our photos and music.

Unfortunately we are users of iTunes. We are forced to do so because we have iPhones (all though not for long - the 7 series phones look great). For whatever reason iTunes would often lose its database including all the playlists etc. This happened more than once, even after complete system rebuilds. I am not sure why this was the case but I suspect that iTunes just wasn't playing nicely with the behind the scenes sync mechanism that Offline files uses. (It uses a local cache that it will dynamically redirect you too if you become disconnected) Also - because all of our My folders were UNCs there were some applications that didn't like that. (CAS in Visual Studio and Live Movie maker are examples)

Now I could disable the Offline Files and just use network shares, but what I like about the sync is that it also gives me better data redundancy. If my workstation dies I have all my important bits on the server as well as a few other machines. Conversely a down server wont stop me from getting access to my files.

I found a replacement that is built on the Microsoft Sync Framework called SyncToy. SyncToy lets you build folder pairs and perform bi-directional sync between them. You can then schedule a sync via Task Scheduler which will automatically propagate your changes. There are some nice options including Syncro (bidirectional sync), Echo (pushes changes in one direction only), and Contribute (which only pushes add/modify/renames in one direction).

So far so good, but I have only been using it for a few days - I'll update this post after I have lived with it for a little while. Download SyncToy 2.1 here.

0 Comments     follow

Login to post comments
Icon

Connecting XBox 360 MCE to Windows 7 in a Domain

Fri Feb 19th 2010 by Brett
I have been having problems getting my XBOX 360 to connect to my Windows 7 Media Center for the last year. I never spent the time to get it working until today. After I performed the normal steps for adding and extender (which would complete successfully) I would get errors on my 360 saying that it could not connect the the Media Center. Sometimes I would get as far as the MCE start page, other times it would fail on the screen with the little white dots below the WMC logo. In any case I found the solution:

Solution
Run gpedit.msc. Go to Computer Configuration -> Administrative templates -> Windows Components -> Remote Desktop Services -> Remote Desktop Session Host -> Security.

Enable "Set client connection encryption level" & change encryption level to 'Client Compatible'. Disable "Always prompt for password upon connection"

I'm guessing these settings don't only apply to Windows 7, but to Vista and XP media centers as well.

0 Comments     follow

Login to post comments
Icon

Introducing TagBox

Tue Feb 16th 2010 by Brett
Recently I wanted to write a TO: box in a Silverlight that worked similar to the one Outlook has. It is a neat control that allows you to "resolve" items based on text matching. Unlike a standard AutoComplete box this control allows you to "resolve" multiple items inline. Once an item is resolved it acts as a cohesive element instead of individual letters - what I call a tag. The tag (a resolved email address in Outlook) can be clicked on which brings up more information about the address. A number of popular sites use this style of control (js based) including Hotmail (the To box obviously) and Facebook (their email function).

Effectively this control allows you to build one-to-many relationships between an email and its intended recipients in a very natural way. Obviously the key to this control working effectively is the excellent keyboardability (is that a work?) that it offers. Aside from the usage described above there are a number of cases where such a control would be useful. One example might be applying a set of categories to a blog post. In an online store example it might be used to define the areas of the store where an item might appear. This control is extremely effective when the relationship between the entities is simple - it can track the relationship and the order of the relationship but no additional data about the relationship.

Example

This example starts with our familiar case of an Email where the user would like to enter a number of email addresses. If you start typing an address it performs an async search for the email address based on name and address. A popup is displayed if matches are found without losing your position in the TagBox and you can presss up and down to navigate the matches. Also - if you enter a valid email format such as test@test.com, you will see it appear in the bound listbox to the right. This control was designed to be databound, and in particular work well in MVVM Patterns.

There are a few interesting properties on the Control:
  • ItemsSource – IList value represents the set of resolved matches in the control. It also supports INotifyCollectionChanged so it can be bound to ObservableCollection allowing external changes to be propagated to the control automatically.
  • DisplayMemberPath – I used a similar name here to what the ListBox control uses to determine which property is displayed when the results are shown either in the tags or the search results.
  • SearchMethod –a Action dependency property provides the logic for taking the text entered and execting a query/lookup that in turn returns SearchResults. This method can be synchronous or asynchronous, so long as the returned results are placed in SearchResults.
  • SearchResults – to support Synchronous or Async searching, when this property is populated search results are shown to the user. Make sure the class to which SearchResults is bound to implements INotifyPropertyChanged so TagBox is aware of SearchResult changes.


In an MVVM scenario the four important properties above you can simply bind these values to a ViewModel. In my example I have an EmailViewModel (implement INotifyPropertyChanged) which is bound as follows (position omitted for clarity).
<tsm:TagBox SearchMethod="{Binding SearchMethod}" SearchResults="{Binding SearchResults}"
          DisplayMemberPath="DisplayName" ItemsSource="{Binding To, Mode=TwoWay}" />
  • ItemsSource -> To (ObservableCollection)
  • DisplayMemberPath = “DisplayName” which is a property of Contact
  • SearchMethod -> SearchMethod(Action which points to a method FindMatchingContacts(string))
  • SearchResults -> SearchResults(IEnumerable)


The following code illustrates the implementation of SearchMethod in EmailViewModel.cs. You will note that although this is a synchronous method in this example SearchResults can be populated as a result of an async web service invokation.

        #region SearchMethod (INotifyPropertyChanged Property)
        private Action<string> _searchMethod;
        public Action<string> SearchMethod
        {
            get { return _searchMethod; }
            set
            {
                if (value == _searchMethod) return;
                _searchMethod = value;
                base.OnPropertyChanged("SearchMethod");
            }
        }
        #endregion

        public void FindMatchingContacts(string searchText)
        {
            if (searchText.Length >= 1)
            {
                var contacts = from cs in ContactCollection.Members
                               where cs.EmailAddress.StartsWith(searchText, StringComparison.InvariantCultureIgnoreCase) 
                                    | cs.DisplayName.ToLower().Contains(searchText.ToLower())
                               select cs;

                SearchResults = contacts.ToList();
            }
            else
                SearchResults = null;
        }
Fig 1. Code from EmailViewModel.cs demonstrating search method

The control does all the heavy lifting and it simply needs to be provided with search logic and search results. This fits well with MVVM and the ViewModel in my example could easily be bound to entirely different lookup UI not dependent on TagBox.

Validation

This aspect of the control probably gave me the most consternation. At a high level the control is dealing with a non homogenous collection of item types. In the example of an email TO: box we have:

  • Contacts: resolved items that were matched via search
  • Text Addresses: unresolved items that may have been entered by the user


In the email case – text addresses are perfectly fine, so long as they pass some kind of validation. So the question became – how do you deal with a non-homogenous collection of items without it being a mess on the ViewModel side (or the non-control side if not using MVVM). Initially – I dealt with the problem by creating two collections – one for resolved that was used for databinding – and another for unresolved that was readonly (trying to synch two collections to the UI was going to be awful). As I got into it I realized this was about as good an idea as a “Larry the Cable Guy” movie (e.g. bad idea).

I realized that ideally the collection would be homogenous, but how to convert text entries into strongly typed objects. I didn’t want to have to expose a special container class outside the control as it would corrupt the layer of separation I was trying to achieve. Ultimately I added an Func UnresolvedValidationMethod property to the TagBox where you can specify your own function for examining the text entered and returning it classed as your bound object type. In the email example I check the format of the address and return a Contact. The great thing about this is that on the ViewModel side you have a single collection that holds all the addresses, and ultimately you could decide how to deal with these newly created contacts. (for example – you could just send a message to them, or you could save them to your Contact repository when you detect that their Ids are 0)

Lastly – there could exist a set of unresolved items that would not validate (if you entered ASDF as an email address for example). These are not included in ItemSource, but can be found in InvalidItems. The logic here is that if we cannot pass the Validation method then they are not robust enough to be included in that set. Instead they are decorated (a dashed underline OOB) and you can decide how to handle them. Common ways would be

  1. In an email scenario – do not allow the message to be sent until they are corrected – could present a custom UI for correcting them.
  2. Prompt and allow them to be discarded
  3. Discard them automatically


Validation Properties

  • ValidateUnresolved – boolean property indicates whether or not validation should be performed – if true an UnresolvedValidationMethod must be provided
  • UnresolvedValidationMethod – Function takes a text entry and converts it to an object compatible with the objects stored in ItemsSource. Once validated the text entry, now a correctly typed object, is placed in ItemsSource in the correct location.
  • VisualState “Invalid” – The UnresolvedTag control template contains an “Invalid” state that can be customized. It is set whenever text cannot be validated.

The following code demonstrates the UnresolvedValidationMethod as implmented in EmailViewModel.cs. Note - asynchronous validation is not supported at this point.

        public Contact IsValidEmailAddress(string email)
        {
            bool valid = Regex.IsMatch(email, @"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" +
                                              @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" +
                                              @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
            Debug.WriteLine("Valid Email? " + email + " " + valid);
            if (!valid) return null;
            return new Contact() { DisplayName = email, EmailAddress = email };
        }
Fig 2. Code from EmailViewModel.cs demonstating text validation

Customization

TagBox is implemented as a CustomControl, meaning that its templates can be customized very easily to provided a dramatically different looking appearance. There are 3 main templates that can be customized

TagBox – this template is responsible for the actual border around the TagBox and the panels that hold the tags. OOB – it is essentially a ScrollViewer that contains a WrapPanel and a Popup (search results container)



ResolvedTag – after an item is resolved it gets translated into a ResolvedTag. OOB it has a rounded border with an X so you can remove an item from the tagbox with the mouse. A custom template could be used here to display more information about the tag if so desired. DataBinding occurs in the Content field by default.


UnresolvedTag – this holds the text entered prior to being resolved. It is a pretty simple template who’s most important component is a TextBox with very little styling.



The example below has been restyled to be more appropriate to a set of categories. (Templates are included in the sample project)



Licensing

Although I am not releasing the source code for this control, I am allowing folks to make use of the control for use in personal projects. I go back and forth on the free versus paid approach and my general rule of thumb is that if it takes me more than a week to build something, and I intend on supporting it in the future, it is worth a nominal fee. In this case I ended up putting a little under 3 weeks into the project and documenation and I think it has a lot of value.

Watermarked Control – you may use the control for non-commercial purposes so long as the "thesilvermethod.com" watermark is visible.

Business License - a non-watermarked version of the control is available. I haven't gotten my act together yet on setting up the online purchasing, but in the short term if you would like to use this, please contact me directly - bbalmer@setpowersoftware.com.

Updated 2-23-2010 You can now purchase developer licenses for TagBox here. After purchasing a license a link will be emailed to you that will allow you to download a non-watermarked version of the TagBox assembly.

Here are the details of the license.

Demo Code includes TagBox assembly and demo project shown in this blog post.

3 Comments     follow

Any chance you would consider adding support for SelectedItem? I have a scenario where I am performing a second layer of validation on the submission of my form. If I detect certain objects I would like to notify the user and have the focus set on that object. Sweet control BTW. Jim
posted by jWalker on Wed Feb 24th 2010 at 3:39 PM
Jim- that is an interesting idea and at first blush not that difficult to do. I hadn't really considered using SelectedItem for that (instead I raise events for selection) but I like the idea because it would support databinding for other use cases. For example suppose when an email address got focus that we would show relationship information or a picture to the right of the TagBox. Let me see what I can do.
posted by Brett on Wed Feb 24th 2010 at 3:48 PM
Jim - I just updated the release to v.1.0.0.3 which includes support for SelectedItem. The demo project in the download also has code demonstrating the use of hte property. It is two-way bindable so if you update SelectedItem it will be reflected by the focused item in TagBox.
posted by Brett on Wed Feb 24th 2010 at 6:19 PM
Login to post comments
Icon

Drag and Drop Upload to Azure Storage via Silverlight 4

Thu Jan 21th 2010 by Brett
I recently needed a way to upload images and other files to Windows Azure Storage. I like the way some sites implement ActiveX controls or other plugins that allow you to drag and drop the files onto the browser itself for upload. Naturally when I read about the new capabilites of Silverlight 4 to accept dropped files I was dying to write a little upload control. This blog is hosted on Windows Azure, and as mentioned in previous posts, the blog-entry content files (images/xap files) are stored in Windows Azure Storage.
Fig 1. screenshot of upload control with 4 files
I did a quick search for Silverlight upload controls and came across an interesting project on CodePlex being worked on by Darrick C (thanks!). This project saved me quite a bit of time as it already had code for transferring a file from Silverlight to IIS. The code supported very large file sizes and larger chunk sizes than a webservice upload would generally support. There were some additional features there as well, that I didn't care about, but would mention should anyone else be interested, such as image re-sizing and upload resume.

Now on to the interesting parts:
Drag and Drop support - accepting a file drop event in SL4 is extremely easy. You can accept a drop from any control that derives from UIElement by setting AllowDrop=true.
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="55"></RowDefinition>
            <RowDefinition Height="437*"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="75"/>
        </Grid.ColumnDefinitions>
        <TextBlock HorizontalAlignment="Left" Margin="5,5,5,0"  Name="textBlock1" 
                   Text="Drag and Drop Files Below" VerticalAlignment="Top" />
        <StackPanel Grid.Column="1" >
            <Button Content="Upload" Name="button1"  Click="button1_Click"  />
            <Button Content="Clear" Margin="0,5,0,0" Click="Button_Click" />
        </StackPanel>
        <ScrollViewer x:Name="ImagesTarget" Background="WhiteSmoke" AllowDrop="True" Grid.ColumnSpan="2" Grid.Row="1">
            <ItemsControl x:Name="ImagesList">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <controlsToolkit:WrapPanel Orientation="Vertical">
                            <Image Source="{Binding Image}" Margin="5" Stretch="Uniform" MaxHeight="100" MaxWidth="100" />
                            <ProgressBar Value="{Binding FileUpload.UploadPercent}" Margin="3" Height="10"/>
                        </controlsToolkit:WrapPanel>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <controlsToolkit:WrapPanel />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </ScrollViewer>

    </Grid>
You can see in my case I am allowing drop on the ScrollViewer named ImagesTarget. In the code-behind I attach an event handler to the ImagesTarget.Drop event:
        public UploadControl()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(MainPage_Loaded);
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            ImagesList.ItemsSource = _images; 
            ImagesTarget.Drop += new DragEventHandler(ImagesTarget_Drop);
        }

        void ImagesTarget_Drop(object sender, DragEventArgs e)
        {
            if (e.Data == null) return;

            IDataObject dataObject = e.Data as IDataObject;
            FileInfo[] files = dataObject.GetData(DataFormats.FileDrop) as FileInfo[];

            //create a collection of FilePair for databinding
            foreach (FileInfo file in files)
            {
                try
                {
                    FilePair pair = new FilePair();
                    using (var stream = file.OpenRead())
                    {
                        var imageSource = new BitmapImage();
                        try
                        {
                            imageSource.SetSource(stream);
                        }
                        catch 
                        {   //it is not an image - lets show a default icon
                            imageSource.UriSource = new Uri("unknownfile.png", UriKind.Relative);
                        }
                        pair.Image = imageSource;
                    }
                    pair.FileUpload = new FileUpload(this.Dispatcher, UploadUri, file);
                    _images.Add(pair);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Unknown error prepping file for upload: \n" + ex.ToString());
                }
            }
        }
You can see that we try to load the files as images so that we can show thumnails in the UI, defaulting to a generic icon in cases where the file is not an image. Through databinding the files are then shown in the UI as a thumbnail and a progressbar. The work of uploading the file is performed by the FileUpload class which communicates with the HTTPHandler using querystring parameters. It also raises events when the upload of the file is complete. There are a couple of things I don't like about this class, one of which is the fact that the function of uploading the file is intermingled with UI telling the users the file already exists on the server. Since this was a quick and dirty for my own personal use I didn't refactor this yet (this code is largely unchanged from the codeplex project), but I would put it high on the list.

Storing the File in Azure - the HTTP handler does a couple of things.
  1. Creates a Container in Azure for holding uploaded files if it does not already exist.
  2. Checks to see if the file already exists in Azure
  3. Listens for chunks of an incoming file writing them to a temporary file in the filesystem. I wanted to avoid this step, but I couldn't find a way to append to a file in Azure storage.
  4. Writes the file to Azure Storage and deletes the temporary file.
The heavy lifting is done in a class called AzureFileUploadProcess. A couple of interesting bits of code:
       //the first time this method is called lets make sure our container is setup properly non-authenticated users have permissions 
        // to access files in the Azure container.
        void Initialize(HttpContext ctx)
        {
            CloudBlobClient client = CloudStorageAccount.FromConfigurationSetting("StorageAccount").CreateCloudBlobClient();

            //containers must be lower case - this seems strange to me but I cannot get it to work with uppercase 
            CloudBlobContainer container = new CloudBlobContainer(_containerName, client);
            container.CreateIfNotExist();
            container.SetPermissions(new BlobContainerPermissions() { PublicAccess = BlobContainerPublicAccessType.Blob });
            _container = container;
        }
The above code is responsible for creating the Azure Container. Containers in Azure can most be thought of as specialized file directories. They can define metadata that applies to the files they contain and also can have permissions. In the above code I create the container and allow public access to it (wouldn't do my much good to upload images no-one could get to).

Next is some code demonstrating check Azure Storage for file existence
                CloudBlob blob = Container.GetBlobReference(filename.ToLower());
                try
                {
                    blob.FetchAttributes(); // this will throw an exeception if it does not exist
                    context.Response.Write(blob.Attributes.Properties.Length);  //report the size of the file
                }
                catch (Exception) { context.Response.Write("0"); }  //I don't let checking for existence via exception handling, 
                                                                    // but that was the recommended/only approach on the MSFT blogs.  
                context.Response.Flush();
And finally we write the file to Azure and delete the temporary file
                       CloudBlob blob = Container.GetBlobReference(filename);
                        blob.UploadFile(filePath);

                        File.Delete(filePath);  //we stored this in a temporary area - delete it now that we are done

                        FileUploadCompletedEventArgs args = new FileUploadCompletedEventArgs(filename, blob.Uri.ToString());
                        FileUploadCompleted(this, args);

In the attached project I actually included an UploadProcess that is just designed to work against the FileSystem for those of you who aren't using Azure. As you can imagine, the code is not all that different from the Azure code.

Obviously this is not intended as the be-all-end-all of file upload controls. There is a lot of room here for neat things like
  1. Show the list of files already on Azure, presumably so you could delete/move/rename them.
  2. The ability to pause an upload via the UI
  3. Set metadata in Azure storage to futher categorize the files
  4. This should really be implemented as a custom control so that the UI can be re-styled more easily.
A Visual Studio 2010 project can be found here with all the code. I should note that you will need to have the Azure tools installed for this to work. Presently the project is setup to use the local Development Storage so you can test it without having to setup a service on Azure. Also - for some reason on my machine when debugging I cannot drop files onto the control (the mouse cursor even indicates it won't work). The solution is to open an entirely new browser and test it there.

10 Comments     follow

This is a great sample of using SL4 and Azure. I have the same issue when I debug the code in VS2010. Yes, I can run the second browser window to drop files, but I cannot debug in this case. Have you resolved this problem? If there any work around? I am thinking to enhance your sample into a full functional photo album management site. Of course, for free. What's on your mind?

KevinZ
kevin.zhang.canada at gmail dot com
posted by KevinZ on Sun Mar 14th 2010 at 7:34 AM
I set Chrome as default browser and start debug your application. I can drag drop files into chrome. But this won't work in IE (Windodws7). I think there may be a problem in IE with Silverlight 4.

BTW, I think the FileUploadProcess.cs is useless. You did not really use the class. It has been replaced by the Azure version.

posted by KevinZ on Mon Mar 15th 2010 at 5:09 AM
Hi Kevin -
Did you try this on SL4 RC yet? Since this was written on SL4 Beta I wonder if the debugging issue has since been corrected. I plan on trying it out later this week.

BTW - I included the FileUploadProcess.cs just in case someone wanted to use it in a non-azure screnario.
posted by Brett on Thu Mar 18th 2010 at 12:50 PM
I tried in VS2010 RC with SL4 RC, still the same problem. You can double check.
posted by kevinz on Thu Mar 18th 2010 at 11:41 PM
I was wondering if uploading a large file in chunks will break in a load balanced scenario. Since each post could go to a different server, isn't it possible that individual chunks could get written to different temporary files?
posted by Ozzy on Wed Mar 31th 2010 at 10:38 AM
Hi Ozzy - A load balancer would probably have to be taken into account unless it supports sticky sessions. If it didn't then one simple approach would be to write the chuncks to a shared network location instead of a local path on the balanced server. Of course that would result in a single point of failure, but you could always program in a rollover location if the first server couldn't be reached.
posted by Brett on Thu Apr 1st 2010 at 1:22 PM
Kevin-
Regarding debugging drag and drop: I was debugging a totally unrelated Outlook Addin and while in my debugging session I couldn't drag and drop items into Outlook either. I looked into it and it turns out the problem is that UAC prevent drag-drop operations between processes executed by diffent accounts. In my case I was running visual studio as Administrator (elevated). Once I switched to running Visual Studio in non-elevated mode I was fine. I just tried it for this project and it also worked - sort of. Because the Azure Tools require VS to be run elevated you cannot debug the solution end-to-end. Kind of a catch-22. Supposedly if you disable UAC then this is a non-issue.
posted by Brett on Thu Apr 1st 2010 at 1:39 PM
Brett, this is a great post, and a great example. I have a follow up question regarding downloading as opposed to uploading. I want the Silverlight 4 app to be able to download a file given that the SL app knows the blob container and filename on Azure. However, I don't want to leak any Azure keys to the SL4 client.

Specifically, let's say that the SL4 app accesses a record from SQL Azure, which contains the blob filename. Similar to your upload example, the SL4 app would communicate with the server, passing the filename, and have it downloaded into SL4's memory for displaying. Only the server would know how to specifically access blob storage (just like your upload example). Any examples or direction you could give would be appreciated.
posted by spbgeb on Fri Jul 16th 2010 at 10:21 PM
Ozzy & Brett, to solve the load-balancing issue, what about copying the files to a container that contains ONLY temp files, then move (copy) the file to the destination container once it is uploaded. Can you think of any downsides to this approach? I believe this solves the load-balancing issue in that the destination is always known and is not local to the server, and does not clutter up the desitination container.
posted by spbgeb on Sat Jul 17th 2010 at 11:10 PM
spgeb:
Regarding downloading files: I assume that the files you want the SL client to download are non-anyonymous files, otherwise you wouldn't need the key - just the Url. Assuming that is the case you could generate a shared access signature that you would pass to the SL client for download. I haven't done this myself, but here is an article that discusses the concept. http://blog.smarx.com/posts/new-storage-feature-signed-access-signatures

Regarding load balancing: Yes - I think that would work, with the only downside being that you are going to generate a lot of traffic between the webservers and the shared location as each file will consume the (file size/divided by the chunk size )! * chunk size unless you can append to the file in the shared location. I was just doing some reading and it looks like some folks have tried an approach where they are using PutBlock to append to an Azure Blob. http://social.msdn.microsoft.com/forums/en-us/windowsazure/thread/C60EB581-A503-463F-A102-E4A54099EB18 That would be the best way to handle the situation, other than the fact you would have to delete incomplete uploads otherwise they would sit in Azure Storage forever.
posted by Brett on Mon Jul 19th 2010 at 3:32 PM
Login to post comments
Icon

Architecting a Blog Engine for Windows Azure

Fri Jan 15th 2010 by Brett
I have mentioned this in previous articles but this Blog is hosted on Windows Azure. It represented my first foray into Azure development and I thought it might be helpful to point out some architectural changes I had to make when targeting this platform.

Post Storage
Blog posts (the HTML) and comments are stored in a SQL Database (along with Role and Membership Services). Created a SQL database was pretty straightforward in Azure, but unfortunately none of the SQL 2008 management tools work against Azure. This created some difficulties at first because additionally some aspects of TSQL are not supported in Azure. Fortunately a tool exists that lets you take existing databases and script them to SQL Azure (including data if desired). It will also parse SQL files and remove any non-supported TSQL so you can run them directly against Azure. It can be downloaded here:
http://sqlazuremw.codeplex.com/

I also had to grab a custom script for setting up the ASP.NET tables which can be found here:
http://support.microsoft.com/default.aspx/kb/2006191


I have a very common architecture that looks like this:

Fig 1. Architecture Diagram
As mentioned in another post, make sure you decorate your services with the following attribute or you may run into trouble when trying to access your service when published to the cloud.
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
Technically the JSON service and Silverlight service could have the same code and just be exposed as different endpoints, however I have found when working with jquery and JSON that you often want to simplify your object graphs both for performance and ease of coding on the client side. Not only that, but rarely is there a 1:1 overlap between the two services.

All my server code is hosted in a single Azure WebRole. I could have hosted the services in WebServiceRoles but in a simplistic case like mine I didn't see the benefit.


Post Media Storage
I have a slick little file uploader I wrote for Silverlight 4 that lets me drag and drop files onto it, which are in-turn uploaded to my site. Content usually includes images, but can also be source code or XAP files when demonstrating Silverlight. The Silverlight piece is backended by an ashx file that accepts the upload stream and writes the file to disk.

Normally – I create a directory structure to host these files beneath the website (being careful to setup IIS so that files in this directory cannot be executed). This actually works fine in Azure, however a subtlety of the Azure architecture prevented this from being a valid solution. Each time you publish, or update your Azure project anything previously in the file-system is wiped out. This means that if you were relying on the file-system for storage those files are now gone.

I considered storing the files in SQL directly, but that has never been my favorite approach for a lot of reasons. Back in the old days it was ill-advised because of performance reasons, however I don’t believe that to be the case any longer (SharePoint stores all of its content there and it scales very well). It is still however a fair share of work to setup the code to write and extract the data. You also have to consider setting up an HTTP handler to stream the files out, which includes setting the proper content type.

All that considered it seemed to me that Azure Storage would be a good candidate. It has a REST service that lets you post/retrieve items, and individual items are URL addressable, eliminating the need to write my own handlers. Of course not knowing a things about working with Azure blobs I realized that I would spend way for time learning and troubleshooting this new tech than the four hours it would have taken me to implement the SQL solution :> Of course I opted for the sparkling new toy. Handily classes exist in the Azure assemblies that wrap the REST calls. This is a big timesaver and a lot less error prone when compared with making the REST calls yourself. I did get stuck a number of times and will document what I learned in another post as I want to keep the focus of this article on architecture not code.

After learning the ropes and completing my implementation Azure Blog Storage worked great. It even lets you do some neat things with metadata so that you could organize your content around the associated Articles. (I haven’t done this yet, but plan to) In my case I created a Container (almost akin to a drive) and stored all my files there. Containers may contain directories as well, however I didn’t make use of that feature.

0 Comments     follow

Login to post comments
Icon

Hosting Silverlight Accessible WCF Services in an Azure WebRole

Thu Jan 14th 2010 by Brett
I recently spent some time writing a web application for Windows Azure. I am really excited about Azure and plan to leverage it for my development projects whenever applicable. This blog is actually hosted on Azure as it gave me a good opportunity to get some hands on experience with the technology. The blog post editor is actually a Silverlight application that posts its changes through a WCF webservice.

I created a Silverlight compatible WCF service and was able to add a service reference in VS2010. I should note that I had the website project set as my Startup project, not the Azure Roles project which spins up the Azure Fabric Simulators. After publishing to Azure and attempting to use the webservice from Silverlight I received the following message:

“The message with To ‘http://thesilvermethod.cloudapp.net/BlogService.svc’ cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. Check that the sender and receiver’s EndpointAddresses agree.”

As it turns out WCF performs message filtering so that messages sent to different logical adresses can be mapped to the same physical address. In an Azure solution where unknown layers of redirection (Load Balancers, Firewall Redirection) are present between the client and the server the situation exists where the physical and logical are not one and the same. After some research I determined that you could force all requests coming to a given physical address to be accepted by the service.

I had to decorate my class with the followig attribute :
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

More information about Service Addressing can be found here if you are curious.
http://msdn.microsoft.com/en-us/magazine/cc163412.aspx

Hopefully this will save someone some time.

0 Comments     follow

Login to post comments
Icon

Embedding Silverlight in a Windows Service

Thu Jan 7th 2010 by Brett
I had an interesting idea a few weeks ago. Wouldn’t it be interesting to see if I could host a Silverlight application inside a WCF service. The reason the idea came to mind was that my company has an application that has three components – a windows service (that hosts several WCF services), and WPF Management Application, and a Windows Forms application. In an effort to reduce the installation steps I thought it would be nice if instead of having to setup the management application on administrator’s desktops – it would be much easier to exercise Silverlight’s local install option. The whole upgrade process would also be made easier from that point forward because updates to the server would then go hand in hand with the management application.

Obviously – this would be easy to do in IIS, but from my application’s perspective I didn’t want to put a dependency on IIS because of the complexity of configuration. Few things are more time consuming than walking a customer through IIS configuration over an email conversation when they haven’t had any experience with IIS. I wanted a drop dead simple installation experience for my end users. In my case – they run setup.exe, and at the end of the process it opens a browser to a page running my Silverlight management application.


Fig 1. Old and new architectures

Now initially I must confess I didn’t think to host the Silverlight application inside WCF – instead I started looking at a variety of webservers that could run in a .NET process such as Cassini. I ruled them out for a number of reasons including:
  1. My WCF Service was already running on port 80 and I couldn’t find an easy way to port share between with an embedded web server .
  2. I considered running Cassini – and then using that to host WCF services, but this isn’t listed as a supported way for hosting WCF and I really didn’t want to go that far out of band .

One of the nice features built into the WCF infrastructure is Url-rewriting. This allows you take a particular WebMethod, say GetPage.asmx?pageName=x and re-write it to /x where x is the name of the page you wish to display. The method returns a stream, which when invoked by the web-browser returns some HTML.

Storage of web content:
Obviously I didn’t want HTML stored in-line with my C# code (for about 1000 reasons), so in my case I decided to embed the necessary files inside my assembly. I could have stuck them in the file-system somewhere, but I liked the fact that embedding them would make it impossible for people to tamper with them (ok – not impossible – but difficult). I created folders (Images and ClientBin) in my project and added the necessary images and xap files here. (Note – you must mark them as embedded resources or they will not get compiled into the assembly)

In the actual implementation class, WebServer.cs, files are extracted from the assembly and returned as a Stream.
    //The service contract for the WebServer - Url re-writing is used to simulate 
    //accessing file resources on a normal web server
    [ServiceContract]
    public interface IWebServer
    {

        [OperationContract, WebGet(UriTemplate = "/")]
        Stream Default();

        [OperationContract, WebGet(UriTemplate = "/Images/{imagename}")]
        Stream GetImage(string imageName);

        [OperationContract, WebGet(UriTemplate = "/ClientBin/{xapname}")]
        Stream GetXap(string xapName);
    }
    //WebServer extracts resources out of the Assembly and serves them up via a Stream
    //Note: production code should have improved exception handling in cases where resources cannot be found
    public class WebServer : IWebServer
    {
        public const string AssemblyRootPath = "ServiceHostedSilverlight.";
        public Stream Default()
        {
            WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";
            return Assembly.GetExecutingAssembly().GetManifestResourceStream(AssemblyRootPath + "Default.htm");
        }

        public Stream GetXap(string xapFile)
        {
            WebOperationContext.Current.OutgoingResponse.ContentType = "application/x-silverlight-2";
            return Assembly.GetExecutingAssembly().GetManifestResourceStream(AssemblyRootPath + "ClientBin." + xapFile);
        }

        public Stream GetImage(string imageName)
        {
            string ext = new FileInfo(imageName).Extension.ToLower();
            WebOperationContext.Current.OutgoingResponse.ContentType = "image/" + ext;
            return Assembly.GetExecutingAssembly().GetManifestResourceStream(AssemblyRootPath + "Images." + imageName);
        }
    }

In addition to the actual code there are a few critical pieces to the configuration of the WCF host that we need to look at in our app.config. Without WCF configured as shown below this will not work. This took quite a bit of stumbling to figure out the right mix of settings.
    <behaviors>
      <endpointBehaviors>
        <behavior name="ServiceHostedSilverlight.WebServerEndpointBehavior">
          <webHttp />  <!--Necessary for Http/REST style services-->
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="ServiceHostedSilverlight.WebServerBehavior">
          <serviceMetadata httpGetEnabled="false" /> <!--must be false or the Url re-writing will not work-->
          <serviceDebug httpHelpPageEnabled="false" includeExceptionDetailInFaults="true" />
          <!-- must disable the help page or the default re-written url (/) will not work -->
        </behavior>
        <behavior name="ServiceHostedSilverlight.DataServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
All is well and good – ok – not quite. While this worked fine in IE (seems to look at the extension name as a last resort for determining the content-type of the page), Chrome and Firefox just gave me a prompt to open a file using a local application.

Some more digging revealed that you can set the content type within a web method. I set mine appropriately based on the type of content (see WebServer.cs above) and things were working in all my target browsers. The next issue I wanted to tackle was the default landing page if someone just went to http://myinternalserver . WCF lets you define parameter-less methods and I was able to do this so long as I didn’t have any other methods sharing the / url. This wasn't the case initially as by default WCF contains a help page that grabs the root url. After trying to figure out how to override the help page I realized I could just disable it, thereby enabling usage of root.

Another great tip I learned here is that if you place the resources in the same path as your re-written WCF method Url then the Visual Studio designer will work just fine because from the perspective of the HTML the resources will be in the same place.

Silverlight – ok finally to the Silverlight – hosting Silverlight is just like hosting any other content type except when you stream the Silverlight XAP you need to set the content-type to application/x-silverlight-2. Your Silverlight application then communicate with the other WCF services to acquire data or do whatever it needs to do.

Fig 2. Resultant web page


Obviously this little web server has its limitations – it doesn’t have a dynamic engine (e.g. – no ASP.NET). These limitations are largely mitigated by its pairing with Silverlight since the UI is handled client side. I like how lean the implementation is and I can think of a ton of cases where this is useful:
  1. A service that syncs data between two enterprise applications – the UI here would be minimal – but a robust log viewer could be presented through Silverlight.
  2. The Admin UI for a network service such as a Firewall or Spam filter.
  3. Pure configuration dialog instead of directing users to modify app.config settings. Your UI could give you validation and the ability to restart the service after a setting change if necessary.
  4. A commercial application you wish to package for quick and easy setup and administration.

This has become my go-to-method for service administrative UI’s. It lets me offer my customers a very rich UI experience without having to “mess with IIS”.

Code: (download here)
You will note that the sample project I have included hosts the WCF Services inside a console application instead of a Windows Service. Since I didn't want to make readers register a Windows service just to test the code I thought this was a better approach for demonstration purposes. Obviously hosting WCF (instead of a console app) is a well documented and simple task. You will also note that the solution builds the Silverlight App first and then automatically copies the XAP file to the ClientBin folder on the ServiceHostedSilverlight project - that ensures it has the latest version when it is compiled. Also - when you add/update service references to Silverlight you need to make sure that the console is up and running - since you cannot do this while in debugger - manually start the console app and then add your service reference in VS.

3 Comments     follow

This is awesome. I have been working on an application that runs as a service and handles grabbing updates from another service and applying them to a local database. Presently I show a history of the updates by writing to a log file, but it would be much slicker to have a built in Silverlight UI for showing the information to the admins who depend on the service.
posted by WilliamK on Tue Jan 19th 2010 at 7:28 PM
Very Nice Idea and Thx for sharing the write up and Code. This will definitely catch up.
posted by kanchirk on Tue Feb 23th 2010 at 10:11 PM
This is a very good work! I try to do the same without using WCF service, and it work fine, but i find that you have the same problem that I find using silverlight OOB update process. If you try to implement the update process for Out Of Browser application (using CheckDownloadUpdateAsync() method), when you have installed the application on desktop, it seems to make the download of the application everytime you launch the application, even if the application version is the same. Do you have any idea about it?
posted by vibergui on Fri Jul 9th 2010 at 7:52 AM
Login to post comments
Icon

Welcome to The Silver Method

Wed Dec 23th 2009 by Brett
The Silver Method is a site discussing technology generally related to the Microsoft stack. Specifically technologies such as Silverlight, WPF, WCF and Windows Azure are frequently discussed. In addition to blog posts specific projects are called out on the site that might have long-term appeal to readers of the site. I intend this site to serve as a reference to the community and hope that people find it interesting and helpful. I should also note that I am an independent consultant not affiliated with Microsoft.

The Author - Brett Balmer I am a software developer and general technology enthusiast who has worked for and owned several software development companies. My first company was called Scout Solutions and we sold a product called Aptus which was a Customer Relationship Managment (CRM) application targeted toward law firms. Aside from the business value the product provided - Aptus broke new ground in what is now commonly referred to as AJAX. Originally written in ASP backed by a VB6 object model I hand wrote my own XML "webservice" layer through which our client-side jscript library communicated. While this is a common practice today, back in 1999 few were architecting their applications this way. In fact we utilized a little used feature of IE 4 called DHTML behaviors which allowed code to be attached to HTML objects via a CSS reference. Ultimately Scout was purchased by our larger competitor, Interface Software which ultimately became part of Lexis Nexis where I served as director of technology for several years.

Ultimately I grew eager for some new ground up projects and began consulting (and continue to do so) over the last several years. I recently have worked on a number of projects based on SharePoint 2007, WPF and also Silverlight. Silverlight is a technology that really excites me given my roots in web based application development. The blood, sweat and tears that used to be required for a marginally rich UI are a thing of the past when working with Silverlight.

I have also recently started an pc energy management company called SetPower. SetPower, the principal product, allows you to configure schedules by which the power plans of your computer conform to. We got the idea for the product because, being very energy consious individuals, we grew annoyed with having to constantly wake our machines when they were configured to go to sleep on idle. Our desire was to enact the power saver plan after working hours and keep our machines in high performance during the day. SetPower was born, and is a free product for non-business users. We have an enterprise version as well that allows for central management of power plans, reporting of power savings, and even remote wake capabilites in case you need to wake your sleeping machine for remote access.

Even though the app is brand new we estimate that the free version has already saved folks $700,000 and many thousand tons of carbon emissions.

You can reach me here: bbalmer -at- setpowersoftware.com

0 Comments     follow

Login to post comments
 

Recent Posts

By Month