web-dev-qa-db-fra.com

Passer la liste de MVC ViewBag à JavaScript

J'ai une liste d'utilisateurs que je passe de ma manette à ma vue à l'aide du view bag. Maintenant, je dois pouvoir transmettre la même liste au javascript de la page. Je pourrais reconstruire la liste en utilisant une boucle foreach:

    @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>
}

Cependant, cela semble être une approche désordonnée et nécessitait beaucoup de retouches si un changement était apporté. Je sais qu'il y a des publications similaires sur le débordement de pile, mais beaucoup d'entre elles utilisent la version précédente de MVC et la même syntaxe ne semble pas s'appliquer. Des idées?

11
Matt

Vous pouvez le faire dans une seule ligne de code sécurisée à l’aide d’un analyseur JSON. Vous ne devez absolument jamais construire manuellement JSON avec des concaténations de chaînes et des opérations similaires à celles que vous avez tenté de faire dans votre exemple. Pas besoin d'écrire des boucles aussi.

Voici la bonne façon de faire cela:

<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>

Le code HTML généré ressemblera exactement à ce que vous attendez:

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

Bien entendu, le prochain niveau d’amélioration de ce code consiste à supprimer la ViewCrap et à utiliser un modèle de vue fortement typé.

21
Darin Dimitrov

Une autre option pourrait être de créer une nouvelle action dans votre contrôleur renvoyant un JsonResult. Ce résultat JSON pourrait retourner votre liste. Dans votre page, vous pouvez appeler l'action avec jquery et l'utiliser à partir de là.

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

    return Json(new { userlist = list }, JsonRequestBehaviour.AllowGet);
}
2
gdp

@Darin Dimitrov réponse est sur place. Je voudrais juste ajouter si quelqu'un passe un modèle et non un sac de vision.

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

Mon cas d'utilisation était spécifique à select2 . On peut alors simplement passer le tableau aux données: attribut

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

viewmodel

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

Contrôleur

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

Je me rends compte que cette réponse est peut-être redondante, mais c’est la première fois que j’utilise Json.Encode et que je passe les valeurs du modèle à une extension jquery. C'est trop cool pour moi. Cela crée dans une certaine mesure une extensibilité massive sur ce qui serait autrement un @htmlhelper

1
user1752532