【问题标题】:Possible to access MVC ViewBag object from Javascript file?可以从 Javascript 文件访问 MVC ViewBag 对象吗?
【发布时间】:2012-05-10 12:06:58
【问题描述】:

是否可以从 MVC 应用程序中的 javascript 文件执行以下操作?

$(function(){
   alert(@ViewBag.someValue);
}

目前它会抛出错误:

引用未定义的 XML 名称 @ViewBag

【问题讨论】:

  • 我之前也问过类似的问题,希望对你有所帮助。 stackoverflow.com/questions/10036903/…
  • 它的 tl;dr 是:使用数据属性在视图中设置值,然后使用 jQuery 访问您单独的 .JS 文件中的这些数据属性。

标签: c# jquery asp.net-mvc asp.net-mvc-3 razor


【解决方案1】:

我认为目前没有任何方法可以做到这一点。 Razor 引擎不解析 Javascript 文件,仅解析 Razor 视图。但是,您可以通过在 Razor 视图中设置变量来完成您想要的操作:

<script>
  var someStringValue = '@(ViewBag.someStringValue)';
  var someNumericValue = @(ViewBag.someNumericValue);
</script>
<!-- "someStringValue" and "someNumericValue" will be available in script -->
<script src="js/myscript.js"></script>

正如 Joe 在 cmets 中指出的那样,如果上面的字符串值中有一个单引号,它就会中断。如果你想让这个完全铁定,你必须用转义的单引号替换所有的单引号。那里的问题是所有突然的斜线成为一个问题。例如,如果您的字符串是“foo \' bar”,并且您替换了单引号,那么会出现“foo \\' bar”,而您又回到了同样的问题。 (这是链式编码的古老难题。)处理此问题的最佳方法是将反斜杠和引号视为特殊,并确保它们全部转义:

  @{
      var safeStringValue = ViewBag.someStringValue
          .Replace("\\", "\\\\")
          .Replace("'", "\\'");
  }
  var someStringValue = '@(safeStringValue)';

【讨论】:

  • 如果你的 ViewBag.someStringValue 中有一个单引号,这不会破坏 js 吗?我相信正确的方法是使用隐藏的表单字段(如下面的答案所示)
  • 这是一个好点,乔,你说得对:单引号确实会搞砸。我觉得隐藏表单字段方法非常笨拙,不过这更直接。并且单引号问题很容易处理......我会相应地更新我的答案,感谢您的提示。
  • 我认为不需要括号
  • Idk 如果这在以前的版本中是可能的,但您可以直接在警报中输入“@(ViewBag.someStringValue)”(不使用变量)并且仍然会收到基础信息。
  • 谢谢,我认为.Replace("'", "\\'); 可能必须是:.Replace("'", "\'");
【解决方案2】:

不在 JavaScript 文件中,不。
您的 JavaScript 文件可以包含一个类,您可以在视图中实例化该类的一个新实例,然后您可以在类构造函数中传递 ViewBag 值。

或者如果它不是一个类,你唯一的选择是在你的 HTML 元素中使用data 属性,将它们分配给你的视图中的属性,然后在 JS 文件中检索它们。

假设你有这个输入:

<input type="text" id="myInput" data-myValue="@ViewBag.MyValue" />

然后在您的 JS 文件中,您可以使用:

var myVal = $("#myInput").data("myValue");

【讨论】:

  • +1 - 这是最广泛接受的方法,也是我自己使用的方法
  • 小心将 viewbag 数据存储在 html 元素中,具体取决于您正在构建的数据类型和应用程序类型,这可能是一个严重的安全漏洞。在某些情况下,可能值得通过将一些逻辑从 javascript 移动到控制器来进行重组。 (仅在某些情况下,例如我现在的情况!):) 不过答案很好!
  • 如果 data-myValue 的内容包含 HTML 特殊字符,您可能需要进行一些编码或转义
【解决方案3】:

在 HTML 中:

<input type="hidden" id="customInput" data-value = "@ViewBag.CustomValue" />

在脚本中:

var customVal = $("#customInput").data("value");

【讨论】:

  • 这必须被选为答案!.. 投票+
【解决方案4】:

为此,您的 JavaScript 文件需要在服务器端进行预处理。从本质上讲,它必须变成某种 ASP.NET 视图,而引用该文件的 script 标记本质上将引用一个响应该视图的控制器操作。

这听起来像是一罐你不想打开的蠕虫。

既然 JavaScript 是客户端的,为什么不将值设置为一些客户端元素并让 JavaScript 与之交互。这可能是额外的间接步骤,但听起来比创建 JavaScript 视图要少得多。

类似这样的:

<script type="text/javascript">
    var someValue = @ViewBag.someValue
</script>

然后外部 JavaScript 文件可以引用该文档范围内的 someValue JavaScript 变量。

甚至:

<input type="hidden" id="someValue" value="@ViewBag.someValue" />

然后你可以访问隐藏的输入。

除非您想出一些非常巧妙的方法来真正使您的 JavaScript 文件可用作视图。这当然是可行的,而且我很容易想到你会遇到的任何问题(除了非常丑陋的视图代码,因为视图引擎会非常混淆什么是JavaScript 和 Razor 是什么...所以期待 ton&lt;text&gt; 标记),所以如果你找到一种巧妙的方法来做这将是非常酷的,尽管对于需要支持的人来说可能不直观后面的代码。

【讨论】:

    【解决方案5】:

    在您的 .cshtml 文件中使用此代码。

     @{
        var jss = new System.Web.Script.Serialization.JavaScriptSerializer();
        var val = jss.Serialize(ViewBag.somevalue); 
        }
    
        <script>
            $(function () {
                var val = '@Html.Raw(val)';
                var obj = $.parseJSON(val);
                console.log(0bj);
        });
        </script>
    

    【讨论】:

      【解决方案6】:

      创建一个视图并将其作为局部视图返回:

      public class AssetsController : Controller
      {
          protected void SetMIME(string mimeType)
          {
              this.Response.AddHeader("Content-Type", mimeType);
              this.Response.ContentType = mimeType;
          }
      
          // this will render a view as a Javascript file
          public ActionResult GlobalJS()
          {
              this.SetMIME("text/javascript");
              return PartialView();
          }
      }
      

      然后在 GlobalJS 视图中添加类似的 javascript 代码(添加 // 将使 Visual Studio intellisense 将其读取为 java-script)

      //<script>
      
          $(document).ready(function () {
             alert('@ViewBag.PropertyName');
          }); 
      
      //</script>
      

      然后在您的最终视图中,您可以像这样添加对 javascript 的引用。

      <script src="@Url.Action("GlobalJS", "Assets")"></script> 
      

      然后在您的最终视图控制器中,您可以创建/传递您的 ViewBags,它将在您的 javascript 中呈现。

      public class MyFinalViewController : Controller
      {
          public ActionResult Index()
          {
              ViewBag.PropertyName = "My ViewBag value!";
              return View();
          }
      }
      

      希望对你有帮助。

      【讨论】:

        【解决方案7】:

        我注意到,如果您尝试这样做,Visual Studio 的内置错误检测器会变得很愚蠢:

        var intvar = @(ViewBag.someNumericValue);
        

        因为@(ViewBag.someNumericValue) 有可能评估为空,这会导致生成以下错误的 JavaScript:

        var intvar = ;
        

        如果您确定 someNemericValue 将设置为有效的数字数据类型,则可以通过执行以下操作来避免出现 Visual Studio 警告:

        var intvar = Number(@(ViewBag.someNumericValue));
        

        这可能会生成以下示例:

        var intvar = Number(25.4);
        

        它适用于负数。如果该项目不在您的 viewbag 中,Number() 的计算结果为 0。

        不再有 Visual Studio 警告!但请确保该值已设置并且是数字,否则您将打开可能的 JavaScript 注入攻击或运行时错误的大门。

        【讨论】:

          【解决方案8】:

          在控制器动作中添加:

           public ActionResult Index()
                  {
                      try
                      {
                          int a, b, c;
                          a = 2; b = 2;
                          c = a / b;
                          ViewBag.ShowMessage = false;
                      }
                      catch (Exception e)
                      {
                          ViewBag.ShowMessage = true;
                          ViewBag.data = e.Message.ToString();
                      }
                      return View();    // return View();
          
                  }
          
          in Index.cshtml
          Place at the bottom:
          
          <input type="hidden" value="@ViewBag.data" id="hdnFlag" />
          
          @if (ViewBag.ShowMessage)
          {
              <script type="text/javascript">
          
                  var h1 = document.getElementById('hdnFlag');
          
                  alert(h1.value);
          
              </script>
              <div class="message-box">Some Message here</div>
          }
          

          【讨论】:

          • 复制异常集 b=0 ,以便显示弹出窗口
          【解决方案9】:

          对于 CoreMVC 3.1,那就是,

          @using Newtonsoft.Json
          var listInJs =  @Html.Raw(JsonConvert.SerializeObject(ViewBag.SomeGenericList));
          

          【讨论】:

            【解决方案10】:

            onclick="myFunction('@ViewBag.MyValue')"

            【讨论】:

              猜你喜欢
              • 2014-01-09
              • 1970-01-01
              • 2015-08-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-09-20
              • 1970-01-01
              • 2020-12-03
              相关资源
              最近更新 更多