对于所有剃刀专家,我都有一个相当简单的问题。我正在尝试对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>
}
答案 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,问题现在已经完全消失了。