Monday, August 29, 2011

Silverlight local messaging issues with ‘\0’

When we want to communicate between 2 Silverlight applications locally, we have a framework way to accomplish the same.Its nothing but 2 classes LocalMessageSender and LocalMessageReceiver.Recently we had faced an issue with local messaging system of Silverlight.The problem was LocalMessageSender sends a message without any exception but when LocalMessageReceiver receives the message, it is not the same message. Its not incorrect data, but the length itself reduced.
We first checked the size of the message which we are sending.It not exceeding 40KB limit as per Microsoft.Then we started digging into the project specifics and could see that the data passed is binary data.ie it’s the data got from a BinarySerializer which is just using the BinaryWriter Class to make the data as binary.The investigation continued to find the character which says the end of the message at the receiver side. After couple of hours I got the character which is nothing but our famous ‘\0’ which was used in C & C++ to denote as end of string.
Our binary serializer was adding this character while serializing the objects. Since the serializer internally uses BinaryWriter, this happens by the BinaryWriter when serializing numbers. I have checked .Net string specification and it says the string is represented using its length rather than the old ‘\0’ style. But don’t know why in local message sending, this is happening.
You can reproduce it simply.Try to send the message "Joy\0George" it will transmit or receives only ‘Joy’.I am not sure which communication end is cutting the message.

private void btnJSON_Click(object sender, RoutedEventArgs e)
{
SendMessage("joy\0George");
}
private void SendMessage(string serialized)
{
MessageBox.Show("Length:"+serialized.Length.ToString());
LocalMessageSender sender = new LocalMessageSender("TestPoint");
sender.SendCompleted += new EventHandler<SendCompletedEventArgs>(sender_SendCompleted);
sender.SendAsync(serialized);
}
void sender_SendCompleted(object sender, SendCompletedEventArgs e)
{
if (e.Error != null) MessageBox.Show(e.Error.ToString());
}





Here is the receiving end.




Private Sub ListenForMessage()
Dim receiver As New LocalMessageReceiver("TestPoint")
AddHandler receiver.MessageReceived, AddressOf Received
receiver.Listen()
End Sub
Private Sub Received(ByVal sender As Object, ByVal e As MessageReceivedEventArgs)
MessageBox.Show("Length " + e.Message.Length.ToString())
DirectCast(sender, IDisposable).Dispose()
End Sub




Don’t confuse with the C# and VB.Net code.All will compile into same ILCode Smile.At the sending side the length will be 10 and receiving end the length will be 3 if we send the above mentioned string which has ‘\0’. 

I can guess that Microsoft uses unmanaged modules to accomplish the communication which takes ‘\0’ as end of string. Anyway I have posted in Silverlight forums.

Monday, August 22, 2011

Adding custom EndPoint Behavior at client side ServiceReferences.ClientConfig

A custom Endpoint behavior which implements IEndpointBehavior can be added for many purposes. That depends upon your requirements and the nature of the application you are working on. But interesting thing is you cannot add the EndpointBehavior through config in Silverlight 4. But supports addition of custom Endpoint Behaviors through code .ie after creating the proxy you may add the behavior to the Endpoint.Behaviors collection of proxy.As you know, here proxy is a derived class of ClientBase<T> and this class has the property Endpoint.

Passing ClientBase<T> objects as method arguments
Next question comes how to make the code to add end point more generic in order to reuse the code for all the WCF service proxies.ie we need to write a method which accepts ClientBase<T>.This is little tricky at first look .But please don’t go for dynamic keyword or object where we have a typed way.Here is the small code snippet to use ClientBase<T> as method parameter type in C#.

private void CreateProxy()
{
TestServiceReference.TestServiceClient client = new TestServiceReference.TestServiceClient();
AddMyEndpointBahavior < TestServiceReference.ITestService>(client);
}
private void AddMyEndpointBahavior<T>(ClientBase<T> client) where T :class
{
client.Endpoint.Behaviors.Add(new MyEndpointBehavior());
}




For VB.Net version see my general coding blog where I posted this first since it is more related to generics.


Monday, August 15, 2011

Changing Application.RootVisual at runtime

If you are a Silverlight Island programmer, this will not applicable to you because you will never face a situation which demands to change the Application.RootVisual property. Don’t confuse the word Island programmer ,it simply refers to the programmers who are creating small sized Silverlight applications mainly with some animations to fit into a small portion of HTML page which may be static or emitted by technologies such as ASP.Net or PHP.

Sometimes I feel that the Silverlight is more suited to Island programs than full window business apps. There are so many reasons.One is its rich user interface capabilities.This is more needed for glazy island apps than business apps. When we talk about great user experience there is always some cost attached to it which reduces performance. The performance is more important when we come to business apps than the user interface. In some of the tests we could see that the UI rendering takes more time than the WCF service in the whole display cycle. This happens when the data elements are huge in number but small and has complex data templates.

Ok.Coming back to changing Application.RootVisual multiple times at runtime. There may be scenarios where you need to show your authentication UI first and then load your application XAPs and the actual UI pages. In this case you need to change the RootVisual for sure.But this is not supported by the Silverlight runtime. First of all if you simply change, it will not change.You will get the below exception when you try to set null first and assign another visual after that.

Invalid value set for application's RootVisual

ie the below code will result into System.InvalidOperationException' in System.Windows.dll

'This will result in System.InvalidOperationException occurred in System.Windows.dll
Application.Current.RootVisual = Nothing
Application.Current.RootVisual = New TextBox With {.Text = "changed"}




So what is the simple solution.Keep a ContentControl as your RootVisual and set your Login UI and Application UI pages as its content.In the Application_Startup event set a ContentControl as your RootVisual then add initial UI to that. Later cast the RootVisual as ContentControl and change its Content property.


Private Sub Application_Startup(ByVal o As Object, ByVal e As StartupEventArgs) Handles Me.Startup
'Initial UI.Here its button
Dim btnChangeRootVisual As New Button() With {.Content = "Change RootVisual"}
AddHandler btnChangeRootVisual.Click, AddressOf btnChangeRootVisual_Click

'ContentControl as RootVisual
Me.RootVisual = New ContentControl() With {.Content = btnChangeRootVisual}
End Sub
Private Sub btnChangeRootVisual_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
'Get the ContentControl and assign new UI to its content property
Dim rootContentControl As ContentControl = DirectCast(Application.Current.RootVisual, ContentControl)
rootContentControl.Content = New TextBox With {.Text = "changed"}
End Sub




This is just a hack for real business application programmers of Silverlight.