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

时间:2012-04-30 19:47:05

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

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

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

目前它会抛出错误:

  

引用未定义的XML名称@ViewBag

10 个答案:

答案 0 :(得分:85)

我不相信目前有任何方法可以做到这一点。 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在评论中指出的那样,如果其中有单引号,则上面的字符串值将会中断。如果你想让它完全是铁质的,你必须用转义的单引号替换所有单引号。问题在于所有突然的斜线都成了问题。例如,如果您的字符串是“foo \' bar”,并且您替换了单引号,那么将会出现“foo \\' bar”,您就会回到同样的问题。 (这是链式编码的古老难度。)处理此问题的最佳方法是将反斜杠和引号视为特殊,并确保它们全部转义:

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

答案 1 :(得分:27)

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

或者,如果它不是一个类,您唯一的另一种选择是在HTML元素中使用data属性,将它们分配给View中的属性并在JS文件中检索它们。

假设你有这个输入:

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

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

来获得它
var myVal = $("#myInput").data("myValue");

答案 2 :(得分:11)

在Html中:

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

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

答案 3 :(得分:5)

为了做到这一点,您的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 <text>标记,所以如果你找到一个光滑的方式来做这将是非常酷的,虽然可能不直观的需要的人以后支持代码。

答案 4 :(得分:0)

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

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>

    $(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();
    }
}

希望它有所帮助。

答案 5 :(得分:0)

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

var intvar = @(ViewBag.someNumericValue);

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

var intvar = ;

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

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

这可能会生成以下示例:

var intvar = Number(25.4);

它适用于负数。如果项目不在您的视图包中,则Number()的计算结果为0.

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

对于CoreMVC 3.1,应该是

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

答案 8 :(得分:0)

onclick =“ myFunction('@ ​​ViewBag.MyValue')”

答案 9 :(得分:-1)

在控制器操作中添加:

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