MVC4 Razor对括号感到困惑

时间:2012-02-20 18:10:41

标签: asp.net-mvc razor asp.net-mvc-4

对于所有剃刀专家,我都有一个相当简单的问题。我正在尝试对URL进行jQuery $ .ajax()调用,使用Url.Content()将home相对路径转换为根相对路径。在这样做的过程中,Razor对@section的结尾位置感到有些困惑。我希望能够指定内联URL,但是当我这样做时,Razor认为$ .ajax()参数列表的结尾是我@section的结尾。我正在使用@section,因为我想使用布局将我的javascript放在每个文件的底部。 Razor为何如此困惑?我甚至尝试过使用@(Url.Content(...)),但这也不起作用。

此外,这是解决问题的最佳方法吗?我正在使用ASP.NET MVC 4 Preview。

这有效:

@section Scripts {
    <script type="text/javascript">        
        var getMessagesUrl = '@Url.Content("~/Logging/GetMessages")';

        $(document).ready(function () {
            $.ajax({
                url: getMessagesUrl,
                dataType: 'html',
                success: function (result) {
                    $('tbody').html(result);
                }
            });
        });
    </script>
}

这不是:

@section Scripts {
    <script type="text/javascript">        
        $(document).ready(function () {
            $.ajax({
                url: '@Url.Content("~/Logging/GetMessages")',
                dataType: 'html',
                success: function (result) {
                    $('tbody').html(result);
                }
            }); //Razor thinks this is the curly-brace that ends the section!
        });
    </script>
}

5 个答案:

答案 0 :(得分:9)

这可能取决于解析器的行为。当它遇到@符号时,解析器切换到代码模式并读取隐式表达式Url.Content("~/Logging.GetMessages")(实际上,它会读到'符号,确定它不是有效的表达式和引用中的字符返回到)的结尾。在此阶段之后,解析器与您的视图有点混淆,因为它可能在遇到最终}时处于代码模式字符,并认为它是代码范围的结束。

实际情况是,在使用C#的剃刀视图中使用javascript时必须非常小心。转换到代码是明确的,例如@之后和{之后,但标记的转换有点难以确定。

除了Razor之外,我的建议是将你的javascript应用程序代码粘贴在外部文件中,并利用data- *属性将元信息传递给你的应用程序代码,例如:

<script id="messageScript" type="text/javascript"
    src="/Scripts/messages.js" 
    data-messages="@Url.Content("~/Logging/GetMessages")"></script>

您可以访问:

(function($) {

    $(function() {
        var $this = $("#messageScript");
        $.ajax({
            url: $this.attr("data-messages"),
            type: "html",
            success: function(result) {
                $("tbody").html(result);
            }
        });
    });

})(window.jQuery);

答案 1 :(得分:4)

更新:Dave不符号不会导致问题,他只是在问题中添加它以用于说明目的。

在MVC4上,我能够找出问题所在。这不会编译:

<script type="text/javascript">
  $(document).ready(function () {
    $.ajax({
      url: '@Url.Content("~/Logging/GetMessages")',
      dataType: 'html',
      success: function (result) {
        $('tbody').html(result);
      }
    }); //<-- test
  });
</script>

但这会:

<script type="text/javascript">
  $(document).ready(function () {
    $.ajax({
      url: '@Url.Content("~/Logging/GetMessages")',
      dataType: 'html',
      success: function (result) {
        $('tbody').html(result);
      }
    }); //-- test
  });
</script>

好像它只是投放它的评论中的&lt;

答案 2 :(得分:1)

马修的答案几乎解释了这种行为(虽然,老实说,我不能重现你的问题 - 也不知道为什么它不起作用 - 你的例子在这里运行得很好)。对于不同的方法,您可以将动作/视图专用于生成javascript变量(网址,设置,本地化文本,等等),即:

// Could/should be OutputCached depending on the scenario
public ActionResult Globals()
{
   var model = new ClientGlobalsModel();

   // ClientGlobalsModel has a single (could be more) Dictionary<string, string>
   // (Urls) and a ToJSON() method which uses JavaScriptSerializer to serialize 
   // the object:
   model.Urls.Add("GetMessages", Url.Content("~/Logging/GetMessages"));

   // I mostly use this method for e.g. actions:
   model.Urls.Add("UploadImage", Url.Action("Upload", "Image"));

   Response.ContentType = "text/javascript";

   return View(model);
}

Globals.cshtml:

@model ClientGlobalsModel
@{
    Layout = null; // If you have a layout supplied in e.g. _ViewStart
}
var GLOBALS = @Model.ToJSON()

是的,这可能是一个简单的Content()结果而不是视图 - 但是当你有更多的全局变量(例如设置+网址+文本)时,你可能希望更容易控制脚本输出并且可能序列化每个单独的字典。可能还想在某些共享应用程序命名空间中命名“GLOBALS”变量,以避免污染全局范围。

(例如)Index.cshtml:

<script src="@Url.Action("Globals", "Client")"></script>
<script src="@Url.Content("~/Scripts/main.js")"></script>

...它只包含/ Client / Globals的输出。和“main.js”,我们现在已经移动了你的其余部分:

main.js(静态):

$(document).ready(function () {
   $.ajax({
      url: GLOBALS.Urls.GetMessages,
      dataType: 'html',
      success: function (result) {
         $('tbody').html(result);
      }
   });
});

当然,您可以使用相同类型的方法直接在视图中输出一些用户/上下文/视图特定的设置。对于一些URL或数据,data- *属性方法可能会更好,具体取决于您的口味。不过,我不喜欢在每个HTML页面上填充的基本设置到属性中。

答案 3 :(得分:1)

似乎仍然是最终MVC4 / Visual Studio 2010的问题,但这是我的修复:

@section jQueryDocumentReady
{
  @{
  <text>
     // All the javascript and bracers you want here
  </text>
  }
}

答案 4 :(得分:-1)

感谢所有帮助,伙计们。

看起来它一定是ASP.NET MVC 4 Preview中的一个错误。我刚刚升级到2月15日发布的ASP.NET MVC 4 Beta,问题现在已经完全消失了。