How to Determine the Cause from WCF Connection Errors

Asked 2 years ago, Updated 2 years ago, 94 views

.NET Framework 4.5 creates WCF services and client applications that utilize them.
Custom classes and enumerations used for arguments and returns for WCF services may forget to attach the DataMember or EnumMember attributes, but it is difficult to determine the cause from the exception message that occurs on the client side.
If the return value is a custom class and you forget to attach the EnumMember attribute to a member of the enum that you are using in any of its properties, you will get the following error:

Exception type: System.ServiceModel.CommunicationException
Message:The underlying connection was closed: The connection that should have been maintained was disconnected by the server
実際Actually, TargetInvocationException occurred, and the InnerException contained the above CommunicationException.

I learned from this message that there is a possibility of forgetting to attribute around the data contract.
However, the specific cause of where and what you forgot to attach is the situation where you are only visually examining the code.
Is there any way to make debugging easier?

Write down the results of the ToString exception.
System.Reflection.TargetInvocationException: 呼び出しのターゲットが例外をスローしました。 ---> System.ServiceModel.CommunicationException: 基礎になる接続が閉じられました: 維持される必要があった接続が、サーバーによって切断されました ---> System.Net.WebException: 基礎になる接続が閉じられました: 維持される必要があった接続が、サーバーによって切断されました ---> System.IO.IOException: 転送接続からデータを読み取れません: 既存の接続はリモート ホストに強制的に切断されました。。 ---> System.Net.Sockets.SocketException—An existing connection was forced to disconnect to the remote host.
*The stack trace below is omitted

c# wcf

2022-09-30 18:06

3 Answers

For EnumMember, look at the internal exception error message instead of CommunicationException and you should know the cause, including the field name.
excursion.ToString() should be printed in the log.


2022-09-30 18:06

I wrote a code to check the data controller.
It's also good to look at the runtime log, but it's also good to have it guaranteed in advance. I think it's one way.
I think it would be better to check the data controller in advance by a single test.
In my case, the check runs only when debugging is performed.
For your information.

using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;

namespace tests
{
# if DEBUG

    // Declare enum for testing
    DataContract
    public enum MyEnum
    {
        EnumMember
        Enum1,

        EnumMember
        Enum2,

        // This is the error
        Enum 3,
    }

    // Declare data controller for testing
    DataContract
    public class MyData
    {
        DataMember
        public MyEnum MyEnum {get;set;}
    }

    // Class for checking data controllers
    public static class DataContractChecker
    {
        // Check the data controller from an Instance
        // It might be easier to check when you run debugging.
        public static void Assert (object dataContract)
        {
            Debug.Assert (dataContract!=null);
            Assert(dataContract.GetType());
        }

        // Check from type.
        // I think it's easier to do unit tests, etc.
        public static void Assert (Type dataContractType)
        {
            // The DataContract attribute is specified.
            Debug.Assert(dataContractType.CustomAttributes.Any(atr=>atr.AttributeType==typeof(DataContractAttribute),
                string.Format("class{0} requires DataContract attribute", dataContractType.FullName));

            // List the properties marked with DataMember and limit the properties to enum
            varq = dataContractType.GetProperties (BindingFlags.Instance | BindingFlags.Public)
                .Where(p=>p.CustomAttributes.Any(atr=>atr.AttributeType==typeof(DataMemberAttribute)))
                .Where(p=>p.PropertyType.IsEnum)
                .Select(p=>p.PropertyType);

            foreach (varet in q)
            {
                // Enum also has DataContract attribute
                Debug.Assert(et.CustomAttributes.Any(atr=>atr.AttributeType==typeof(DataContractAttribute))),
                    string.Format("enum{0} requires DataContractAttribute attribute", et.FullName);

                foreach(varevinet.GetEnumValues())
                {
                    varen=ev.GetType().GetField(ev.ToString());

                    // Enum enumerator has EnumMember attribute
                    Debug.Assert(en.GetCustomAttributes(typeof(EnumMemberAttribute), false).Length==1,
                        string.Format ("enum {0}/{1} requires EnumMember attribute", et.FullName, en.Name);
                }
            }
        }

        // Here is a sample of how to call method.
        public static void test()
        {
            Assert(typeof(MyData)));
            Assistant (new MyData());
        }
    }
#endif
}


2022-09-30 18:06

If you change the config file to output the wcf trace log and view the output log from the tool below, you may be able to find out more about it.

You can find instructions on how to configure trace log output on the following MSDN page:

cf.Service Trace Viewer Tool (SvcTraceViewer.exe)


2022-09-30 18:06

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.