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 EventHandlerThen handle any error situation in the completed event:(client_ThrowExceptionMethodCompleted); client.ThrowExceptionMethodAsync(); }
void client_ThrowExceptionMethodCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { if (e.Error == null) MessageBox.Show("Call sucessfull"); else { string msg; FaultExceptionfex = 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