Click here to Skip to main content
15,886,729 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hello I am doing functional API testing. This error occurred when I am trying to serialize my json payload. When I try to run my test I get the following error
"The active test run was aborted. Reason: Test host process crashed : Process is terminated due to StackOverflowException"
My helper method worked fine but I believe it has a infinite recursion somewhere. Here is the break down of the different classes I have.
I have one helper class and using custom ContractResolver I am picking the methods name and the attributes I want to apply to and then using my custom serialize method. Please any helper from any c# expert who be highly appreciated!

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);
        }
    }



Here is my Model class called TagModel where I am using the get and set and assigning the values

C#
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; }




    }


}


Lastly I have another class is where my fuction method called "Tags" is where I came calling the SerializeForApiMethod and passing the model class instance and the method name. This class is also inherting TagModel class

C#
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"));
        }


What I have tried:

After debugging the code, I see it throws the stackoverflow exception when I created the instance of Tagmodel class. When I said
public TagModel defaultModel = new TagModel
Posted
Updated 23-Mar-20 20:21pm
v3
Comments
PIEBALDconsult 22-Mar-20 22:13pm    
Find out which expression is causing the error. I suspect this one:
Formatting = Formatting.Indented
ZurdoDev 23-Mar-20 7:46am    
You're right, stackoverflow often comes from infinte recursion. All you have to do is debug the code, we can't do that for you, and you'll find where the issue is.
Member 14779968 23-Mar-20 21:44pm    
Hi ZurdoDev my exception stackoverflow is thrown when I created the instance of the class TagModel. Its throws the error in defaultmodel instance. But how can I solve this since I need to set the values
ZurdoDev 23-Mar-20 21:47pm    
Step through your code and find out why you have infinite recursion.
Member 14779968 23-Mar-20 22:10pm    
It will not let me step over the TagModel instances

1 solution

You need to study singleton pattern : Singleton pattern
[^]

Understand this and modify it to return two objects as per your requirement.

For your code
defaultModel
and
modelForUpdate 
should be static. You also need to include a private constructor.

Hope this helps.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900