ASP.NET MVC $.post call returning string...need help with format for jqGrid

16,444

Solution 1

If you try to solve the problem for jqGrid only you can choose another way.

You can use dataUrl and buildSelect properties of editoptions or searchoptions instead of value property. This features are introduced specially for the usage in AJAX. The dataUrl defines url provided results in the form like

<select><option value="1">One</option> <option value="2">Two</option></select>

If for you is easer to return JSON results from the server your custom function buildSelect will help. As the parameter it receive the data send from the server and it should return the string <select><option>...</option></select>. In the way you will achieve better results.

If you do decide to stay at your old way you should at least fix your code to following

foreach (var q in query)
{
     if (sb.Length != 0)
         sb.Append(';');
     sb.Append(q.Destination); // instead of sb.Append("ID");
     sb.Append(':');
     sb.Append(q.Destination);
}

to has "FedEx:FedEx;InTime:InTime;TNT:TNT" instead of "ID:FedEx; ID:InTime; ID:TNT; ".

UPDATED: You asked for a small example. Let us you can for example get all different values of the destinations strings as a List<string> and the name of this Method is GetAllDestinations. Then your action used by dataUrl can look like

public JsonResult GetDestinationList() {
    List<string> allDestinations = GetAllDestinations();
    Json(allDestinations, JsonRequestBehavior.AllowGet);
}

To use this action inside of editoptions or searchoptions of jqGrid you can define about following

{ name: 'destinations', ditable: true, edittype:'select',
  editoptions: { dataUrl:'<%= Url.Action("GetDestinationList","Home") %>',
                 buildSelect: function(data) {
                     var response = jQuery.parseJSON(data.responseText);
                     var s = '<select>';
                     if (response && response.length) {
                         for (var i = 0, l=response.length; i<l ; i++) {
                             var ri = response[i];
                             s += '<option value="'+ri+'">'+ri+'</option>';
                         }
                     }
                     return s + "</select>";
                 }
                }
}

If you don't want have actions which be used per HTTP GET you can use Json(allDestinations); instead of Json(allDestinations, JsonRequestBehavior.AllowGet); in the GetDestinationList action, but add to the list of jqGrid options an additional option

ajaxSelectOptions: { type: "POST" }

UPDATED 2: The answer is already old. In the interim the code of jqGrid where buildSelect will be called was changed. Now the buildSelect will be used inside of success handler of jQuery.ajax (see here) instead of the complete handler before (see the post and the post for example). So in the current version of jqGrid the line

var response = jQuery.parseJSON(data.responseText);

is not needed. The data is typically the parsed JSON data and so the lines

                 buildSelect: function(data) {
                     var response = jQuery.parseJSON(data.responseText);

in the code above can be replaced to

                 buildSelect: function(response) {

Solution 2

This is another alternative

[Controller Method]

  [HttpGet]
    public ActionResult SchoolList()
    {
        //Get Schools
        var qry = SchoolManager.GetAll();

        //Convert to Dictionary
        var ls = qry.ToDictionary(q => q.SchoolId, q => q.Name);

        //Return Partial View
        return PartialView("_Select", ls);
    }

[_Select Partial View]

@model Dictionary<int, string>
<select>
<option value="-1">--select--</option>
@foreach(var val in Model)
{
    <option value="@val.Key.ToString()">@val.Value</option>
}

[Page with jqGrid]

{ name: 'SchoolId', index: 'SchoolId', align: 'left', editable: true, edittype: 'select', editoptions: { dataUrl: '@Url.Action("SchoolList")' }, editrules: { required: true} },

Hope this saves someone hours of Googling!

Solution 3

The quote problem is fixed in this way I believe

$.ajax({ type:"POST",
         url: '<%= Url.Action("GetDestinations", "Logger") %>',
         dataType: "json",
         async: false,
         success: function(data) {
           destinations = data.value;
         }
      });

This should work, data in this case has been converted from json so value will evaluate to a string without the double quotes.

If that does not work then change the return statement to look like this:

return "{ value : """+sb.ToString()+""" }";

Yay Linq (this won't have the trailing ; which I think is your problem.)

  (From q In query.AsEnumerable
   select "ID: "+q.Destination).join(";");

(might have typos I did not test)

Share:
16,444
dolphy
Author by

dolphy

Updated on July 30, 2022

Comments

  • dolphy
    dolphy almost 2 years

    I'm trying to dynamically populate a dropdown for the jqGrid when the user is editing data. I have it pretty much working however, there is one value in the dropdown call "undefined". I suspect this is because of the way I'm sending the data to the grid. I'm using ASP.NET MVC 2 and I'm getting the data for the dropdown using jQuery like so:

    var destinations = $.ajax({ type:"POST",
                            url: '<%= Url.Action("GetDestinations", "Logger") %>',
                            dataType: "json",
                            async: false,
                            success: function(data) {
    
                             } }).responseText;
    

    Now, the jqGrid wants the values for the dropdown formatted like this:

    value: "FE:FedEx; IN:InTime; TN:TNT"
    

    I'm using the StringBuilder to iterate through my collection and provide the proper string that the jqGrid wants:

    foreach (var q in query)
    {
         sb.Append("ID:");
         sb.Append(q.Destination);
         sb.Append("; ");
    }
    

    I return this from my controller like this:

    return this.Json(sb.ToString());
    

    This is all swell and I get all the items I need for the dropdown but there is an extra item (the last one) called "undefined".

    I think the problem is when I debug in FireBug, the result for the jqGrid looks like this:

    value: ""ID: One;ID: Two;ID: Three;ID: Four;ID: Five;""
    

    See how there are two sets of quotes. This is probably because when I say:

    sb.ToString()
    

    It probably generates the quotes and then the jqGrid adds a second set. But I'm not 100% on that.

    What is the best way to deal with this? Any advice would be greatly appreciated.

    SOLUTION:

    I solved this by using return ContentResult(sb.ToString();

    I would like to use the dataUrl method as Oleg mentioned but haven't got that working yet.

  • dolphy
    dolphy over 13 years
    All right, I'm just working out the syntax now. Hopefully post the solution soon. Thanks
  • dolphy
    dolphy over 13 years
    I got the "undefined" out by using sb.Remove(sb.Length -2, 2) but now I have a quote at the end of the last drop down item. I think this is because of the two sets of quotes that I don't know how to get rid of yet.
  • dolphy
    dolphy over 13 years
    Oleg, I'd like to use the dataUrl method as it seems to be the preferred way according to the documentation. I was able to set the dataUrl to correct url because I can see the grid calling it when I hit the edit button. I'm not sure how to setup the buildSelect portion. Can you provide a code snippet?
  • dolphy
    dolphy over 13 years
    I will try this next week. Thank you sir for your help
  • Billy Logan
    Billy Logan about 13 years
    The first example above worked for me. It seemed as though the issue was with the double quotes placed around the value when using responseText. Using the logic above there are no double quotes around the value which resolves the issue with a double quote at the end of my last value in the combo box.
  • Anatoliy
    Anatoliy over 11 years
    I am also interested to see a working snippet for buildSelect. If you have one, please post it here or send by email. Thanks
  • Oleg
    Oleg over 11 years
    @Anatoliy: Sorry, but I am very busy now: I am at the customer in the business trip. So I am posting very little last time.
  • Anatoliy
    Anatoliy over 11 years
    @Oleg: Yes, I understand, the customer has a highest priority, no doubt.