none
How to catch serialization exceptions at the server side RRS feed

  • Question

  • Hi,

    I have a a few data members which are required and whose emidefaultvalue is false.Now when i dont assign values to such data members i get a serialization exception at the service(i was able to catch this only after tracing) which propogates as a communicationexception and says the underlying connection was closed. Now is there a way to catch such exceptiosn at the service itself?
    Tuesday, February 24, 2009 6:05 PM

Answers

  • You can use an IErrorHandler (http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.ierrorhandler.aspx) to accomplish that.

        public class Post_83da004b_7ddb_40e0_8d34_fd90ea48832d  
        {  
            [DataContract(Namespace = "", Name = "MyDC")]  
            public class MyDCServer  
            {  
                [DataMember(IsRequired = true)]  
                public string str = "The string";  
                [DataMember]  
                public int i = 123;  
            }  
            [DataContract(Namespace = "", Name = "MyDC")]  
            public class MyDCClient  
            {  
                [DataMember(EmitDefaultValue = false)]  
                public string str = null;  
                [DataMember]  
                public int i = 123;  
            }  
            [ServiceContract(Name = "ITest", Namespace = "")]  
            public interface ITestServer  
            {  
                [OperationContract]  
                [FaultContract(typeof(string), Action = Service.FaultAction)]  
                MyDCServer EchoDC(MyDCServer input);  
            }  
            [ServiceContract(Name = "ITest", Namespace = "")]  
            public interface ITestClient  
            {  
                [OperationContract]  
                [FaultContract(typeof(string), Action = Service.FaultAction)]  
                MyDCClient EchoDC(MyDCClient input);  
            }  
            public class Service : ITestServer  
            {  
                public const string FaultAction = "http://my.fault/serializationError";  
                public MyDCServer EchoDC(MyDCServer input)  
                {  
                    return input;  
                }  
            }  
            public class MyErrorHandler : IErrorHandler  
            {  
                public bool HandleError(Exception error)  
                {  
                    return error is FaultException && (error.InnerException as SerializationException != null);  
                }  
     
                public void ProvideFault(Exception error, MessageVersion version, ref Message fault)  
                {  
                    if (error is FaultException)  
                    {  
                        SerializationException serException = error.InnerException as SerializationException;  
                        if (serException != null)  
                        {  
                            string detail = String.Format("{0}: {1}", serException.GetType().FullName, serException.Message);  
                            FaultException<string> faultException = new FaultException<string>(detail, new FaultReason("SerializationException caught while deserializing parameter from the client"));  
                            MessageFault messageFault = faultException.CreateMessageFault();  
                            fault = Message.CreateMessage(version, messageFault, Service.FaultAction);  
                        }  
                    }  
                }  
            }  
            public class MyServiceBehavior : IServiceBehavior  
            {  
                public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)  
                {  
                }  
                public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)  
                {  
                    foreach (ChannelDispatcher disp in serviceHostBase.ChannelDispatchers)  
                    {  
                        disp.ErrorHandlers.Add(new MyErrorHandler());  
                    }  
                }  
                public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)  
                {  
                    foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints)  
                    {  
                        if (endpoint.Contract.ContractType == typeof(IMetadataExchange)) continue;  
                        foreach (OperationDescription operation in endpoint.Contract.Operations)  
                        {  
                            FaultDescription expectedFault = operation.Faults.Find(Service.FaultAction);  
                            if (expectedFault == null || expectedFault.DetailType != typeof(string))  
                            {  
                                throw new InvalidOperationException("Operation must have FaultContract(typeof(string))");  
                            }  
                        }  
                    }  
                }  
            }  
            static Binding GetBinding()  
            {  
                BasicHttpBinding result = new BasicHttpBinding();  
                return result;  
            }  
            public static void Test()  
            {  
                //string baseAddress = "http://" + Environment.MachineName + ":8000/Service";  
                string baseAddress = "http://localhost:8000/Service";  
                ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));  
                host.AddServiceEndpoint(typeof(ITestServer), GetBinding(), "");  
                host.Description.Behaviors.Add(new MyServiceBehavior());  
                host.Open();  
                Console.WriteLine("Host opened");  
     
                ChannelFactory<ITestClient> factory = new ChannelFactory<ITestClient>(GetBinding(), new EndpointAddress(baseAddress));  
                ITestClient proxy = factory.CreateChannel();  
     
                try 
                {  
                    Console.WriteLine(proxy.EchoDC(new MyDCClient()));  
                }  
                catch (Exception e)  
                {  
                    Console.WriteLine(e);  
                }  
     
                ((IClientChannel)proxy).Close();  
                factory.Close();  
     
                Console.Write("Press ENTER to close the host");  
                Console.ReadLine();  
                host.Close();  
            }  
        }  
     
    Saturday, February 28, 2009 11:45 AM

