Saturday, March 20, 2010

Creating WCF proxy without reference

The problem : Creating WCF proxy in Silverlight without using the add service reference and it’s auto generated code

It was a debate that whether we can call a WCF service from Silverlight without using “Add Service Reference” menu item.In WPF or in the other .Net environments it is easy.We just need to refer the contracts dll and write a class which inherits from ClientBase.But this is Silverlight - A different runtime.

A Normal WCF service reference with all the generated code files

There were 3 opinions.Not at all possible,Possible with less amount of code,Possible if we create all those classes by our own.Just avoid the last one because that doesn’t give us any benefit as it is just making the process manual.

One of my Colleagues started research on that and was able to achieve the same.I am just sharing the idea.

Solution : We can achieve the same using contract interface,proxy class and a custom eventargs class

First of all there are no changes at the server side.Only 3 types we are going to write at client side which will be present in the reference.cs file if you create the proxy using “Add Service Reference” Dialog.

There will be a question for sure.Why are we writing the code which is being auto generated ? Why don’t we create a reference using the dialog and copy paste the reference.cs code?

The answer for both the questions is same.You can create reference using the dialog and get the code from reference.cs.That is enough.

Advantages

  • Can avoid huge amount of code which is auto generated.
  • This is acting as a separate layer and can encapsulate operations here in future.

Implementation steps

Lets take example of implementing a DataService with one method GetData which returns a string.Don’t bother about the server side.Use the same.Below are the steps to perform at client side ie Silverlight side.

  1. Create interface IDataService
    1. Decorate with ServiceContract attribute.
    2. Add method BeginGetData.Decorate it with OpertionContract and Set AsyncPattern to True.
    3. Add Method EndGetData.
      Imports System.ServiceModel

      <ServiceContract()> _
      Public Interface IDataService
      <OperationContract(AsyncPattern:=True)> _
      Function BeginGetData(ByVal callback As System.AsyncCallback, ByVal asyncState As Object) As System.IAsyncResult
      Function EndGetData(ByVal result As System.IAsyncResult) As String
      End Interface





  2. Create eventArgs class deriving from System.ComponentModel.AsyncCompletedEventArgs


    1. Add required properties to pass values.

      Public Class GetDataCompletedEventArgs
      Inherits System.ComponentModel.AsyncCompletedEventArgs

      Private results() As Object

      Public Sub New(ByVal results() As Object, ByVal exception As System.Exception, ByVal cancelled As Boolean, ByVal userState As Object)
      MyBase.New(exception, cancelled, userState)
      Me.results = results
      End Sub

      Public ReadOnly Property Result() As String
      Get
      If Me.results IsNot Nothing Then
      Return CType(Me.results(0), String)
      End If
      Return Nothing
      End Get
      End Property
      End Class




  3. Create class DataServiceProxy derived from ClientBase which Implements IDataService.Write constructors.Implement methods.Write delegates and event which communicate back to the caller.



Public Class DataServiceProxy
Inherits ClientBase(Of IDataService)
Implements IDataService
#Region " Constructors"
Public Sub New()
MyBase.New()
End Sub

Public Sub New(ByVal endpointConfigurationName As String)
MyBase.New(endpointConfigurationName)
End Sub

Public Sub New(ByVal endpointConfigurationName As String, ByVal remoteAddress As String)
MyBase.New(endpointConfigurationName, remoteAddress)
End Sub

Public Sub New(ByVal endpointConfigurationName As String, ByVal remoteAddress As System.ServiceModel.EndpointAddress)
MyBase.New(endpointConfigurationName, remoteAddress)
End Sub

Public Sub New(ByVal binding As System.ServiceModel.Channels.Binding, ByVal remoteAddress As System.ServiceModel.EndpointAddress)
MyBase.New(binding, remoteAddress)
End Sub
#End Region

#Region "GetData"
Private onBeginGetDataDelegate As BeginOperationDelegate
Private onEndGetDataDelegate As EndOperationDelegate
Private onGetDataCompletedDelegate As System.Threading.SendOrPostCallback
Public Event GetDataCompleted As System.EventHandler(Of GetDataCompletedEventArgs)

Public Function BeginGetData(ByVal callback As System.AsyncCallback, ByVal asyncState As Object) As System.IAsyncResult Implements ServiceContracts.IDataService.BeginGetData
Return MyBase.Channel.BeginGetData(callback, asyncState)

End Function

Public Function EndGetData(ByVal result As System.IAsyncResult) As String Implements ServiceContracts.IDataService.EndGetData
Return MyBase.Channel.EndGetData(result)
End Function

Private Function OnBeginGetData(ByVal inValues() As Object, ByVal callback As System.AsyncCallback, ByVal asyncState As Object) As System.IAsyncResult
'Dim engID As String = CType(inValues(0), String)
'Dim libraryID As String = CType(inValues(1), String)
'Dim folderName As String = CType(inValues(2), String)
'Dim parentFolder As PathInfo = CType(inValues(3), PathInfo)
'Dim folderGeneralProperties As FolderGeneralProperties = CType(inValues(4), FolderGeneralProperties)
'Dim additionalProperties As System.Collections.Generic.Dictionary(Of String, String) = CType(inValues(5), System.Collections.Generic.Dictionary(Of String, String))
Return CType(Me, IDataService).BeginGetData(callback, asyncState)
End Function

