2013-03-08 15 views
10

Ich habe eine Liste von Benutzern, die ich von meinem Controller zu meiner Ansicht mit der Ansichtstasche übergeben. Jetzt muss ich in der Lage sein, die gleiche Liste an das Javascript auf der Seite zu übergeben. Ich könnte die Liste mit einer foreach-Schleife rekonstruieren:Übergabe der Liste von MVC ViewBag an JavaScript

@foreach (var item in ViewBag.userList) //Gets list of users passed from controller and adds markers to the map 
{ 
    var userLat = item.LastLatitude; 
    var userLon = item.LastLongitude; 
    var _userId = item.Id; 

    <script>array.push({"userId":"'@_userId'","userLat":"'@userLat'","userLon":"'@userLon'"});</script> 
} 

Allerdings scheint dies wie ein chaotischer Ansatz und eine Menge Nacharbeit erforderlich, wenn eine Änderung vorgenommen wird. Ich weiß, es gibt ähnliche Beiträge auf Stack-Überlauf, aber viele von ihnen verwenden vorherige Version von MVC und die gleiche Syntax scheint nicht zu gelten. Irgendwelche Ideen?

Antwort

20

Sie könnten dies in einer einzigen und sicheren Codezeile mit einem JSON-Parser tun. Sie sollten JSON niemals manuell mit einigen String-Verkettungen und anderen Dingen erstellen, wie Sie es in Ihrem Beispiel versucht haben. Keine Notwendigkeit, irgendwelche Schleifen auch zu schreiben.

Hier ist der richtige Weg, das zu tun:

<script type="text/javascript"> 
    var array = @Html.Raw(
     Json.Encode(
      ((IEnumerable<UserModel>)ViewBag.userList).Select(user => new 
      { 
       userId = user.Id, 
       userLat = user.LastLatitude, 
       userLon = user.LastLongitude 
      }) 
     ) 
    ); 

    alert(array[0].userId); 
</script> 

Der erzeugte HTML aussehen wird genau wie Sie es erwarten:

<script type="text/javascript"> 
    var array = [{"userId":1,"userLat":10,"userLon":15}, {"userId":2,"userLat":20,"userLon":30}, ...]; 
    alert(array[0].userId); 
</script> 

Natürlich ist die nächste Stufe der Verbesserung in diesem Code ist loswerden von ViewCrap und verwenden Sie ein stark typisiertes Ansichtsmodell.

+0

Danke für die schnelle und detaillierte Antwort! Aber ich erhalte den folgenden Fehler 'Kann einen Lambda-Ausdruck nicht als Argument für eine dynamisch versendete Operation verwenden ...' ohne den IEnumerable-Teil. Mit diesem hinzugefügten Teil bekomme ich auch einen Fehler 'Die Argumenttypen für die Methode ... können nicht aus der Verwendung abgeleitet werden'. Danke für die Hilfe, und es tut mir leid, wenn das ein Anfängerfehler ist. p.s. Ich verwende das Ansichtsmodell für etwas anderes auf dieser Seite, deshalb verwende ich die Ansichtstasche. – Matt

+0

Aber ein View-Modell ist eine Klasse, die Sie speziell für die Anforderungen Ihrer Sicht entwerfen. In diesem Fall muss Ihre Ansicht dieses dynamische Javascript generieren. Ihr View-Modell sollte also eine Collection-Eigenschaft vom Typ 'IEnumerable 'enthalten. Und dann ersetzen Sie einfach die gesamte Besetzung durch 'Model.Users.Select (...)'.Wenn Sie den schwach getippten ViewBag verlassen, müssen Sie ihn in den richtigen 'IEnumerable ' Typ umwandeln. –

+0

Ok Ich habe die Seite schnell geändert und das View-Modell verwendet und es hat funktioniert. Ich musste auch auf eine andere Ihrer Antworten verweisen http://stackoverflow.com/questions/12111729/razor-javascript-and-trailing-semicolon, wusste nicht über diesen Fehler in VS2012. Danke für die tolle und informative Antwort! – Matt

2

Eine andere Option könnte sein, eine neue Aktion in Ihrem Controller zu erstellen, die ein JsonResult zurückgibt. Dieses JSON-Ergebnis könnte Ihre Liste zurückgeben. Auf Ihrer Seite können Sie die Aktion mit jquery aufrufen und von dort aus verwenden.

public ActionResult GetMyList() 
{ 
    var list = GetMyUserList(); 

    return Json(new { userlist = list }, JsonRequestBehaviour.AllowGet); 
} 
+0

Danke für den Tipp, ich werde das auch ausprobieren :) – Matt

1

@Darin Dimitrov Antwort ist vor Ort. Ich möchte nur hinzufügen, wenn jemand ein Modell und nicht eine Sichttasche passiert.

<script type="text/javascript"> 
var array = @Html.Raw(Json.Encode(
      Model.YourModel.Select(_ => new { 
       id = _.Id, 
       text = _.Name 
      }) 
     )) 

Mein Anwendungsfall spezifisch für select2. Man kann dann passieren nur das Array zu den Daten: Attribut

$("#storeSelect").select2({ 
     data: array, 
     placeholder: "Select something" 
}); 
</script> 

Viewmodel

public class YourViewModel 
    { 
    public IEnumarable<YourPoco> YourPocos { get; set; } 
    } 

-Controller

public class YourController : Controller 
{ 
    public ActionResult Index() 
    { 
     YourViewModel vm = new YourViewModel{ 
      // Using Dependancy injection 
      YourPocos = yourRepo.GetYourPocos(); 
     }; 
     return View("Index", "_Layout",vm); 
    } 
} 

Ich weiß, diese Antwort überflüssig sein könnte, aber es ist Beim ersten Mal verwende ich Json.Encode und übergebe Modellwerte an eine jQuery-Erweiterung. Das ist für mich zu cool. Es macht bis zu einem gewissen Grad massive Erweiterbarkeit auf was wäre sonst ein @htmlhelper