Почему я получаю эту ошибку при вызове веб-службы, что при сериализации объекта типа обнаружена циклическая ссылка? - PullRequest
0 голосов
/ 24 сентября 2019

Я использую asmx webservice на странице aspx.Я вызываю его, но он выдает эту ошибку.

При сериализации объекта типа SAPWebServices.clsFunctionalLocation обнаружена циклическая ссылка.

Ранее я использовал веб-службы, ноэтот действительно доставляет мне неприятности.В чем проблема?Почему это так?

событие клика:

protected void btnAdd_Click(object sender, EventArgs e)
    {
        SAPWebServicesSoapClient c = new SAPWebServicesSoapClient("SAPWebServicesSoap");

        List<clsFunctionalLocation> ListFuncLocations = new List<clsFunctionalLocation>();
        SAPWebServices.clsFunctionalLocation objFunLocation = new SAPWebServices.clsFunctionalLocation();

        for(int i=1; i<=Convert.ToInt32(txtBoxRecords.Text); i++)
        {



            objFunLocation.Description = txtDes.Text;
            objFunLocation.EquipmentCategory = txtEqCat.Text;
            objFunLocation.EquipmentNo = txtEqNo.Text + txtBoxRecords.Text;
            objFunLocation.EquipmentType = txtEqNo.Text + txtBoxRecords.Text;
            objFunLocation.FunctionalLocation = txtFL.Text;

            ListFuncLocations.Add(objFunLocation);



        }

        objFunLocation.ListFunctionalLocations = ListFuncLocations.ToArray();

        c.SendFunctionalLocations(objFunLocation);
    }

Веб-метод:

 [WebMethod]
    public clsFunctionalLocsResponse SendFunctionalLocations(clsFunctionalLocation Send_ObjFunctionalLocation) {

        clsFunctionalLocation ObjFunctionalLocations = new clsFunctionalLocation();

        return ObjFunctionalLocations.InsertFunctionalLocationsSAP(Send_ObjFunctionalLocation);
    }

DAL:

namespace SAPServicesCollection 
{
    public class clsFunctionalLocation
    {
        public string Description { get; set; }
        public string FunctionalLocation { get; set; }
        public string EquipmentNo { get; set; }
        public string EquipmentCategory { get; set; }
        public string EquipmentType { get; set; }
        public List<clsFunctionalLocation> ListFunctionalLocations { get; set; }

        public clsFunctionalLocation()
        {


        }

        public clsFunctionalLocsResponse InsertFunctionalLocationsSAP(clsFunctionalLocation Param_ObjFunctionalLocations)
        {

            try
            {
                string query = "InsertFunctionalLocationsSAP";
                string ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["SAPConnection"].ConnectionString;

                clsFunctionalLocsResponse ObjFunctionalLocsResponse = new clsFunctionalLocsResponse();
                ObjFunctionalLocsResponse.StatusRet = "";

                using (SqlConnection cn = new SqlConnection(ConnectionString))

                using (SqlCommand cmd = new SqlCommand(query, cn))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    if (ListFunctionalLocations.Count > 0)
                    {
                        foreach (var traverser in Param_ObjFunctionalLocations.ListFunctionalLocations)
                        {
                            cmd.Parameters.Add("@Description", SqlDbType.VarChar, 1000).Value = traverser.Description;
                            cmd.Parameters.Add("@FunctionalLocation", SqlDbType.VarChar, 20).Value = traverser.FunctionalLocation;
                            cmd.Parameters.Add("@EquipmentNo", SqlDbType.VarChar, 20).Value = traverser.EquipmentNo;
                            cmd.Parameters.Add("@EquipmentCategory", SqlDbType.VarChar, 20).Value = traverser.EquipmentCategory;
                            cmd.Parameters.Add("@EquipmentType", SqlDbType.VarChar, 20).Value = traverser.EquipmentType;
                            cmd.Parameters.Add("@StatusRet", SqlDbType.VarChar, 20).Direction = ParameterDirection.Output;
                            cmd.Parameters.Add("@ErrorRet", SqlDbType.VarChar, 100).Direction = ParameterDirection.Output;

                            cn.Open();

                            cmd.ExecuteNonQuery();

                            ObjFunctionalLocsResponse.StatusRet = Convert.ToString(cmd.Parameters["@StatusRet"].Value);
                            ObjFunctionalLocsResponse.ErrorRet = Convert.ToString(cmd.Parameters["@ErrorRet"].Value);

                            cmd.Parameters.Clear();

                            cn.Close();
                        }
                    }
                    else 
                    {
                        ObjFunctionalLocsResponse.StatusRet = "Failed";
                        ObjFunctionalLocsResponse.ErrorRet = "No data has been provided";
                    }

                 }

                return ObjFunctionalLocsResponse;
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }
    }

