【问题标题】:Problem: ASP.NET does not recognize external script问题:ASP.NET 无法识别外部脚本
【发布时间】:2011-04-04 09:12:48
【问题描述】:

我有一个简单但非常烦人的问题。我有一个使用 Razor 作为视图引擎的 ASP.NET MVC3 应用程序。

我有两个从局部视图调用的脚本,如果我将整个代码放在 _layout 页面中,它们会很好地工作。如果我将脚本放在外部文件中并引用它们,它们就不起作用。怎么可能?我已经检查了基本问题,例如文件位置和脚本标签的语法。

这是 JavaScript 代码:

$(document).ready(function () {
$('#Year').change(function () {
    var selectedYear = $(this).val();
    if (selectedYear != null && selectedYear != '') {
        $.getJSON('@Url.Action("Months", "Home")', { year: selectedYear }, function (months) {
            var monthsSelect = $('#Month');
            monthsSelect.empty();
            $.each(months, function (index, month) {
                monthsSelect.append($('<option/>', {
                    value: month.value,
                    text: month.text
                }));
            });
        });
    }
}).change();

});

这里是 _Layout 文件中的参考:

<script src="../../Scripts/CascadeDropDownList.js" type="text/javascript"></script>

这是将 Json 结果返回给视图的操作方法:

public ActionResult Months(int year)
    {
        if (year == DateTime.Now.Year)
        {
            return Json(
                Enumerable.Range(1, (DateTime.Now.Month -1)).Select(m => new 
                {
                    value = m,
                    text = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(m)
                }),
                JsonRequestBehavior.AllowGet
            );
        }
        return Json(
            Enumerable.Range(1, 12).Select(m => new 
            {
                value = m,
                text = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(m) 
            }),
            JsonRequestBehavior.AllowGet
        );
    }

堆栈:

[ArgumentException: Illegal characters in path.]
   System.IO.Path.CheckInvalidPathChars(String path) +126
   System.IO.Path.Combine(String path1, String path2) +38
   System.Web.Configuration.UserMapPath.GetPhysicalPathForPath(String path, VirtualDirectoryMapping mapping) +114
   System.Web.Configuration.UserMapPath.GetPathConfigFilename(String siteID, VirtualPath path, String&amp; directory, String&amp; baseName) +82
   System.Web.Configuration.UserMapPath.MapPath(String siteID, String path) +58
   System.Web.Hosting.HostingEnvironment.MapPathActual(VirtualPath virtualPath, Boolean permitNull) +301
   System.Web.Hosting.HostingEnvironment.MapPathInternal(VirtualPath virtualPath, Boolean permitNull) +51
   System.Web.CachedPathData.GetPhysicalPath(VirtualPath virtualPath) +39
   System.Web.CachedPathData.GetConfigPathData(String configPath) +704
   System.Web.CachedPathData.GetVirtualPathData(VirtualPath virtualPath, Boolean permitPathsOutsideApp) +110
   System.Web.HttpContext.GetFilePathData() +36
   System.Web.HttpContext.GetConfigurationPathData() +26
   System.Web.Configuration.RuntimeConfig.GetConfig(HttpContext context) +43
   System.Web.Configuration.CustomErrorsSection.GetSettings(HttpContext context, Boolean canThrow) +41
   System.Web.HttpResponse.ReportRuntimeError(Exception e, Boolean canThrow, Boolean localExecute) +101
   System.Web.HttpRuntime.FinishRequest(HttpWorkerRequest wr, HttpContext context, Exception e) +397
</pre></code>

提前致谢

【问题讨论】:

  • “不工作”是什么意思?包含错误和/或代码会有所帮助。
  • 它没有给出任何错误,只是没有执行。我现在正试图用 Fiddler 整理一些东西,以防万一发布信息。感谢您的帮助

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


【解决方案1】:

问题是 JS 文件没有被 razor 解析器处理,所以这个代码是在客户端上渲染的,完全是这个

