WCF CommunicationException with no Exception message details - wcf

One of the things I never understood about WCF is why no Exception message details are propagated back to the calling client when the server encounters an unhandled exception.
For example, if I have the following server code
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class Server : IServer
{
public DTO GetDTO()
{
DTO dto = new DTO();
dto.dto = dto;
return dto;
}
}
public class DTO
{
public DTO dto;
}
[ServiceContract]
public interface IServer
{
[OperationContract]
DTO GetDTO();
}
I deliberately introduced an ObjectGraph to cause a serialization exception when the DTO object is returned.
If I have a client that calls this Server's GetDTO() method, I will get the following CommunicationException.
The socket connection was aborted. This could be caused by an error
processing your message or a receive timeout being exceeded by the
remote host, or an underlying network resource issue. Local socket
timeout was '00:00:58.9350000'.
Which is absolutely useless. It has no inner exception and not even the real exception message.
If you then use Microsoft Service TraceViewer, you will see the exception but you must turn on the Diagnostics tracing for this.
The exception message that should be sent back is
There was an error while trying to serialize parameter
http://tempuri.org/:GetDTOResult. The InnerException message was
'Object graph for type 'TestWCFLib.DTO' contains cycles and cannot be
serialized if reference tracking is disabled.'. Please see
InnerException for more details.
So can anybody tell me how get the right exception message show up on the client side? Obviously, setting IncludeExceptionDetailInFaults to true doesn't make a difference.

I think that it is by design that the server errors are not propogated to client. This is in general a practice to not expose server internals to clients as the main purpose of Client Server architecture is independence of server.
You can still achieve this by using Fault Exception
Decorate your service declaration with a fault contract
[ServiceContract]
public interface IServer
{
[OperationContract]
[FaultContract(typeof(MyApplicationFault))]
DTO GetDTO();
}
Then catch errors in servcie implementation and throw a fault exception.
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class Server : IServer
{
public DTO GetDTO()
{
try
{
DTO dto = new DTO();
dto.dto = dto;
return dto;
}
catch (Exception ex)
{
MyApplicationFault fault = new MyApplicationFault(...);
throw new FaultException<MyApplicationFault>(fault);
}
}
}
And catch the exception in client
IServer proxy = ...; //Get proxy from somewhere
try
{
proxy.GetDTO();
}
catch (TimeoutException) { ... }
catch (FaultException<MyApplicationFault> myFault) {
MyApplicationFault detail = myFault.Detail;
//Do something with the actual fault
}
catch (FaultException otherFault) { ... }
catch (CommunicationException) { ... }
Hope this helps.
For a nice tutorial please see Code Project Tutorial on Fault Exception

Related

WCF catch custom FaultException

I Want to use custome FaultException like this
[DataContract]
public class Fault
{
[DataMember]
public string Message { get; set; }
}
public class MyFault<T>:FaultException<T> where T : Fault
{
public MyFault(T faultClass)
: base(faultClass, new FaultReason(faultClass.Message))
{
}
}
...
throw new MyFault<Fault>(new Fault {Message = "hello"});
...
Interface
[OperationContract]
[FaultContract(typeof(Fault))]
string GetData2(int value);
but when it get to the client it's transform to FaultException
try
{
var res = serv.GetData2(1);
}
catch (MyFault<WcfService1Sample.Fault> ex)
{
label1.Text = ex.Reason.ToString(); //-> i want here
}
catch (FaultException<ServiceReference1.Fault> ex)
{
label1.Text = ex.Reason.ToString(); //-> catch here
}
catch (Exception)
{
throw;
}
can i catch custom fault on clint ?
or the WCF automatic convert it to FaultException
how do i make this issue work
thanks kfir
There are two issues, I think. First:
What shambulator said: Your custom Fault class must be
a DataContract, and use
DataMember to mark all properties that shall be serialized.
If this is done, then WCF will
translate a service-side throw new FaultException<MyFault>(new MyFault { ... }); into a message which contains your fault, including the data; and
translate this fault on the client-side to a FaultException<MyFault>.
Second:
This client-side FaultException<> is generated by WCF. Maybe one can register a custom Exception-Translator, but I have never used it, never needed it, and not found such a thing after a one-minute Google search. I'd recommend just going with the FaultException plus custom Fault-type.

Why does the following code return an error when consuming multiple endpoints of a WCF service?

I have created a multi-endpoint WCF service and consumed and it is working fine.
But when I am trying to close the service client then am getting error.
This is how I am creating the client object and disposing its working fine for single endpoint WCF service
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
ICardPrintingService Service = null;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Service = new CardPrintingServiceClient();
var response = this.Service.GetCardData(new GetCardDataRequest { NIK = 6666620501740003 });
try
{
((CardPrintingServiceClient)Service).Close();
}
catch (Exception ex)
{
MessageBox.Show("error");
}
}
}
}
This is going to the catch block when closing the connection with error message
The remote endpoint no longer recognizes this sequence. This is most
likely due to an abort on the remote endpoint. The value of
wsrm:Identifier is not a known Sequence identifier. The reliable
session was faulted.
Can some one tell me why?
Thanks a ton in adv
Raghavendra
What is the need of casting overhere.
((CardPrintingServiceClient)Service).Close(); //pls explain this.
you can try this in finally block.
if (Service.State != System.ServiceModel.CommunicationState.Closed)
{
Service.Abort();
}

