Member 14779968 Ответов: 1

Как исправить проблему stackoverflowexception?


Здравствуйте, я занимаюсь функциональным тестированием API. Эта ошибка произошла, когда я пытаюсь сериализовать свою полезную нагрузку json. Когда я пытаюсь запустить свой тест, я получаю следующую ошибку
- Активный тестовый запуск был прерван. Причина: сбой процесса тестового хоста : процесс завершается из-за исключения StackOverflowException"
Мой вспомогательный метод работал нормально, но я думаю, что где-то у него есть бесконечная рекурсия. Вот разбивка различных классов, которые у меня есть.
У меня есть один вспомогательный класс, и с помощью custom ContractResolver я выбираю имя методов и атрибуты, к которым хочу применить, а затем использую свой собственный метод сериализации. Пожалуйста, любой помощник от любого эксперта c#, который будет высоко оценен!

public class Helper
    {
        public void Asserts(HttpWebResponse response)
        {
            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
        }


        [AttributeUsage(AttributeTargets.Property)]
        public class UseWithApiMethodsAttribute : Attribute
        {
            public UseWithApiMethodsAttribute(params string[] methodNames)
            {
                MethodNames = methodNames;
            }

            public string[] MethodNames { get; private set; }
        }

        public class SelectivePropertyResolver : DefaultContractResolver
        {
            public string ApiMethodName { get; private set; }

            public SelectivePropertyResolver(string apiMethodName)
            {
                ApiMethodName = apiMethodName;
            }

            protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
            {
                JsonProperty prop = base.CreateProperty(member, memberSerialization);
                if (member.MemberType == MemberTypes.Property)
                {
                    var att = ((PropertyInfo)member).GetCustomAttribute<UseWithApiMethodsAttribute>(true);
                    if (att == null || !att.MethodNames.Contains(ApiMethodName))
                    {
                        prop.Ignored = true;
                    }
                }
                return prop;
            }
        }

        public string SerializeForApiMethod(Object model, string methodName)
        {
            var settings = new JsonSerializerSettings
            {
                ContractResolver = new SelectivePropertyResolver(methodName),
                Formatting = Formatting.Indented
            };
            return JsonConvert.SerializeObject(model, settings);
        }
    }



Вот мой класс модели под названием TagModel, где я использую get и set и присваиваю значения

public class TagModel
    {

        public TagModel defaultModel = new TagModel
        {
            endpointIds = new List<int> { -2147483612, -2147483611 },
            tagIds = new List<int> { 35, 37 },
            id = -2147483639,
            parentId = 37,
            nodeId = 1,
            oldParentId = null,
            isEndpoint = false,
            state = 2,
            destinationTag = 2,

        };

        public TagModel modelForUpdate = new TagModel
        {
            tagNode = new TagModel.TagNode
            {
                query = null,
                type = 0,
                filter = null,
                ldapPaths = null,
                editPermissions = 0,
                id = 0,
                disallowed = false,
                name = "NewTag"

            },
            parentId = 7
        
        };

        [UseWithApiMethods("UpdateTag")]
        public TagNode tagNode { get; set; }


        public class TagNode
        {
            [UseWithApiMethods("UpdateTag")]
            public object query { get; set; }
            [UseWithApiMethods("UpdateTag")]
            public int type { get; set; }
            [UseWithApiMethods("UpdateTag")]
            public object filter { get; set; }
            [UseWithApiMethods("UpdateTag")]
            public object ldapPaths { get; set; }
            [UseWithApiMethods("UpdateTag")]
            public int editPermissions { get; set; }
            [UseWithApiMethods("UpdateTag")]
            public int id { get; set; }
            [UseWithApiMethods("UpdateTag")]
            public bool disallowed { get; set; }
            [UseWithApiMethods("UpdateTag")]
            public string name { get; set; }
        }


        [UseWithApiMethods("UpdateTagToRoot")]
        public int nodeId { get; set; }
        [UseWithApiMethods("UpdateTagToRoot")]
        public object oldParentId { get; set; }
        [UseWithApiMethods("UpdateTagToRoot")]
        public bool isEndpoint { get; set; }
        [UseWithApiMethods("UpdateTagToRoot")]
        public int state { get; set; }
        [UseWithApiMethods("UpdateTagToRoot")]
        public int destinationTag { get; set; }




        [UseWithApiMethods("UpdateEndpointsToTags")]
        public List<int> endpointIds { get; set; }
        [UseWithApiMethods("UpdateEndpointsToTags")]
        public List<int> tagIds { get; set; }


        [UseWithApiMethods("UpdateEndpointsFromTags")]
        public int id { get; set; }
        [UseWithApiMethods("UpdateEndpointsFromTags", "UpdateTag")]
        public int parentId { get; set; }




    }


}


