Passing response from ajax call to view in C#

2019-09-11 09:37发布

问题:

I am using ajax to call an action in the controller. The code is like this

   $('#kitchen').change(function () {
    var selectedKitchen = $('#kitchen').val();
    if (selectedKitchen != '') {
        console.log("selected item:" + $('#kitchen').val());
        $.ajax({
            type: "GET",
            url: "/Home/GiveInsitutionsWithoutResponsibility",
            data: "id=" + selectedKitchen,
            dataType:'json',
            success: function (result) {
                result = JSON.parse(result);
                console.log(result.length);
            },
            error: function (error) {
                console.log("There was an error posting the data to the server: ");
                console.log(error.responseText);
            }
        });
    }

});

Now what I want is to use the result coming from the server to populate a drop down on the client side. How should I do it? Is there a way for it or my approach here is wrong?

My result object is like this

{
Id: "04409314-ea61-4367-8eee-2b5faf87e592"
Name: "Test Institution Two"
NextPatientId: 1
OwnerId: "1"
PartitionKey: "1"
RowKey: "04409314-ea61-4367-8eee-2b5faf87e592"
Timestamp: "/Date(1417180677580)/"
}

The controller function is like this

    public ActionResult GiveInsitutionsWithoutResponsibility()
    {
        var kitchenId = Request["id"].ToString();
        Kitchen k = Kitchen.Get(kitchenId);
        IEnumerable <Institution> ins = k.GetInstitutions();
        IEnumerable<Institution> allIns = Institution.GetAll();
        List<Institution> result = new List<Institution>();
        bool contain = true;
        int index = 0;
        if (ins.Count() > 0)
        {
            for (int i = 0; i < allIns.Count(); i++, contain = true)
            {
                for (int j = 0; j < ins.Count(); j++)
                {
                    if (allIns.ElementAt(i).Id == ins.ElementAt(j).Id)
                    {
                        contain = true;
                        break;
                    }
                    else
                    {
                        index = j;
                        contain = false;
                    }
                }
                if (!contain)
                {
                    result.Add(allIns.ElementAt(index));
                }
            }
        }
        else
        {
            for (int i = 0; i < allIns.Count(); i++)
            {
                result.Add(allIns.ElementAt(index));
            }
        }
        string response = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(result);
        return Json(response, JsonRequestBehavior.AllowGet);

    }

回答1:

First your action method can be simplified to

public ActionResult GiveInsitutionsWithoutResponsibility(int ID)
{
  Kitchen k = Kitchen.Get(ID);
  var data = Institution.GetAll().Except(k.GetInstitutions(), new InstitutionComparer()).Select(i => new
  {
    ID = i.ID,
    Name = r.Name
  });
  return Json(data, JsonRequestBehavior.AllowGet);
}

Note the Kitchen.ID is passed in the method parameter. The Linq query is used to select all Institution's then exclude any Institution's that already exist in the Kitchen, then creates a collections of anonymous object so unnecessary data is not sent to the client. The Json() method returns the data in the correct JSON format (calling JavaScriptSerializer().Serialize() is not required).

In order for .Except() to work with complex objects, you need a comparer

public class InstitutionComparer : IEqualityComparer<Institution>
{
  public bool Equals(Institution x, Institution y)
  {
    if (Object.ReferenceEquals(x, y)) 
    {
      return true;
    }
    if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
    {
        return false;
    }
    return x.ID == y.ID;
  }
  public int GetHashCode(Institution institution)
  {
    if (Object.ReferenceEquals(institution, null))
    {
      return 0; 
    }
    return institution.ID.GetHashCode();
  }
}

Next change the ajax method to

$('#kitchen').change(function () {     
  var selectedKitchen = $('#kitchen').val();
  if (!selectedKitchen) {
    return;
  }
  $.ajax({
    type: "GET",
    url: '@Url.Action("GiveInsitutionsWithoutResponsibility", "Home")', // don't hard code urls
    data: { id: selectedKitchen }, // pass selectedKitchen to the id parameter
    dataType:'json',
    success: function (result) {
      var select = $('YourDropDownSelector').empty().append($('<option></option>').val('').text('--Please select--'));
      $.each(result, function(index, item) {
        select.append($('<option></option>').val(item.ID).text(item.Name));
      });
    },
    error: function (error) {
    }
  });
});

or you could use the short cut

$.getJSON('@Url.Action("GiveInsitutionsWithoutResponsibility", "Home")', { id: selectedKitchen }, function(result) {
  $.each(result, .... // as above
});


回答2:

Depending on the object from your controller, you could loop through your results data and .append this to your drop down list.

success: function (result) {

   $.each(result, function(index, manager) {
       $('select#yourId').append(
               '<option value="' + result.Id + '">'
                    + result.Name + 
       '</option>');
   });

}


回答3:

Your approach is fine, you will have to format the result to be added to combo box. For example, support on a page I have country and states combo box. Based on selected country, I need to populate state, so I will write following code:

    $("#billingContactCountry").change(function (e) {
        e.preventDefault();

        var countryId = $("#billingContactCountry").val();

        getStatesByCountry(countryId, "", "#billingContactState", "#billingContactZip");
    });

    function getStatesByCountry(countryId, stateId, stateCombobox, zipTextBox) {

    $.ajax({
        url: "@Url.Action("GetStatesByCountry", "Admin")",
        data: { countryId: countryId },
        dataType: "json",
        type: "GET",
        error: function (xhr, status) {
            //debugger;
            var items = "<option value=\"\">-Select State-</option>";
            $(stateCombobox).html(items);

            var zipMessage = validateZip(countryId, $(zipTextBox).val());
            if (zipMessage != "The ZIP Code field is required.") {
                $(zipTextBox).parent().find("span.field-validation-error").text(zipMessage);
            }

            $("div.overlay").hide();
        },
        success: function (data) {
            //debugger;
            var items = "<option value=\"\">-Select State-</option>";
            $.each(data, function (i, item) {
                items += "<option value=\"" + item.Id + "\">" + item.Name + "</option>";
            });

            $(stateCombobox).html(items);

            if (stateId != "") {
                $('#billingContactState').val(stateId);
            }

            var zipMessage = validateZip(countryId, $(zipTextBox).val());
            if (zipMessage != "The ZIP Code field is required.") {
                $(zipTextBox).parent().find("span.field-validation-error").text(zipMessage);
            }

            $("div.overlay").hide();
        }
    });
}

So basically interesting code is,

            var items = "<option value=\"\">-Select State-</option>";
            $.each(data, function (i, item) {
                items += "<option value=\"" + item.Id + "\">" + item.Name + "</option>";
            });

            $(stateCombobox).html(items);

We are operating on each element returned from server to create option item for combo box.

As an aside, you should use @Url.Action as shown in example above.