I think every Silverlight developer has seen at least once, an exception showing a message “The remote server returned an error: NotFound” while connecting to a WCF Service. Alright, that message could have been a better message, but why are we getting this message?
Yes, you probably figured that out yourself, something is wrong with your WCF Service, and it’s not a missing WCF Service. Yes it feels something is seriously wrong, why do we get this strange NotFound message?
If anything goes wrong, the WCF Service returns some data, but also sets the HTTP Status code to 500. The browser HTTP stack doesn’t allow to read the data when the HTTP Status code is 500.
Solution 1:
There’s an easy solution to solve this: Don’t use the browser HTTP stack but the client HTTP stack instead. Just a matter of adding the below line of code in the Application_Startup method in the App.xaml.cs.
WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);Solution 2:
Because sometimes you don’t want to make use of the client HTTP stack but rather like the browser HTTP stack there’s a solution for that as well. If you’re using the browser HTTP stack you’ll get things like Windows Authentication and automatic Cookie handling.
Because of the extreme flexibility of WCF and really a lot of hook-points we can change the behavior of the HTTP Status code in case of errors. There’s a MSDN article which explains this in detail. The only real important part is line 18, which changes the Status code to 200 in case of Faults.
public class SilverlightFaultBehavior : BehaviorExtensionElement, IEndpointBehavior
{
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
var inspector = new SilverlightFaultMessageInspector();
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
}
public class SilverlightFaultMessageInspector : IDispatchMessageInspector
{
public void BeforeSendReply(ref Message reply, object correlationState)
{
if (reply.IsFault)
{
// Here the response code is changed to 200.
var property = new HttpResponseMessageProperty { 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;
}
}
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();
}
}Of course you need to configure the services to use this behavior.
<system.serviceModel> <extensions> <behaviorExtensions> <add name="silverlightFaults" type="Silverlight.Poc.SilverlightFaultBehavior, Silverlight.Poc, Version=1.0.0.0, Culture=neutral"/> </behaviorExtensions> </extensions> <services> ... </services> <behaviors> <endpointBehaviors> <behavior name=""> <silverlightFaults/> </behavior> </endpointBehaviors> <serviceBehaviors> <behavior name=""> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> </serviceBehaviors> </behaviors> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> </system.serviceModel>
Exception details
Next you might actual want to see the details of exceptions that occur in the service on the client. The simple solution is to just allow the service to include the exception details in Faults.
<serviceDebug includeExceptionDetailInFaults="true" />
You would want to do this in a development and maybe in a test environment, but not for production. In the production environment you’ll only want to provide known faults. Yes in a lot of situations there are known faults which in essence are very similar to application specific exceptions.
If you want to enable a known Fault on your WCF Service you will need to create a FaultContract and also decorate the ServiceContract with information about what kind of Faults in can expect. Let’s start with a simple FaultContract which is in this case a simple DataContract.
[DataContract]
public class AuthenticationFault
{
[DataMember]
public string Reason { get; set; }
}We decorate the Service with a FaultContract attribute which references the datacontract we created in the previous step.
[OperationContract] [FaultContract(typeof(AuthenticationFault))] List<Package> FindPackages(PackageQuery query);
Alright we now only need a way to fire a WCF Fault. This is similar to the way we fire normal exceptions, but an instance of the Fault DataContract will be added to the Fault.
throw new FaultException<AuthenticationFault>(new AuthenticationFault(), new FaultReason("Authentication failed."));