How to throw an exception to the client over wcf callback

I have a wcf service which has a one way operation and it sends the result in a callback. Here is my service definition
[ServiceContract(CallbackContract = typeof(IIrmCallback), SessionMode = SessionMode.Required)]
public interface IFileService
{
[OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
[ServiceKnownType(typeof(StatementFile))]
[ServiceKnownType(typeof(InvoiceFile))]
void UploadFile(IFile file);
}
public interface IFileCallback
{
[OperationContract]
void FileProcessed(string result);
}
public MyService : IFileService
{
IFileCallBack callbackchannel;
object result;
public void UploadFile(IFile file)
{
callbackChannel = OperationContext.Current.GetCallbackChannel<IIrmCallback>();
Task.Factory.StartNew(() => ProcessFile(file));
}
private ProcessFile(IFile file)
{
// file gets processed
callbackChannel.FileProcessed(result)
}
}
So now if there is some error during the file processing is there someway I can throw an exception back to the caller in the callback?
You can use FaultException
When an operation throws an exception, a FaultException will be returned to the client.
You need to implement a FaultContract in your service interface specifying the types of faults that are possible in that given method and then throw a new fault that inherits from FaultException within the method.
On the client, make sure to catch and handle FaultException and Exception objects individually because Exceptions will cause the WCF channel to fault and it cannot be reused, while a FaultException will allow you to continue using the existing channel.

Wcf exception handling throw an error

Hi I have a problem handling exceptions in wcf.
I have a service like this one:
[ServiceContract]
public interface IAddressService
{
[OperationContract]
[FaultContract(typeof(ExecuteCommandException))]
int SavePerson(string idApp, int idUser, Person person);
}
I am calling the SavePerson() on the service in the WCFTestClient utility.
The SavePerson() implementation is:
public int SavePerson(string idApp, int idUser, Person person)
{
try
{
this._savePersonCommand.Person = person;
this.ExecuteCommand(idUser, idApp, this._savePersonCommand);
return this._savePersonCommand.Person.Id;
}
catch (ExecuteCommandException ex)
{
throw new FaultException<ExecuteCommandException>(ex, new FaultReason("Error in 'SavePerson'"));
}
}
But I get this error:
Failed to invoke the service. Possible
causes: The service is offline or
inaccessible; the client-side
configuration does not match the
proxy; the existing proxy is invalid.
Refer to the stack trace for more
detail. You can try to recover by
starting a new proxy, restoring to
default configuration, or refreshing
the service.
if I change the SavePerson method and instead of:
catch (ExecuteCommandException ex)
{
throw new FaultException<ExecuteCommandException>(ex, new FaultReason("Error in 'SavePerson'"));
}
I do
catch(Exception)
{
throw;
}
I don't get the above error, but I only get the exception message and no inner exception.
What am I doing wrong?
When you define the fault contract:
[FaultContract(typeof(ExecuteCommandException))]
you must not specify an exception type. Instead, you specify a data contract of your choice to pass back any values that you deem necessary.
For example:
[DataContract]
public class ExecuteCommandInfo {
[DataMember]
public string Message;
}
[ServiceContract]
public interface IAddressService {
[OperationContract]
[FaultContract(typeof(ExecuteCommandInfo))]
int SavePerson(string idApp, int idUser, Person person);
}
catch (ExecuteCommandException ex) {
throw new FaultException<ExecuteCommandInfo>(new ExecuteCommandInfo { Message = ex.Message }, new FaultReason("Error in 'SavePerson'"));
}

Serializable exception and WCF

if i made my exception Serializable like this article from msdn , so can my exception serialized over WCF ?
Yes you can serialize exceptions and return them with WCF. I wrote an app where it was necessary for the WCF client to have the real exception that occurred on the server; not just a high level fault.
Here are the steps to implement what we have done:
1 - Declare a class EncodedException with a single string property
public class EncodedException
{
public string SerializedException {get;set;}
}
2 - On your service contract add the attribute to indicate that your service could return a FaultException exception.
[ServiceContract()]
public class MyService
{
[OperationContract]
[FaultContract(typeof(EncodedException),
ProtectionLevel = ProtectionLevel.EncryptAndSign)]
public string Method1 ();
}
3 - In you service implementation add a try/catch in all service operations:
public void Method1()
{
try
{
// some code here
}
catch( Exception ex)
{
EncodedException encodedException = Helper.SerializeException( ex );
throw new FaulException<EncodedException>();
}
}
4 - In your client code catch the exception and unwrap it:
public void someMethod()
{
try
{
serviceClient.Method1();
}
catch( FaulException<EncodedException> ex)
{
Exception decodedException = Helper.DeserializeException( ex );
throw new decodedException();
}
}
5 - Write the Helper to serialize/deserialize the exception. If you need help with that part too, let me know.
I hope this helps.
I don't see why not, if you've successfully created an object that can be serialized over classic asmx, then it be fine in WCF.