Introduction:
This article explains about handling the exception in Silverlight application from WCF. I have created the sample Silverlight application, which uses the WCF service for process the data. While testing the application I came to know that exception message thrown from WCF cannot be received at the client side(Silverlight application) even after using the FaultException. I was always getting System.ServiceModel.CommunicationException: The remote server returned an error: NotFound.
Later I came to know that WCF throws the HTTP 500 series Fault message but Silverlight can handle only 200 series. So we need to convert the 500 series to 200 error message for Silverlight. Here is the sample application for exception handling between WCF and Silverlight.
Step 1:
We can customize the Endpoint behavior of the WCF service by inheriting the BehaviorExtensionElement and implementing the IEndpointBehavior. Actual code for converting the 500 error serice to 200 serivce in BeforeSendReply method.
Create a ClassLibrary project and name it as "Silverlight_WCF_FaultBehavior" and name the class as "SilverlightFaultBehavior". Copy and paste the following code inside the SilverlightFaultBehavior class.
Imports System.ServiceModel.Configuration
Imports System.ServiceModel.Description
Imports System.ServiceModel.Dispatcher
Imports System.ServiceModel.Channels
Imports System.ServiceModel
Public Class
SilverlightFaultBehavior
Inherits BehaviorExtensionElement
Implements IEndpointBehavior
Public Overrides ReadOnly Property
BehaviorType() As System.Type
Get
Return GetType(SilverlightFaultBehavior)
End Get
End Property
Protected Overrides Function CreateBehavior() As Object
Return New
SilverlightFaultBehavior
End Function
Public Sub
AddBindingParameters(ByVal endpoint As System.ServiceModel.Description.ServiceEndpoint, ByVal bindingParameters As
System.ServiceModel.Channels.BindingParameterCollection) Implements
System.ServiceModel.Description.IEndpointBehavior.AddBindingParameters
End Sub
Public Sub
ApplyClientBehavior(ByVal endpoint As System.ServiceModel.Description.ServiceEndpoint, ByVal clientRuntime As
System.ServiceModel.Dispatcher.ClientRuntime) Implements
System.ServiceModel.Description.IEndpointBehavior.ApplyClientBehavior
End Sub
Public Sub
ApplyDispatchBehavior(ByVal endpoint As System.ServiceModel.Description.ServiceEndpoint, ByVal endpointDispatcher As
System.ServiceModel.Dispatcher.EndpointDispatcher) Implements
System.ServiceModel.Description.IEndpointBehavior.ApplyDispatchBehavior
Dim inspector As New SilverlightFaultMessageInspector()
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector)
End Sub
Public Sub Validate(ByVal endpoint As
System.ServiceModel.Description.ServiceEndpoint) Implementsystem.ServiceModel.Description.IEndpointBehavior.Validate
End Sub
Public Class
SilverlightFaultMessageInspector
Implements IDispatchMessageInspector
Public Function
AfterReceiveRequest(ByRef request As System.ServiceModel.Channels.Message, ByVal channel As
System.ServiceModel.IClientChannel, ByVal
instanceContext As
System.ServiceModel.InstanceContext) As Object Implements
System.ServiceModel.Dispatcher.IDispatchMessageInspector.AfterReceiveRequest
' Do nothing to the incoming message.
Return Nothing
End Function
Public Sub
BeforeSendReply(ByRef reply As System.ServiceModel.Channels.Message, ByVal correlationState As Object) Implements
System.ServiceModel.Dispatcher.IDispatchMessageInspector.BeforeSendReply
If reply.IsFault Then
Dim
[property] As New
HttpResponseMessageProperty()
'
Here the response code is changed to 200.
[property].StatusCode =
System.Net.HttpStatusCode.OK
reply.Properties(HttpResponseMessageProperty.Name)
= [property]
End If
End Sub
End Class
End Class
Note: Highlighted code shows the conversion for 500 series to 200 series error code.
Step 2:
Build the project
Step 3:
Create a new WCF service with Interface and implementation class as follows
Interface
<ServiceContract()> _
Public Interface IService
<OperationContract()> _
Function Add(ByVal
num1 As Integer,
ByVal num2 As Integer) As Integer
<OperationContract()> _
Function Subtract(ByVal
num1 As Integer,
ByVal num2 As Integer) As Integer
End Interface
Implementation
Public Class Service
Implements IService
Public Sub New()
End Sub
Public Function Add(ByVal num1 As Integer, ByVal num2 As Integer) As Integer Implements IService.Add
Throw New
FaultException("Error thrown by user for Add
operation")
'Return num1 + num2
End Function
Public Function
Subtract(ByVal num1 As Integer, ByVal
num2 As Integer)
As Integer Implements IService.Subtract
Return num1 - num2
End Function
End Class
Step 4:
Add the Silverlight_WCF_FaultBehavior project dll as reference to WCF Service
Step 5:
In WCF we can extend the binding and behavior by using <extention> tag. In our case also we are extending the custom endpoint behavior as shown below. In the <behaviorExtensions> tag we need specify the fully qualified name of the custom behavior assembly.
Modify the Web.config file as shown below
<system.serviceModel>
<services>
<service name="Service" behaviorConfiguration="ServiceBehavior">
<!-- Service
Endpoints -->
<endpoint address="" binding="basicHttpBinding" contract="IService" behaviorConfiguration="SilverlightFaultBehavior">
<!--
Upon deployment, the following identity element should be removed or
replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate
identity
automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<!-- To avoid
disclosing metadata information, set the value below to false and remove the
metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive
exception details in faults for debugging purposes, set the value below to
true. Set to false before deployment to
avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="SilverlightFaultBehavior">
<silverlightFaults/>
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="silverlightFaults" type="Silverlight_WCF_FaultBehavior.SilverlightFaultBehavior,
Silverlight_WCF_FaultBehavior, Version=1.0.0.0,
Culture=neutral,
PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
Step 6:
Create the any sample silverlight application as "Silverlight_WCF_Exception" and add this WCF service as Service Reference.
url: http://localhost/MathService/Service.svc
Step 7:
Add a button to the MainPage.xaml and call the WCF method as shown below
Private Sub Button_Click(ByVal sender As
System.Object, ByVal e As
System.Windows.RoutedEventArgs)
Dim proxy As New ServiceProxy.ServiceClient
AddHandler proxy.AddCompleted, AddressOf AddOperationCompleted
proxy.AddAsync(5, 6)
End Sub
Private Sub
AddOperationCompleted(ByVal sender As Object, ByVal e As
ServiceProxy.AddCompletedEventArgs)
If e.Error IsNot Nothing Then
MessageBox.Show(e.Error.Message)
Else
MessageBox.Show(e.Result)
End If
End Sub
Step 8:
Output will look like this
Conclusion:
This article explains about handling the exception in Silverlight application from WCF. I will get back to you guy's with another article.