$(document).ready(function () {
$('#Year').change(function () {
    var selectedYear = $(this).val();
    if (selectedYear != null && selectedYear != '') {
        $.getJSON('@Url.Action("Months", "Home")', { year: selectedYear }, function (months) {
            var monthsSelect = $('#Month');
            monthsSelect.empty();
            $.each(months, function (index, month) {
                monthsSelect.append($('<option/>', {
                    value: month.value,
                    text: month.text
                }));
            });
        });
    }
}).change();

请注意,请求网址在客户端完全相同

@Url.Action("月", "家")

它不会被转换为真实的 URL,因为 JS 文件不是由 razor 解析器处理的。或者,实际上是任何其他解析器。这就是为什么外部文件不起作用的原因。如果你把它放在 razor 视图中,@Url.Action 会被 razor 处理并在客户端生成有效的链接

【讨论】:

  • @Archil:感谢您的回答。这个问题越来越清楚了。感谢您,我意识到我的应用程序中的其他 js 文件都没有使用 Url.Action 方法,因为它们没有调用控制器上的任何操作方法。我还在网上发现了一个讨论,其中一个人将双引号(%20)归咎于路径中非法字符的原因。有没有其他方法可以从 javascript/jQuery 调用一种操作方法?谢谢
  • @Archil:您知道这是 Razor 问题还是所有 ASP.NET 应用程序的典型问题?您通常如何从 javascript 调用操作方法?
  • 这不是问题,这是 MVC 应用程序的典型问题。案例很简单——如果你希望你的代码是生成的而不是静态的,你不应该把它写在 js 文件中。
  • 很抱歉,但我真的认为是个问题。我认为用 Javascript 代码填充您的 _Layout 页面不是一件优雅的事情(根本不是 DRY),它违反了 MVC 基础的可重用性原则。如果我想使用与操作方法交互的 Javascript在另一个应用程序中,我必须复制并粘贴所有 js 代码,而不是简单地引用它?
【解决方案2】:

永远不要像这样硬编码网址:

<script src="../../Scripts/CascadeDropDownList.js" type="text/javascript"></script>

在处理 url 时始终使用 Url 助手:

<script src="@Url.Content("~/Scripts/CascadeDropDownList.js")" type="text/javascript"></script>

还要确保您的控制器操作不会引发异常,并且由于 JSON 部分,请确保它允许 GET 请求:

public ActionResult Months(int year) 
{
    var someModel = ...
    return Json(someModel, JsonRequestBehavior.AllowGet);
}

最后确保此操作返回的模型是一个集合,并且该集合的每个元素都具有textvalue 属性(区分大小写)。

您还想对脚本末尾的.change() 方法调用做什么?如果您想在页面加载时填充此下拉列表,我强烈建议您在服务器端执行此操作(在呈现此视图的相应控制器操作中)。

【讨论】:

  • 亲爱的 Darin,在我的应用程序中,我已经关注了 Json 请求中的 AllowGet 以及传递/返回到/通过操作方法的元素。如果我直接在 _Layout 页面中编写脚本而不将其引用到外部文件,则该脚本实际上可以工作。我还有其他一些脚本,如果被引用,它们可以完美运行。我运行 Fiddler 并在调用脚本时获得“Illegal characters in path.
  • @Francesco,你在运行什么脚本?你的控制器动作是什么样的?
  • 我附在主帖脚本和操作方法中。谢谢
  • @Francesco,您是否尝试包含我在回答中显示的脚本?使用 Url.Content 助手而不是硬编码 url?
  • @Dimitri:是的,我做到了。实际上一开始我是使用 Url.Content 来包含脚本,我认为这就是脚本没有执行的原因。这就是为什么我改用“经典”方式
猜你喜欢
  • 2014-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 2015-05-26
  • 2020-03-14
  • 1970-01-01
相关资源
最近更新 更多