'Private Function GetData() As String Implements IDataService.GetData
'Return MyBase.Channel.GetData()
'End Function

Private Function OnEndGetData(ByVal result As System.IAsyncResult) As Object()
Dim retVal As String = CType(Me, IDataService).EndGetData(result)
Return New Object() {retVal}
End Function

Private Sub OnGetDataCompleted(ByVal state As Object)
'If Not (GetDataCompleted Is Nothing) Then
Dim e As InvokeAsyncCompletedEventArgs = CType(state, InvokeAsyncCompletedEventArgs)
RaiseEvent GetDataCompleted(Me, New GetDataCompletedEventArgs(e.Results, e.Error, e.Cancelled, e.UserState))
'End If
End Sub

Public Overloads Sub GetDataAsync()
If (Me.onBeginGetDataDelegate Is Nothing) Then
Me.onBeginGetDataDelegate = AddressOf Me.OnBeginGetData
End If
If (Me.onEndGetDataDelegate Is Nothing) Then
Me.onEndGetDataDelegate = AddressOf Me.OnEndGetData
End If
If (Me.onGetDataCompletedDelegate Is Nothing) Then
Me.onGetDataCompletedDelegate = AddressOf Me.OnGetDataCompleted
End If
MyBase.InvokeAsync(Me.onBeginGetDataDelegate, New Object() {}, Me.onEndGetDataDelegate, Me.onGetDataCompletedDelegate, Nothing)
End Sub
#End Region
End Class



Uploaded a sample which does the same.

Wednesday, March 3, 2010

Silverlight Installation issues I faced

Here are some details about the installation issues which I faced when tried to setup my machine for Silverlight 4 with Visual studio 2010. No need to read further, if you are able to setup your machine with Silverlight 3 + VS 2008 and Silverlight 4 + VS 2010 without issues ;-)

After the completion of previous project which is done in VSTS 2008 and Silverlight 3 we decided to port the same to Silverlight 4.According to my knowledge it is difficult to have 2 versions of Visual studio if any version of them are in beta.Here to work with Silverlight 4 we need Visual studio 2010 beta 2.So normally I uninstalled Silverlight 3 and  started uninstalling VS 2008.

Everything went fine until my onsite counterpart called and asked me to setup my machine with VS 2008 + Silverlight 3and VSTS2010 beta 2 + Silverlight 4 beta .The reason was simple.We may need to support client for the previous project.The good news was he setup his machine with the above mentioned configuration.

So I stopped the uninstallation of VSTS 2008.Seems the problems started here.Started installation of Silverlight 3.Got the simple error message.Not able to complete the installation.Log says a previous version of Silverlight is there.Tried with different versions of Silverlight 3 which were available with colleagues.Hours passed with Uninstallations, Installations and reboots.Finally downloaded the Silverlight 3 version from net and tried.That too not worked out.

As usual I asked Google what is this error message by pasting the installation log in search box.Got a good link with Silverlight error messages and their solutions.

Silverlight 3 installation Error messages : http://blogs.msdn.com/amyd/archive/2009/03/19/silverlight-tools-installation-error-codes.aspx

I figured out that there are 2 patches which are stopping me from installation.They are KB967143 and KB956453 and the solution was to manually uninstall those.But when I tried uninstalling it said “Update removal was disallowed by policy”.What policy ? Its My machine and my login with admin privileges.I haven’t set any policy.

After a google I came to know more things about the patches.There are different types of patches and these patches fall into UNINSTALLABLE patch category.The only solution was to reinstall the application without applying those patches.

Uninstallable patches:http://msdn.microsoft.com/en-us/library/aa372102%28VS.85%29.aspx

Again uninstalling and installing VS 2008.Then Silverlight 3.Next series was VS 2010 beta 2 and Silverlight 4 beta.Tested whether the old project is running or not in VS 2008 and creation of Silverlight 3 and 4 projects in VS 2008 and VS 2010 respectively.Overall cost - a weekend and 2 week days.

Sometimes I am getting error message “VB.Net compiler is not responding” when I compile Silverlight 3 projects in VS 2008.But not consistent.Other than that everything works perfect.

Tuesday, March 2, 2010

Add Reference is empty in Silverlight 4 Beta

As I told in the last post ,I have started with the Silverlight 4 research using Visual Studio 2010 beta 2 .The first thing I noted is the add reference box in Silverlight project is empty.

According to Microsoft this is a bug and has fixed.
Workaround
In the add reference dialog manually browse the dll from the folder [Install Drive]:\Program Files\Microsoft SDKs\Silverlight\v4.0\Libraries\Client

https://connect.microsoft.com/VisualStudio/feedback/details/520040/missing-list-of-components-from-add-reference-in-silverlight-4-0-projects
http://forums.silverlight.net/forums/p/150240/335233.aspx