【问题标题】:Passing list from MVC ViewBag to JavaScript将列表从 MVC ViewBag 传递给 JavaScript
【发布时间】:2013-02-23 20:29:54
【问题描述】:

我有一个用户列表,我使用视图包从控制器传递到我的视图。现在我需要能够将相同的列表传递给页面上的 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>
}

但是,这似乎是一种杂乱无章的方法,如果进行更改,则需要进行大量返工。我知道 Stack Overflow 上也有类似的帖子,但其中很多都使用以前版本的 MVC,并且似乎不适用相同的语法。有什么想法吗?

【问题讨论】:

    标签: javascript asp.net-mvc-4 viewbag


    【解决方案1】:

    @Darin Dimitrov 的回答很到位。如果有人传递模型而不是viewbag,我只想添加它。

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

    我的用例特定于 select2 。然后可以将数组传递给数据:属性

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

    视图模型

    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 创造了巨大的可扩展性

    【讨论】:

      【解决方案2】:

      另一种选择,可能是在您的控制器中创建一个返回 JsonResult 的新操作。此 json 结果可能会返回您的列表。在您的页面中,您可以使用 jquery 调用该操作并从那里使用它。

      public ActionResult GetMyList()
      {
          var list = GetMyUserList();
      
          return Json(new { userlist = list }, JsonRequestBehaviour.AllowGet);
      }
      

      【讨论】:

      • 谢谢你的提示,我也试试这个:)
      【解决方案3】:

      您可以使用 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 并使用强类型视图模型。

      【讨论】:

      • 感谢您快速详细的回答!但是没有 IEnumerable 部分,我收到以下错误“不能使用 lambda 表达式作为动态调度操作的参数...”。添加该部分后,我还会收到错误消息“方法的类型参数......无法从用法中推断出来”。感谢您的帮助,如果这是菜鸟的错误,我们深表歉意。 p.s.我将视图模型用于此页面上的其他内容,这就是我使用视图包的原因。
      • 但是视图模型是您专门设计的一个类,以满足您的视图要求。在这种情况下,您的视图需要生成此动态 javascript。所以你的视图模型应该包含一个IEnumerable&lt;UserModel&gt; 类型的集合属性。然后只需将整个演员表替换为Model.Users.Select(...)。如果您离开弱类型 ViewBag,您需要将其转换为正确的 IEnumerable&lt;T&gt; 类型。
      • 好的,我很快修改了页面并使用了 View 模型,它工作正常。我还不得不参考你的另一个答案stackoverflow.com/questions/12111729/…,不知道 VS2012 中的这个错误。感谢您提供的精彩而翔实的答案!
      猜你喜欢
      • 2012-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多