1

I am experimenting with a WCF service in a Visual Studio unit test. Both the client and the service are configured programmatically.

Currently my code looks like this:

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Tests
{
    public abstract class EntityBase
    {
    }

    public class TestEntity : EntityBase
    {
        public string Name { get; set; }
    }

    [ServiceContract]
    [ServiceKnownType("GetKnownTypes", typeof(ServiceKnownTypesDiscoveryHelper))]
    public interface ITestService
    {
        [OperationContract]
        EntityBase GetEntity(string entityName);
    }

    public class TestService : ITestService
    {
        public EntityBase GetEntity(string entityName)
        {
            Type t = Type.GetType(entityName);
            return (EntityBase)Activator.CreateInstance(t);
        }
    }

    [TestClass]
    public class ServiceTests
    {
        private static ServiceHost ServiceHost { get; set; }

        [ClassInitialize]
        public static void ClassInitialize(TestContext testContext)
        {        
            ServiceHost = new ServiceHost(typeof(TestService));
            NetTcpBinding wsBinding = new NetTcpBinding();

            ServiceHost.AddServiceEndpoint(typeof(ITestService), wsBinding,
                "net.tcp://localhost:8011/TestService");

// trying to turn on debugging here
            var behavior = ServiceHost.Description.Behaviors.Find<ServiceDebugBehavior>();
            behavior.IncludeExceptionDetailInFaults = true;

            ServiceHost.Open();
        }

        [ClassCleanup]
        public static void ClassCleanup()
        {
            ServiceHost.Close();
        }

        [TestMethod]
        public void TestSomething()
        {
            var binding = new NetTcpBinding();
            var endpoint = new EndpointAddress("net.tcp://localhost:8011/TestService");

            using (ChannelFactory<ITestService> testServiceFactory =
                                            new ChannelFactory<ITestService>(binding, endpoint))
            {
                var proxy = testServiceFactory.CreateChannel();
                using (proxy as IDisposable)
                {
                    try
                    {
                        var entity = proxy.GetEntity(typeof(TestEntity).FullName);
                        Assert.IsInstanceOfType(entity, typeof(TestEntity));
                    }
                    catch (FaultException ex)
                    {
// copied this from MSDN example
                        string msg = "FaultException: " + ex.Message;
                        MessageFault fault = ex.CreateMessageFault();
                        if (fault.HasDetail == true)
                        {
                            var reader = fault.GetReaderAtDetailContents();
                            if (reader.Name == "ExceptionDetail")
                            {
                                ExceptionDetail detail = fault.GetDetail<ExceptionDetail>();
                                msg += "\n\nStack Trace: " + detail.StackTrace;
                            }
                        }
                        System.Diagnostics.Trace.WriteLine(msg);
                    }
                }
            }
        }
    }
}

If my ServiceKnownTypesDiscoveryHelper does not return known types, I know that my service and client should throw something serialisation related somewhere deep in .NET servicemodel code (if I modify it to return my TestEntity then of course everything works without any issues).

But currently if the service fails, I get only some vague exception messages like:

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.

and at the end of using() I get

The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.

(which also is weird - why can't I even dispose the ServiceChannel if it's in a faulted state...)

How do I catch the actual fault which caused the service or the client to fail instead of those vague exception messages?

JustAMartin
  • 13,165
  • 18
  • 99
  • 183

0 Answers0