简体   繁体   中英

Parse key/value pair from JSON dictionary result in MVC

I've scoured through the posts here and haven't found a solution that works...

I am using JQuery autocomplete for a dropdown list of employees. I am able to load the list with values but it contains the keys from the dictionary that I am passing and not the values. I want to show both.

Controller code:

public JsonResult GetEmp(string id)
    {
        if (id.Length > 3)
        {
            var result = Json(repository.SearchForEmployee(id), JsonRequestBehavior.AllowGet);
            return result;
        }

        return null;
    }

Jquery code:

    $('.empId').keyup(function () {
    var x = $('.empId').val();
    var arrayValues = [];
    $.ajax({
        url: '../../Employee/GetEmployee',
        type: "Get",
        data: { id : x },
        cache: false,
        datatype: 'json',
        traditional: true,
        success: function (result) {
            $.each(result, function (item) {
                arrayValues.push(item);
            })
            $(".empId").autocomplete({
            source: arrayValues
        });
        },

        error: function (err) {
            alert('Foo')
        }
    });
});

JSON result variable in Controller action when debugging:

[0]  {[12345, Sharon Moore]}
[1]  {[12346, Amy Adams]}
[2]  {[12349, Adam Smith]}

Actual contents of JScript array for automplete:

12345, 24563, 84565

Can anyone explain why it is only bringing in the first value(key)? Both key and value are strings. Thanks again in advance...

Since you are returning an object and not an array you could try something like this:

var array_of_objects = [];
for (var key in result) {
   var val = result[key];
    //Now you have your key and value which you 
    //can add to a collection that your plugin uses
   var obj = {};
   obj.label = key;
   obj.value = val;
   array_of_objects.push(obj);
}

$(".empId").autocomplete({
     source: array_of_objects
});

Alternatively, you could just return an ArrayList in your C# code (which will be an array of objects/records). Here is some sample code from one of my projects:

        [HttpPost]
        public ActionResult GetProject(int id) {
            string connStr = ConfigurationManager.ConnectionStrings["Conn"].ConnectionString;
            SqlConnection conn = new SqlConnection(connStr);

            string sql = "SELECT * FROM [Portfolio] WHERE [id] = @id";
            SqlDataAdapter da = new SqlDataAdapter(sql, conn);
            da.SelectCommand.Parameters.Add(new SqlParameter("@id", id));
            DataTable dt = new DataTable();

            conn.Open();
            da.Fill(dt);
            da.Dispose();
            conn.Close();

            return Json(objConv.DataTableToArrayList(dt), JsonRequestBehavior.AllowGet);
        }

objConv is a helper utility I use. Here is the code for the DataTableToArrayList method I am using in the above code sample:

public ArrayList DataTableToArrayList(DataTable dataTbl) {

            ArrayList arrList = new ArrayList();

            foreach (DataRow dRow in dataTbl.Rows) {
                Hashtable recordHolder = new Hashtable();
                foreach (DataColumn column in dataTbl.Columns) {
                    if (dRow[column] != System.DBNull.Value) {
                        recordHolder.Add(column.ToString(), dRow[column].ToString());
                    } else {
                        recordHolder.Add(column.ToString(), "");
                    }
                }
                arrList.Add(recordHolder);
            }

            return arrList;
        }

JQuery UI Autocomplete expects a specific data structure to work.

SearchForEmployee must return a list of data in this format:

public class EmployeeAutocomplete
{
   public string @label { get; set; }
   public string @value { get; set; }
}

Or you need to convert in the javascript to that format instead of a list of arrays:

success: function (result) {
        $.each(result, function (item) {
            arrayValues.push(new { label: item[1], value: item[0] });
        });
        $(".empId").autocomplete({
            source: arrayValues
        });
    },

Autocomplete reference: http://api.jqueryui.com/autocomplete/

jQuery UI Autocomplete can make the ajax call itself, so I don't really see why you are making the ajax call separately.

$("#txtbox").autocomplete({
    source: url
});

Regardless of that though, the json from your controller should be returned in the format of [ { label: "Choice1", value: "value1" }, ... ] if you want to send value and labels back.

http://api.jqueryui.com/autocomplete/#option-source

Here's a piece of code that i am using in a couple of places. I am not using the autocomplete feature that you are using but i dont think that is a problem.

Client Side:

    $.getJSON('../../Employee/GetEmployee', { id: x }, function (results) {
        var yourDropdown = $('#YourDropdown');
        var json = JSON.parse(results);
        $.each(json, function (index, item) {
            yourDropdown.append($('<option/>', {
                value: item.Value,
                text: item.Text
            }));
        });

        //Implement the autocomplete feature.
    });

Server Side:

    [HttpGet]
    public JsonResult GetElements(int id)
    {
        IEnumerable<SelectListItem> elements;

        //Some routine that gets the elements goes here.

        var serializer = new JavaScriptSerializer();
        return Json(serializer.Serialize(elements), JsonRequestBehavior.AllowGet);
    }

I have not tested the code in your particular scenario but it should work since I am using the code snippet in multiple places.

Note: Try using the getJson method instead of $.ajax . It is a shortcut to the ajax implementation you are using. As you can see, the code is less verbose and more readable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM