Search code examples
c#ajaxwcfserializationcircular-reference

A circular reference was detected while serializing an object of type \u0027ASP.global_asax


I apologize if this has been asked already. I'm fairly new to asp.net stuff, and I did search around, but I couldn't find solution I am able to apply to my situation - or able to apply in a way I know how.

Anyway, here's the issue.

I am building a project for school. A lot of the setup and code has been given to us. We started off by building asp.net web form projects in the following format.

Models ViewModels Website

Models was a class library with the ADO.Net data object. View models consisted of classes that talked to the Model classes, and Website talked to ViewModels. Fairly straight forward.

Within Models we are serializing everything - including an entity. Here's the code for serialization

    public static byte[] Serializer(Object inObject, bool bIsEntity = false)
    {
        byte[] ByteArrayObject;

        if (bIsEntity == true)
        {
            MemoryStream strm = new MemoryStream();
            var serializer = new DataContractSerializer(inObject.GetType());
            serializer.WriteObject(strm, inObject);
            ByteArrayObject = strm.ToArray();
        }
        else
        {
            BinaryFormatter binFormatter = new BinaryFormatter();
            MemoryStream memStream = new MemoryStream();
            binFormatter.Serialize(memStream, inObject);
            ByteArrayObject = memStream.ToArray();
        }
        return ByteArrayObject;
    }

That code basically just serializes a dictionary, and the entity - the entity gets serialized separately, then the entire thing.

We basically then just call some get methods and get the data object. That's all working.

We also use some jquery ajax method calls to retrieve information for a modal. So, in the aspx.cs file in the Website, we have this..

    [System.Web.Services.WebMethod]
    [System.Web.Script.Services.ScriptMethod(ResponseFormat = System.Web.Script.Services.ResponseFormat.Json)]
    public static EmployeeViewModel GetEmployee(int empID)
    {
        EmployeeViewModel emp = new EmployeeViewModel();
        emp.GetByID(empID);
        return emp;
    }

That works fine in that format. There's an ajax call to that function and everything works perfectly. The employee in question comes up.

After this we essentially took this code and created a new solution. Within that solution we now have three other projects (4, but we're just using 3 right now--We have a server project that we're going to use soon). They are as follows:

WCF Services ViewModels Website

Everything works fine up until the ajax call. I know the GetByID method works, as I am calling it from a separate driver in the websites project and printing out the results. I keep getting serialization errors in javascript when the ajax function is called. We actually have three different sections for this solution - there are calls, employees, and problems. The problems portion works fine. It only has a few database items. The Employees and Calls both work in the solution mentioned above, but they don't work when I am including WCF.

The error I am getting is below. First I'm going to give you some other methods that might be important.

this is in the ModelServices (WCF Services) project

    public byte[] GetByID(int empID)
    {
        Dictionary<string, Object> retDict = new Dictionary<string, Object>();
        try
        {
            HelpdeskDBEntities dbContext = new HelpdeskDBEntities();
            dbContext.Configuration.ProxyCreationEnabled = false;
            Employee EmployeeEntity = dbContext.Employees.FirstOrDefault(emp => emp.EmployeeID == empID);
            if (EmployeeEntity != null)
            {
                retDict["firstname"] = EmployeeEntity.FirstName;
                retDict["lastname"] = EmployeeEntity.LastName;
                retDict["phoneno"] = EmployeeEntity.PhoneNo;
                retDict["email"] = EmployeeEntity.Email;
                retDict["departmentid"] = EmployeeEntity.DepartmentID;
                retDict["employeeid"] = EmployeeEntity.EmployeeID;
                retDict["title"] = EmployeeEntity.Title;
                retDict["staffpicture"] = EmployeeEntity.StaffPicture;

                retDict["entity"] = HelpdeskModelUtils.Serializer(EmployeeEntity, true);
            }
            else
            {
                retDict["error"] = "Employee Not Found";
            }
        }
        catch (Exception ex)
        {
            HelpdeskModelUtils.ErrorRoutine(ex, this.GetType().Name, HelpdeskModelUtils.GetCurrentMethod());
            retDict["error"] = ex.Message;
        }
        return HelpdeskModelUtils.Serializer(retDict);
    }