All replies

  • -> Now is there a way to catch such exceptiosn at the service itself?

    When you catch such an exception, what type of programming logic you are supposed to perform?

    Thanks
    Another Paradigm Shift
    http://shevaspace.blogspot.com
    • Edited by Marco Zhou Thursday, February 26, 2009 10:13 AM bad typo
    Thursday, February 26, 2009 10:12 AM
  • The problem i am facing here is when a serialization excetion occurs,it is not thrown as a faultexception. So i want to be able to catch it as a fault exception in my client with a fault reason saying the serilization failed because xx paramter is required andhas emit default value set to true but the vale is false.
    Saturday, February 28, 2009 3:21 AM
  • Can you post some code over here. It would be easy then to discuss.
    Adil Mughal - MCP - http://adilamughal.blogspot.com
    Saturday, February 28, 2009 6:02 AM
  • You can use an IErrorHandler (http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.ierrorhandler.aspx) to accomplish that.

        public class Post_83da004b_7ddb_40e0_8d34_fd90ea48832d  
        {  
            [DataContract(Namespace = "", Name = "MyDC")]  
            public class MyDCServer  
            {  
                [DataMember(IsRequired = true)]  
                public string str = "The string";  
                [DataMember]  
                public int i = 123;  
            }  
            [DataContract(Namespace = "", Name = "MyDC")]  
            public class MyDCClient  
            {  
                [DataMember(EmitDefaultValue = false)]  
                public string str = null;  
                [DataMember]  
                public int i = 123;  
            }  
            [ServiceContract(Name = "ITest", Namespace = "")]  
            public interface ITestServer  
            {  
                [OperationContract]  
                [FaultContract(typeof(string), Action = Service.FaultAction)]  
                MyDCServer EchoDC(MyDCServer input);  
            }  
            [ServiceContract(Name = "ITest", Namespace = "")]  
            public interface ITestClient  
            {  
                [OperationContract]  
                [FaultContract(typeof(string), Action = Service.FaultAction)]  
                MyDCClient EchoDC(MyDCClient input);  
            }  
            public class Service : ITestServer  
            {  
                public const string FaultAction = "http://my.fault/serializationError";  
                public MyDCServer EchoDC(MyDCServer input)  
                {  
                    return input;  
                }  
            }  
            public class MyErrorHandler : IErrorHandler  
            {  
                public bool HandleError(Exception error)  
                {  
                    return error is FaultException && (error.InnerException as SerializationException != null);  
                }  
     
                public void ProvideFault(Exception error, MessageVersion version, ref Message fault)  
                {  
                    if (error is FaultException)  
                    {  
                        SerializationException serException = error.InnerException as SerializationException;  
                        if (serException != null)  
                        {  
                            string detail = String.Format("{0}: {1}", serException.GetType().FullName, serException.Message);  
                            FaultException<string> faultException = new FaultException<string>(detail, new FaultReason("SerializationException caught while deserializing parameter from the client"));  
                            MessageFault messageFault = faultException.CreateMessageFault();  
                            fault = Message.CreateMessage(version, messageFault, Service.FaultAction);  
                        }  
                    }  
                }  
            }  
            public class MyServiceBehavior : IServiceBehavior  
            {  
                public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)  
                {  
                }  
                public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)  
                {  
                    foreach (ChannelDispatcher disp in serviceHostBase.ChannelDispatchers)  
                    {  
                        disp.ErrorHandlers.Add(new MyErrorHandler());  
                    }  
                }  
                public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)  
                {  
                    foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints)  
                    {  
                        if (endpoint.Contract.ContractType == typeof(IMetadataExchange)) continue;  
                        foreach (OperationDescription operation in endpoint.Contract.Operations)  
                        {  
                            FaultDescription expectedFault = operation.Faults.Find(Service.FaultAction);  
                            if (expectedFault == null || expectedFault.DetailType != typeof(string))  
                            {  
                                throw new InvalidOperationException("Operation must have FaultContract(typeof(string))");  
                            }  
                        }  
                    }  
                }  
            }  
            static Binding GetBinding()  
            {  
                BasicHttpBinding result = new BasicHttpBinding();  
                return result;  
            }  
            public static void Test()  
            {  
                //string baseAddress = "http://" + Environment.MachineName + ":8000/Service";  
                string baseAddress = "http://localhost:8000/Service";  
                ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));  
                host.AddServiceEndpoint(typeof(ITestServer), GetBinding(), "");  
                host.Description.Behaviors.Add(new MyServiceBehavior());  
                host.Open();  
                Console.WriteLine("Host opened");  
     
                ChannelFactory<ITestClient> factory = new ChannelFactory<ITestClient>(GetBinding(), new EndpointAddress(baseAddress));  
                ITestClient proxy = factory.CreateChannel();  
     
                try 
                {  
                    Console.WriteLine(proxy.EchoDC(new MyDCClient()));  
                }  
                catch (Exception e)  
                {  
                    Console.WriteLine(e);  
                }  
     
                ((IClientChannel)proxy).Close();  
                factory.Close();  
     
                Console.Write("Press ENTER to close the host");  
                Console.ReadLine();  
                host.Close();  
            }  
        }  
     
    Saturday, February 28, 2009 11:45 AM