可以从 Javascript 文件访问 MVC ViewBag 对象吗?

Posted

技术标签:

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

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

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

目前它会抛出错误:

引用未定义的 XML 名称 @ViewBag

【问题讨论】:

我之前也问过类似的问题,希望对你有所帮助。 ***.com/questions/10036903/… 它的 tl;dr 是:使用数据属性在视图中设置值,然后使用 jQuery 访问您单独的 .JS 文件中的这些数据属性。 【参考方案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')"

【讨论】:

以上是关于可以从 Javascript 文件访问 MVC ViewBag 对象吗?的主要内容,如果未能解决你的问题,请参考以下文章

在.net MVC应用程序中构造javascript

将JSON数组从javascript传递给spring mvc控制器

在 MVC 中移动 javascript 后,Active 中的访问被拒绝

javascript asp .net mvc razor中的访问模型

如何从 javascript 文件中获取函数的值到 ASP.NET MVC 视图?

在javascript中从控制器MVC获取json