2016-04-13 6 views
1

Warum wird der Wert auf das Element ‚c‘ Objekts immer ‚undefined‘ in der JavaScript-Funktion UpdateFields()?

Wenn ich Falle der json Rückkehr in den Controller listCities die Werte hat würde ich erwarten. listCities wird bei der Rückgabe korrekt ausgefüllt.

CityModel.cs

namespace AutoCompleteInMVCJson.Models 
{ 
    public class CityModel 
    { 
     public int Id { get; set; } 
     public string City { get; set; } 
     public string State { get; set; } 
     public string Zip { get; set; } 
    } 
} 

HomeController.cs

namespace AutoCompleteInMVCJson.Controllers 
{ 
    public class HomeController : Controller 
    { 

     [HttpGet] 
     public ActionResult Index() 
     { 
      return View(); 
     } 

     [HttpPost] 
     public JsonResult Index(string s) 
     { 

      List<CityModel> cities = new List<CityModel>() 
      { 
       new CityModel {Id=1, City="Cincinnati", State="Ohio", Zip="c-oh" }, 
       new CityModel {Id=2, City="Miami", State="Florida", Zip="33114" }, 
       new CityModel {Id=3, City="Miami", State="Florida", Zip="33125" }, 
       new CityModel {Id=4, City="Atlanta", State="Georgia", Zip="a-ga" }, 
       new CityModel {Id=5, City="Chicago", State="Illinois", Zip="c-il"}, 
       new CityModel {Id=6, City="Seattle", State="Washington", Zip="s-wa"}, 
       new CityModel {Id=7, City="Culabra", State="Puerto Rico", Zip="c-pr" }, 
       new CityModel {Id=8, City="Key West", State="Flordia", Zip="kw-fl" } 
      }; 

      var listCities = (
        from c in cities 
        where c.City.ToUpper().Contains(s.ToUpper()) 
        select new { c.Id, c.City, c.State, c.Zip } 
       ); 
      return Json(listCities, JsonRequestBehavior.AllowGet); 
     } 
    } 
} 

index.cshtml @model AutoCompleteInMVCJson.Models.CityModel

@{ 
    ViewBag.Title = ""; 
} 
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css"> 
<script src="//code.jquery.com/jquery-1.10.2.js"></script> 
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script> 
<script type="text/javascript"> 
    $(document).ready(function() { 
     $("#City").autocomplete({ 
      source: function (request, response) { 
       $.ajax({ 
        url: "/Home/Index", 
        type: "POST", 
        dataType: "json", 
        data: { s: request.term }, 
        success: function (lst) { 
         response($.map(lst, function (c) { 
          return { label: c.Id + "//" + c.City + "//" + c.State + "//" + c.Zip, value: c.City }; 
         })) 
        } 
       }) 
      }, 
      messages: { noResults: "", results: function() { return (""); } } 
     }); 
    }) 
</script> 



@using (Html.BeginForm()) 
{ 
    @Html.AntiForgeryToken() 
    <div class="form-horizontal"> 
     <hr /> 
     <div class="form-group"> 
      <div class="col-md-12"> 
       @Html.TextBoxFor(m => m.Id, new { @class = "hidden" }) 
      </div> 
     </div> 
     <div class="form-group"> 
      <div class="col-md-12"> 
       @Html.TextBoxFor(m => m.City, new { @class = "form-control" }) 
      </div> 
     </div> 
     <div class="form-group"> 
      <div class="col-md-12"> 
       @Html.TextBox("State") 
      </div> 
     </div> 
     <div class="form-group"> 
      <div class="col-md-12"> 
       @Html.TextBox("Zip") 
      </div> 
     </div> 
    </div> 
} 


<script type="text/javascript"> 
    var x = document.getElementById('City'); 

    x.addEventListener("blur", UpDateFields, true); 

    function UpDateFields() { 
     $.ajax({ 
      url: "/Home/Index" 
      , type: 'post' 
      , data: { s: $('#City').val() } 
      , success: function (c) { 
       $('#Id').val(c.Id); 
       $('#State').val(c.State); 
       $('#Zip').val(c.Zip); 
       alert("//" + c.Id.val() + "//" + c.City + "//" + c.State + "//" + c.Zip + "//") 
      } 
     }); 
    } 
</script> 

Wenn Sie bekommen, was ich bin versuchen, hier zu tun und haben auf einen besseren Weg, um es ihnen zu tun, ich habe alle Ohren.

Danke.

Antwort

3

Ihre Linq-Abfrage wird immer eine Liste zurück, auch wenn es nur ein Element abgestimmt.

Sie machen zwei Ajax-Aufrufe zu/Home/Index. Im ersten Fall behandeln Sie zu Recht der zurück json Liste:

success: function (lst) { 
         response($.map(lst, function (c) { 
          return { label: c.Id + "//" + c.City + "//" + c.State + "//" + c.Zip, value: c.City }; 
         })) 
        } 

Im zweiten Fall, dass Sie ein einzelnes Objekt json erwarten, das nicht das, was zurückkommt ist.

success: function (c) { 
       $('#Id').val(c.Id); 
       $('#State').val(c.State); 
       $('#Zip').val(c.Zip); 
       alert("//" + c.Id.val() + "//" + c.City + "//" + c.State + "//" + c.Zip + "//") 
      } 

Sie müssen die Liste auch im zweiten Fall behandeln.

Auf einer seitlichen Anmerkung: Warum Sie eine POST werden mit einem nur Lesevorgang zu behandeln?

+0

Danke für die Antwort. Ist es nicht wahr, dass ich ein einzelnes Objekt bekomme, wenn nur ein Datensatz zurückgegeben werden muss? Wo ich mehr als einen Miamis habe, wie benenne ich 33114 anders als 33125 im Anruf zum zweiten Aufruf an Index() ist meine nächste Herausforderung. Post/Get/was auch immer. Ich werde es weiter verbessern, sobald es funktioniert, also nehme ich Änderungen von einem Beitrag, wenn ich kann. Aber wie definiere ich den Aufruf des Index() zwischen JsonResult & ActionResult nicht von Get & Post? – Steve

+0

Ja. Du hast recht. Ich werde das JsonResult() ausbrechen müssen. Das Ändern des return() zu dieser Zeile hat den Punkt bewiesen. return Json (listCities.First(), JsonRequestBehavior.AllowGet); Haben Sie einen Vorschlag, wie Sie im zweiten Anruf die Postleitzahl 33114 -v- 33125 festlegen? Gibt es einen insgesamt besseren Weg, dies zu tun? – Steve

+0

Posten Sie eine andere Frage und ich werde es mir ansehen. –