WCF CommunicationException with no Exception message details

こ雲淡風輕ζ 提交于 2019-12-10 15:51:37

问题


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.


回答1:


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



来源:https://stackoverflow.com/questions/7404478/wcf-communicationexception-with-no-exception-message-details

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!