    public class clsFunctionalLocsResponse
    {
        public string StatusRet { get; set; }
        public string ErrorRet { get; set; }

        public clsFunctionalLocsResponse()
        {


        }
    }
}

1 Ответ

0 голосов
/ 24 сентября 2019

В вашем классе clsFunctionalLocation у вас есть список того же типа (List<clsFunctionalLocation>), который не сработает при сериализации.В общем, вы можете сказать, что если вы могли бы сделать из него struct, он будет сериализован, в вашем случае это будет не так, потому что вы ссылаетесь на объект из самого себя, который называется «фигурной ссылкой».

во избежание таких ошибок вы должны сериализовать structs, а не классы, так что вы на безопасной стороне.

Вот что я изменил:

  • Поскольку вы не используете рекурсивное вложениев вашем цикле я удалил их.
  • Исправлены нарушения соглашения об именах.
  • Переименован InsertFunctionalLocationsSAP в соответствующее имя AppendFunctionalLocationsSAP.
  • Упрощены параметры для AppendFunctionalLocationsSAP.
  • Заменены явные объявления типов на var, где это уместно.
  • Перемещены FucntionalLocation и FunctionalLocsResponse в структуры из классов.
  • Упрощено с помощью операторов.
  • Удален бесполезный try-catch.

Вот как могут выглядеть ваши Структуры

public struct FunctionalLocation
{
   public string Description {get; set;}
   public string FunctionalLocation {get; set;}
   public string EquipmentNo { get; set; }
   public string EquipmentCategory { get; set; }
   public string EquipmentType { get; set; }
}

public struct FunctionalLocsResponse
{
   public string StatusRet {get; set;}
   public string ErrorRet {get; set;}
}

public class FunctionalLocationCollection
{
   public string Description {get; set;}
   public string FunctionalLocation {get; set;}
   public string EquipmentNo { get; set; }
   public string EquipmentCategory { get; set; }
   public string EquipmentType { get; set; }
   public List<FunctionalLocation> ListFunctionalLocations {get; set;}

   public FunctionalLocsResponse AppendFunctionalLocationsSAP(List<FunctionalLocation> locationCollection)
   {
      var query = "InsertFunctionalLocationsSAP";
      var locsResponse = new clsFunctionalLocsResponse();
      locsResponse.StatusRet = "";       
      string ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["SAPConnection"].ConnectionString;
      using var cn = new SqlConnection(ConnectionString)
      using var cmd = new SqlCommand(query, cn)
      cmd.CommandType = CommandType.StoredProcedure;
      if (ListFunctionalLocations.Count > 0)
      {
         foreach (var item in locationCollection)
         {
            cmd.Parameters.Add("@Description", SqlDbType.VarChar, 1000).Value = item.Description;
            cmd.Parameters.Add("@FunctionalLocation", SqlDbType.VarChar, 20).Value = item.FunctionalLocation;
            cmd.Parameters.Add("@EquipmentNo", SqlDbType.VarChar, 20).Value = item.EquipmentNo;
            cmd.Parameters.Add("@EquipmentCategory", SqlDbType.VarChar, 20).Value = item.EquipmentCategory;
            cmd.Parameters.Add("@EquipmentType", SqlDbType.VarChar, 20).Value = item.EquipmentType;
            cmd.Parameters.Add("@StatusRet", SqlDbType.VarChar, 20).Direction = ParameterDirection.Output;
            cmd.Parameters.Add("@ErrorRet", SqlDbType.VarChar, 100).Direction = ParameterDirection.Output;
            cn.Open();
            cmd.ExecuteNonQuery();
            locsResponse.StatusRet = Convert.ToString(cmd.Parameters["@StatusRet"].Value);
            locsResponse.ErrorRet = Convert.ToString(cmd.Parameters["@ErrorRet"].Value);
            cmd.Parameters.Clear();
            cn.Close();
         }
      }
      else 
      {
         locsResponse.StatusRet = "Failed";
         locsResponse.ErrorRet = "No data has been provided";
      }      
      return locsResponse;
   }
}

Если вам все еще нужно рекурсивное вложение, я советую Child and Collection of FunctionalLocation, оба класса.

...