Передача списка из MVC ViewBag в JavaScript

У меня есть список пользователей, которые я передаю от своего контроллера к моему представлению, используя сумку просмотра. Теперь мне нужно иметь возможность передать тот же список в javascript на странице. Я мог бы восстановить список, используя цикл 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>
}

Однако это похоже на беспорядочный подход и требует много переделок, если сделано изменение. Я знаю, что есть аналогичные сообщения о переполнении стека, но многие из них используют предыдущую версию MVC, и такой синтаксис, похоже, не применяется. Любые идеи?

Ответ 1

Вы можете сделать это в одной и безопасной строке кода, используя парсер JSON. Вы никогда не должны вручную создавать JSON с некоторыми конкатенациями строк и т.д., Как вы пытались сделать в своем примере. Не нужно писать никаких петель.

Вот правильный способ сделать это:

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

Сгенерированный HTML будет выглядеть точно так, как вы ожидаете:

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

Конечно, следующий уровень улучшения этого кода заключается в том, чтобы избавиться от ViewCrap и использовать сильно типизированную модель представления.

Ответ 2

Другим вариантом может быть создание нового действия в контроллере, возвращающего JsonResult. Этот результат json может вернуть ваш список. На своей странице вы можете вызвать действие с помощью jquery и использовать его оттуда.

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

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

Ответ 3

@Дарин Димитров отвечает на вопрос. Я просто хотел бы добавить к нему, если кто-то передаст модель, а не сумасшедшую.

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

Мой пример использования был специфичным для select2. Затем можно просто передать массив данным: attribute

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

ViewModel

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

контроллер

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

Я понимаю, что этот ответ может быть избыточным, но в первый раз я использую Json.Encode и передаю значения модели в расширение jquery. Это для меня слишком круто. Это в определенной степени создает массивную расширяемость для того, что в противном случае было бы @htmlhelper