Наконец, у меня есть еще один класс, где мой метод fuction называется "Теги", где я пришел, вызывая SerializeForApiMethod и передавая экземпляр класса модели и имя метода. Этот класс также наследует класс TagModel

public class Tags : TagModel
    {
        public string BaseUrl = RequestHandler.GenerateRequestURL("svc-searchcontroller") + "Tag/";
        public Helper helper = new Helper();


        public HttpWebResponse UpdateTag()
        {
            RequestHandler requestor = new RequestHandler(BaseUrl + "UpdateTag", HttpVerb.POST, AuthenticationType.Bearer);
            return requestor.SendRequest(helper.SerializeForApiMethod(modelForUpdate, "UpdateTag"));
        }

   
     
    
        public HttpWebResponse UpdateEndpointsFromTags()
        {
            RequestHandler requestor = new RequestHandler(BaseUrl + "UpdateEndpointsFromTags", HttpVerb.POST, AuthenticationType.Bearer);
            return requestor.SendRequest(helper.SerializeForApiMethod(defaultModel, "UpdateEndpointsFromTags"));
        }

        public HttpWebResponse UpdateEndpointsToTags()
        {
            RequestHandler requestor = new RequestHandler(BaseUrl + "UpdateEndpointsToTags", HttpVerb.POST, AuthenticationType.Bearer);
            return requestor.SendRequest(helper.SerializeForApiMethod(defaultModel, "UpdateEndpointsToTags"));
        }

        public HttpWebResponse UpdateTagToRoot()
        {
            RequestHandler requestor = new RequestHandler(BaseUrl + "UpdateTagToRoot", HttpVerb.POST, AuthenticationType.Bearer);
            return requestor.SendRequest(helper.SerializeForApiMethod(defaultModel, "UpdateTagToRoot"));
        }


Что я уже пробовал:

После отладки кода я вижу, что он выбрасывает исключение stackoverflow, когда я создал экземпляр класса Tagmodel. Когда я сказал:
public TagModel defaultModel = new TagModel

PIEBALDconsult

Выясните, какое выражение вызывает ошибку. Я подозреваю вот это:
Форматирование = Форматирование.Изрезанный

ZurdoDev

Вы правы, stackoverflow часто происходит от бесконечной рекурсии. Все, что вам нужно сделать, это отладить код, мы не можем сделать это за вас, и вы найдете, где проблема.

Member 14779968

Привет ZurdoDev мое исключение stackoverflow выбрасывается, когда я создал экземпляр класса TagModel. Он выдает ошибку в экземпляре defaultmodel. Но как я могу решить эту проблему, так как мне нужно установить значения

ZurdoDev

Пройдите через свой код и узнайте, почему у вас есть бесконечная рекурсия.

Member 14779968

Это не позволит мне перешагнуть через экземпляры TagModel

ZurdoDev

Я не совсем понимаю, что это значит, но вы не хотите переступать через код, вы хотите войти в код, чтобы попытаться понять, что происходит.

1 Ответов

Рейтинг:
2

Mahesh Pratap Singh

Нужно изучить паттерн Singleton : шаблон Singleton
[^]

Поймите это и измените его, чтобы вернуть два объекта в соответствии с вашими требованиями.

Для вашего кода

defaultModel
и
modelForUpdate 
должно быть статично. Вам также необходимо включить частный конструктор.

Надеюсь, это поможет.