Return ListT by Json to JS from c # with class that contains another class

1

I have a class Localidad that contains an attribute of the class Provincia , wanting to make the combos nested by Ajax with Jquery gives me a:

  

error 500 - Internal server error -.

If I take out the Provincia attribute, it's perfect. How can I solve this?

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

    namespace javaScript.Models
    {
        public class Localidad
        {
            public int Id { get; set; }
            public string Descripcion { get; set; }

            [Display(Name ="Provincia")]
            public int IdProvincia { get; set; }

            public Provincia Provincia
            {
                get { return new Provincia(this.IdProvincia); }
                set { }
            }

            public void set_Provincia(int idProvincia)
            {
                this.Provincia = new Provincia(1);
            }
        }
    }

namespace javaScript.Models
{
    public class Provincia
    {
        // public int Id { get; set; }
        public int Id { get; set; }
        public string Descripcion { get; set; }
        public string Gobernador { get; set; }
        public List<Localidad> Localidades { get; set; }
    }
}

Method in the Controller to return the list:

public ActionResult GetSecondValues(string IdProvincia)
{
    IEnumerable<Localidad> localidadList = null;
    var db = new Contexto();

   var id = Int32.Parse(IdProvincia);
    if (id > 0)
    {
        //se carga la lista de Localidades       
        localidadList = db.Localidades.Where(x => x.IdProvincia == id).ToList();
    }
    var retorno = Json(localidadList);
    return retorno;
}

Ajax method in the view:

 <script type = "text/javascript">
    $(function () {
        $("#IdProvincia").change(function () {
            var selectedItem = $(this).val();
            var ddlStates = $("#IdLocalidad");
            var statesProgress = $("#states-loading-progress");
            statesProgress.show();
            $.ajax({
                cache: false,
                type: "POST",
                url: "@(Url.Action(" GetSecondValues "))",
                data: {
                    "IdProvincia": selectedItem
                },
                success: function (data) {
                    ddlStates.html('');
                    $.each(data, function (id, option) {
                        ddlStates.append($('<option></option>').val(option.Id).html(option.Descripcion));
                    });
                    statesProgress.hide();
                },
                error: function (xhr, ajaxOptions, thrownError) {
                    alert('Failed to retrieve states.');
                    statesProgress.hide();
                }
            });
        });
    });
</script>
    
asked by Ariel Octavio D'Alfeo 11.09.2017 в 23:30
source

3 answers

1

The problem arises because of a Recursivity between the class Provinces that contains a List of Locations and the class Locations that contains an attribute of the type Province The strange thing that the error jumps in the ajax method and not in Visual Studio, which made it difficult for me to find the error, because ajax just said Error 500 Internal server error and I do not have much experience in JS. Removing any of the two attributes (the list of localities in province, or the province in localities) The code works correctly.

 public class Localidad
        {
            public int Id { get; set; }
            public string Descripcion { get; set; }

            [Display(Name ="Provincia")]
            public int IdProvincia { get; set; }

            **public Provincia Provincia
            {
                get { return new Provincia(this.IdProvincia); }
                set { }
            }**

            public void set_Provincia(int idProvincia)
            {
                this.Provincia = new Provincia(1);
            }
        }

  public class Provincia
    {
        // public int Id { get; set; }
        public int Id { get; set; }
        public string Descripcion { get; set; }
        public string Gobernador { get; set; }
        **public List<Localidad> Localidades { get; set; }**
    }
    
answered by 14.09.2017 / 17:00
source
0

As I understand it, the error you're getting would be Can not implicitly convert type X to 'System.Collections.Generic.IEnumerable < Location > '.

This would be because the type that returns db.Localities can not be converted directly to a list of Locality .

You could try the following:

localidadList = db.Localidades.Where(x => x.IdProvincia == id).Select(
    l => new Localidad
    {
        Id = l.Id,
        Descripcion = l.Descripcion,
        IdProvincia = l.IdProvincia
    }).ToList();
    
answered by 11.09.2017 в 23:54
0

One problem I see is that you're using Int32.Parse to convert the string IdProvincia , but if it becomes null it will send you a ArgumentNullException , this generates an exception and therefore error 500 makes sense, so the ideal would be to use the method Convert.ToInt32 .

Ideally, it will be to change your Controller code for the following:

public ActionResult GetSecondValues(int IdProvincia)
{
    IEnumerable<Localidad> localidadList = db.Localidades.Where(x => x.IdProvincia == IdProvincia).ToList();
    return Json(localidadList, JsonRequestBehavior.AllowGet);
}

But, seeing the result you use to fill a drop-down list, I would recommend generating the HTML from the Controller:

public ActionResult GetSecondValues(int IdProvincia)
{
    IEnumerable<Localidad> localidadList = db.Localidades.Where(x => x.IdProvincia == IdProvincia).ToList();

    StringBuilder sb = new StringBuilder();
    foreach (var localidad in localidadList)
    {
        sb.Append("<option value='" + localidad.Id + "'>" + localidad.Descripcion + "</option>");
    }

    ViewBag.Localidades = sb.ToString();

    return View();
}

Finally, in the Ajax call, only renderear that HTML in the desired control would be missing:

$.ajax({
    cache: false,
    type: "POST",
    url: "@(Url.Action(" GetSecondValues "))",
    data: {
        "IdProvincia": selectedItem
    },
    success: function (data) {
        ddlStates.html('');
        ddlStates.append(@Html.Raw(ViewBag.Localidades));
        statesProgress.hide();
    },
    error: function (xhr, ajaxOptions, thrownError) {
        alert('Failed to retrieve states.');
        statesProgress.hide();
    }
});
    
answered by 13.09.2017 в 19:12