First wire up the service call:
private void Button_Click_1(object sender, RoutedEventArgs e)
{
TestRef.TestServiceClient client = new TestSilverlightApplication3.TestRef.TestServiceClient();
client.ThrowExceptionMethodCompleted += new EventHandler(client_ThrowExceptionMethodCompleted);
client.ThrowExceptionMethodAsync();
}
Then handle any error situation in the completed event:void client_ThrowExceptionMethodCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
if (e.Error == null)
MessageBox.Show("Call sucessfull");
else
{
string msg;
FaultException fex = e.Error as FaultException;
if (fex != null)
msg = string.Format("Fault Exception recevied. Reason: {0}, Message: {1}", fex.Reason, e.Error.Message);
else
msg = string.Format("Error recevied of type: {0}, Message: {1}",e.Error.GetType(),e.Error.Message);
MessageBox.Show(msg);
}
}
Here you can see that we test the ‘e.Error’ property to see if its an exception of type FaultException, otherwise the error will flow through generally as a CommunicationException as per normal WCF behaviour.
That all sounds easy, however you still need to tell the WCF service (or more specifically WCF itself) to return the fault using a HTTP status code of 200 (OK) instead of a HTTP status code of 500 (server error) which is the default. If you don’t do this, then the error will always come through as a CommunicationException .
You need a little bit of code and configuration for this. First you need to define a custom behaviour like so:
public class SilverlightFaultBehavior : BehaviorExtensionElement, IEndpointBehavior
{
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
SilverlightFaultMessageInspector inspector = new SilverlightFaultMessageInspector();
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
}
public class SilverlightFaultMessageInspector : IDispatchMessageInspector
{
public void BeforeSendReply(ref Message reply, object correlationState)
{
if (reply.IsFault)
{
HttpResponseMessageProperty property = new HttpResponseMessageProperty();
// Here the response code is changed to 200.
property.StatusCode = System.Net.HttpStatusCode.OK;
reply.Properties[HttpResponseMessageProperty.Name] = property;
}
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
// Do nothing to the incoming message.
return null;
}
}
// The following methods are stubs and not relevant.
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
public override System.Type BehaviorType
{
get { return typeof(SilverlightFaultBehavior); }
}
protected override object CreateBehavior()
{
return new SilverlightFaultBehavior();
}
}
Then some config:
So, its still not quite there yet, but its better. It would be nice if this status code behaviour were part of the default Silverlight service template and that it was a provided behaviour, rather than a roll your own custom one.<system.serviceModel> <extensions> <behaviorExtensions> <add name=”silverlightFaults” type=”Microsoft.Silverlight.Samples.SilverlightFaultBehavior, SilverlightFaultBehavior, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”/> </behaviorExtensions> </extensions> <behaviors> <endpointBehaviors> <behavior name=”SilverlightFaultBehavior”> <silverlightFaults/> </behavior> </endpointBehaviors> </behaviors> <services> <service name=”Calculator.Web.Service”> <endpoint address=”” binding=”basicHttpBinding” contract=”Calculator.Web.Service” behaviorConfiguration=”SilverlightFaultBehavior” /> </service> </services> </system.serviceModel>

1 comments:
Thanks it is helpful :)
Post a Comment