在ASP.NET MVC中使用主页面脚本

69

我对ASP.NET MVC还比较陌生,在处理脚本时遇到了一些问题... 特别是我想在大多数页面中使用jQuery,所以将其放在母版页中是有意义的。然而,如果我这样做(从~/Views/Shared/Site.Master):

<script src="../../Scripts/jquery-1.2.6.js" type="text/javascript"></script>

这确切地是发送到客户端的内容——当然,前提是我们当前的路由恰好拥有正确层数。以~/Scripts/...开头不起作用。以/Scripts/...开头只有在项目位于站点根目录时才会生效(我不想假设)。

我有一个可行的方法(我将在下面发布)——但是:我错过了什么吗?

我宁愿不涉及脚本管理器,因为那似乎违背了ASP.NET MVC模型的简单性……或者我太过担心了?

这是我可以让它工作的方式,也适用于复杂的虚拟路径,但似乎过于复杂:

<script src="<%=Url.Content("~/Scripts/jquery-1.2.6.js")%>" type="text/javascript"></script>

3
使用“~”前缀可以很好地用于<link>元素的href属性,但不能用于<script>元素的'src'属性,这就是让人烦恼的事情。 - belugabob
@belugabob:是什么让你觉得这在script标签的src属性中不起作用了? - feihtthief
11个回答

45

我有一个AppHelper类,其中包含一些用于添加脚本引用的方法:

public static string ReferenceScript(string scriptFile)
{
    var filePath = VirtualPathUtility.ToAbsolute("~/Scripts/" + scriptFile);
    return "<script type=\"text/javascript\" src=\"" + filePath + "\"></script>";
}

因此在您的主页面中,您可以使用:

<%= AppHelper.ReferenceScript("jquery-1.2.6.js") %>

6
我喜欢这个;对于常用的API,我现在使用HtmlHelper的扩展方法做了类似的事情,但+1。 - Marc Gravell
是的,我真的很喜欢扩展方法,但我为引用图像、CSS和SWF文件创建了很多方法。为了不过载HtmlHelper类,我创建了AppHelper并将其命名空间添加到web.config中。 - Eduardo Campañó
HtmlHelper的使用只是为了与许多其他MVC代码相似。 - Marc Gravell

35

我认为最简单的方法是使用以下内容,而且它在视图中也可以工作。

<script type="text/javascript" src="<%=ResolveUrl("~/Scripts/myscript.js") %>">

</script>

4
为什么要费心去尝试其他方法呢?这是最简单且最好的方法。 - saille
我在一个敏捷的生产环境中。座右铭是:如果它能工作,就够好了。如果它减少了我需要做的工作量,那就更好了。如果它是一种两全其美的选择,那就太棒了。这很不错。 - Eon

20

根据其他回复,也许可以在Html上编写一个扩展方法(这对于MVC非常常见),与Eduardo的答案类似:

 <%=Html.Script("~/Scripts/jquery-1.2.6.js")%>

使用:

public static string Script(this HtmlHelper html, string path)
{
    var filePath = VirtualPathUtility.ToAbsolute(path);
    return "<script type=\"text/javascript\" src=\"" + filePath + "\"></script>";
}

1
我更喜欢在视图中不包含脚本的路径,这样如果我需要将它们移动到另一个域或子域(或者可能是CDN),我就不必修改每个视图。 - Eduardo Campañó
公正的评论 - 但在这种情况下,它是一个单一的主页面。 - Marc Gravell

10
为什么不直接将您的母版页指向Google的js文件托管?这样即使在部署时(假设您的网站面向网络),您也可以滥用可能预缓存的jQuery文件。

3
假设能够访问Google网络,但并非总是如此……理想情况下,它应该能够只通过本地Web服务器运行。 - Marc Gravell
1
适用于.com网站的好方法,但不一定适用于内部网络应用程序。 - Marc Gravell
2
完全同意。这只是一个FYI,以防万一 :) - OJ.

4
我创建了一个名为GoogleHelper的类,其中包含以下方法,与OJ提到的一些内容有关。
public static string ReferenceGoogleAPI()
{
    var appSettings = new AppSettingsReader();
    string apiKey = appSettings.GetValue("GoogleApiKey", typeof(string)).ToString();
    return ReferenceGoogleAPI(apiKey);
}

public static string ReferenceGoogleAPI(string key)
{
    return "<script type=\"text/javascript\" src=\"http://www.google.com/jsapi?key=" + key + "\"></script>";
}

public static string ReferenceGoogleLibrary(string name, string version)
{
    return "<script type=\"text/javascript\">google.load(\"" + name + "\", \"" + version + "\");</script>";
}

现在我正在添加额外的方法来获取一些客户端位置数据 ;)


1
ResolveUrl 在我看来是最优雅的解决方案。不过遗憾的是,CSS 的 URL 是由 runat=server 解析而不是脚本解析。

1

1

在工作中,我们正在从ASP代码后台执行类似于这样的操作:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  Const jQuery As String = "jQuery"

  With Me.Page.ClientScript
    If Not .IsClientScriptIncludeRegistered(jQuery) Then
      .RegisterClientScriptInclude(jQuery, VirtualPathUtility.ToAbsolute("~/Includes/jQuery-1.2.6.js"))
    End If
  End With
End Sub

我不知道是否可能使用ASP.NET MVC来完成这个任务。


不是这样的。MVC不使用相同的方法。你可能可以在视图中做类似的事情,但没有太多意义。顺便说一下,我添加了关于你之前提出的GetHashCode问题的注释。 - Marc Gravell

1

我只是使用斜杠(/)。

<script src="/Script/jquery-1.4.1.js"></script>

当"jquery-1.4.1.js"文件位于根目录的Script目录中时,它可以完美地工作。

0

我们的应用程序使用虚拟目录部署,我们曾经遇到过其他答案提到的一些问题(无法正确解析路径)。一个行之有效的方法(当然不是唯一的方法)是使用以下代码:

<script src="<%=Request.ApplicationPath%>/Web/AppName/JavaScript/jquery-1.4.1.js"></script>

听起来需要用Url助手扩展进行封装。这样你就可以使用Url.Content或者基于一些配置或参数的你自己的版本了,也许... - Kieron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接