this is the serializer and deserializer methods in the wcf services project

    public static byte[] Serializer(Object inObject, bool bIsEntity = false)
    {
        byte[] ByteArrayObject;

        if (bIsEntity == true)
        {
            MemoryStream strm = new MemoryStream();
            var serializer = new DataContractSerializer(inObject.GetType());
            serializer.WriteObject(strm, inObject);
            ByteArrayObject = strm.ToArray();
        }
        else
        {
            BinaryFormatter binFormatter = new BinaryFormatter();
            MemoryStream memStream = new MemoryStream();
            binFormatter.Serialize(memStream, inObject);
            ByteArrayObject = memStream.ToArray();
        }
        return ByteArrayObject;
    }

    public static Object Deserializer(byte[] ByteArrayIn)
    {
        BinaryFormatter binFormater = new BinaryFormatter();
        MemoryStream memStream = new MemoryStream(ByteArrayIn);
        Object returnObject = binFormater.Deserialize(memStream);
        return returnObject;
    }

this is the ViewModel method

    public void GetByID(int empId)
    {
        try
        {
            EmployeeServiceReference.EmployeeModelServiceClient model = new EmployeeServiceReference.EmployeeModelServiceClient();
            Dictionary<string, Object> dictionaryEmployee =
                (Dictionary<string, Object>)HelpdeskViewModelUtils.Deserializer(model.GetByID(empId));

            if (!dictionaryEmployee.ContainsKey("error"))
            {
                _firstName = (string)dictionaryEmployee["firstname"];
                _lastName = (string)dictionaryEmployee["lastname"];
                _title = (string)dictionaryEmployee["title"];
                _departmentID = (int)dictionaryEmployee["departmentid"];
                _phoneno = (string)dictionaryEmployee["phoneno"];
                _email = (string)dictionaryEmployee["email"];
                _entity = (byte[])dictionaryEmployee["entity"];
                _employeeID = (int)dictionaryEmployee["employeeid"];
            }
            else
            {
                _lastName = "error";
            }
        }
        catch (Exception ex)
        {
            HelpdeskViewModelUtils.ErrorRoutine(ex, this.GetType().Name, HelpdeskViewModelUtils.GetCurrentMethod());
            throw new Exception(ex.Message);
        }
    }

this is the serializer and deserializer in the ViewModels project

    public static byte[] Serializer(Object inObject)
    {
        BinaryFormatter binFormatter = new BinaryFormatter();
        MemoryStream memStream = new MemoryStream();
        binFormatter.Serialize(memStream, inObject);
        byte[] ByteArrayObject = memStream.ToArray();
        return ByteArrayObject;
    }

    public static Object Deserializer(byte[] ByteArrayIn)
    {
        BinaryFormatter binFormater = new BinaryFormatter();
        MemoryStream memStream = new MemoryStream(ByteArrayIn);
        Object returnObject = binFormater.Deserialize(memStream);
        return returnObject;
    }

here's my ajax call and related javascript stuff

function getEmployeeInfoForModal(empID) {
    $.ajax({
        type: "POST",
        url: "Employees.aspx/GetEmployee",
        data: "{empID :" + empID + "}",
        contentType: "application/json; charset-utf-8",
        success: function (data) {
            copyEmployeeInfoToModal(data.d);
        },
        error: function (data) {
            alert('problem getting server data' + data.responseText);
        }
    });
}

function copyEmployeeInfoToModal(emp) {
    .........do stuff - never gets here
}

ERROR I keep getting the following error. It's a long error, so I'm going to keep it on one line.

 problem getting server data{"Message":"A circular reference was detected while serializing an object of type \u0027ASP.global_asax\u0027.","StackTrace":"   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)\r\n   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)\r\n   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)\r\n   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)\r\n   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)\r\n   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)\r\n   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int3...\r\n   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)\r\n   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)\r\n   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)\r\n   at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat, MemberInfo currentMember)\r\n   at System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj, StringBuilder output, SerializationFormat serializationFormat)\r\n   at System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj, SerializationFormat serializationFormat)\r\n   at System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj)\r\n   at System.Web.Script.Services.RestHandler.InvokeMethod(HttpContext context, WebServiceMethodData methodData, IDictionary`2 rawParams)\r\n   at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)","ExceptionType":"System.InvalidOperationException"}

Solution

  • I figured this out! Well, my professor did.

    I have no idea how I missed this, as I compared all files and everything I was referencing.

    The issue was the fact that I was inheriting System.Web.UI.Page in my ViewModels classes that weren't working.

    For example, my ViewModel class for the EmployeeViewModel was....

    public class EmployeeViewModel : System.Web.UI.Page

    I removed the : System.Web.UI.Page and it worked.

    I hope that helps someone somewhere at some point in time.