Wednesday, September 11, 2013

WebSockets in .NET 4.5: System.Net.WebSockets.ClientWebSocket vs Windows.Networking.Sockets.MessageWebSocket

Props to this guy's example project on how to implement a simple WebSocket using System.Net.WebSockets in .NET 4.5. Another good example is here.

I am working on a Windows Store App (WinRT, Metro, Win 8, or whatever name they are trying to market this under currently) and a .NET 4.5 application. Both will be using a WebSocket to talk to the same server.

The WinRT Windows.Networking.Sockets.MessageWebSocket is a wonderfully simple way to use a WebSocket to send and receive strings back and forth. Microsoft has a nice sample project here.

The .NET 4.5 System.Net.WebSockets.ClientWebSocket is just the opposite. See aforementioned blog for a 'simple' example.

Please see both sample projects for details: MessageWebSocket, ClientWebSocket

Two things make the MessageWebSocket really easy to use. First, it has a messageRecieved event handler, so all you need to handle incoming messages is attach a method thusly:

messageWebSocket.MessageReceived += MessageReceived;

See the sample project for the MessageRecieved implementation.


ClientWebSocket requires wrapping the Send and Receive actions in tasks and monitoring the receive buffer with a loop. Reminds me of old time socket monitoring. I though WebSockets were supposed to make my life simpler?


Secondly, MessageWebSocket provides a DataWriter so all you have todo to read or write strings is set the message type, grab the reader, and send a string.


//set the message type
messageWebSocket.Control.MessageType = SocketMessageType.Utf8;
//wrap the output in a DataWriter
messageWriter = new DataWriter(messageWebSocket.OutputStream);
//put a string on the writer
messageWriter.WriteString(message);
// Send the data as one complete message.
await messageWriter.StoreAsync();



Compare this to the ClientWebSocket in .net 4.5:


byte[] sendBytes = Encoding.UTF8.GetBytes(message);
  var sendBuffer = new ArraySegment<byte>(sendBytes);
  await socket.SendAsync(
      sendBuffer,
      WebSocketMessageType.Text,
      endOfMessage: true,
      cancellationToken: cts.Token);



byte[] seriously? I already have a string why would I want to revert to such a low level wrapper?


Reading messages is similarly easy in MessageWebSocket vs ClientWebSocket. See the example projects for details.


Conclusion:


Its good to have all the options provided in the System.Net.WebSockets namespace, but the end of the day, a WebSocket should make my life easy when all I need to do is send and receive some strings (json for example). I find it vexing this is provided for Windows Store Apps, but they don’t provide the same thing across platforms.


If I iron this out I’ll try to get a sample project uploaded showing how to get behavior similar to MessageWebSocket while using ClientWebSocket. No timeframe on this, sorry.

Thursday, September 5, 2013

MVVM Light, WPF, and Opening New Windows

Ran across this while trying to figure out how to properly open a new window in a WPF project using MVVM Light toolkit.

Viv posts a good example project using Messenger to communicate between ViewModel and View. But the code used to new up the appropriate ViewModel and View for the new window is all in the code behind for MainWindow (MainWindow.xaml.cs). I generally avoid putting anything in a code behind, so I added another button showing how to do the same thing without the code behind.

Sample Project - Dropbox download page

Which method is better? Pro’s and Con’s? Let me know, I just dislike code behind.

Here are the main points, see the sample project for the details.
I'm utilizing the ViewModelLocator singleton for this static method

   1:      public static void CreateWindow(OpenWindowMessage message)
   2:      {
   3:          var uniqueKey = System.Guid.NewGuid().ToString();
   4:          var nonModalWindowVM = SimpleIoc.Default.GetInstance<NonModalWindowViewModel>(uniqueKey);
   5:          nonModalWindowVM.MyText = message.Argument;
   6:          var nonModalWindow = new NonModalWindow()
   7:          {
   8:              DataContext = nonModalWindowVM
   9:          };
  10:          nonModalWindow.Closed += (sender, args) => SimpleIoc.Default.Unregister(uniqueKey);
  11:          nonModalWindow.Show();
  12:      }


The MainWindowViewModel has a RelayCommand so the button on MainWindow.xaml has something to bind to.

public RelayCommand OpenNonModalDialog_NoCodeBehind { get; private set; }

Constructor wires up the RelayCommand

      OpenNonModalDialog =
        new RelayCommand(
          () =>
          Messenger.Default.Send<OpenWindowMessage>(
            new OpenWindowMessage() {Type = WindowType.kNonModal, Argument = SomeString}));
        
        //No Code Behind
      OpenNonModalDialog_NoCodeBehind =
        new RelayCommand(
          () =>
            ViewModelLocator.CreateWindow(new OpenWindowMessage() { Type = WindowType.kNonModal, Argument = SomeString }));

Notice the first is using Messenger to tell the code behind to create the window.

The No Code Behind is using the static method on ViewModelLocator.

MainWindow.xaml, Button.Command is bound to the no code behind relay command

    <Button Grid.Row="1"
        Grid.Column="0"
        Margin="10"
        Command="{Binding OpenNonModalDialog_NoCodeBehind}"
        Content="Open No Code Behind" />

Dell Optiplex 9010 All in One and Windows 8

I'm testing a Dell Optiplex 9010 AIO machine with 64 bit Windows 8 and a solid state hard drive.

Highly annoyed by an issue with Windows Store Apps. Some of them try to open then just shut down. Either a blank blue screen (not a blue screen of death, just a blank background) or right back to the Start screen.

Some apps that failed: Evernote Touch, Drums, Elemento

Some that worked: Netflix, Bing, IE

Dell support thought it was the hard drive so they sent me a new one. While installing it was a somewhat interesting look inside this very solid piece of hardware, it did not fix my problems. I did notice there is room to stick another huge spinning hard drive should I need the disk space. Just leave windows on the SSD for speed (it does boot/wakeup ridiculously fast).

Note: if you get Dell to send you a hard drive, make sure you have install media, I didn't realize the resource DVD did NOT have a Windows 8 image on it. Had to wait for them to send me a USB key with the image.

None of this solved my problem!

Ran across this post, pointing to a display driver issue. Ran Windows Update, didn't find any driver updates.
Went to Device Manager, right clicked Display device, Update Driver, found nothing.

Solution!
Dell support site, put in Service Tag, downloaded and installed the latest drivers from there for the Intel HD Graphics card.

This fixed everything, Dell seriously needs to update there image to use the new drivers.

Current driver:
Dated: 2/22/2013
Version: 9.17.10.3040