【问题标题】:building relative URLs for an MVC app with JavaScript使用 JavaScript 为 MVC 应用程序构建相对 URL
【发布时间】:2012-04-02 11:03:37
【问题描述】:

我无法让 C# 和 JavaScript/jQuery 在这里发挥得很好。

我有一个淘汰视图模型,普通的旧 javascript 对象...它的属性/方法之一触发 .ajax() 调用,并且 url 参数是使用它的一些其他属性值(javascript 变量)构建的。

这在完全包含在 JavaScript 中时可以正常工作,但是当作为应用程序部署到 IIS 时,相对路径会被破坏。

在 MVC3 中,通常我会使用 @Url.Action 之类的东西并让服务器端构建地址...但同样,技巧是 C# 不知道更改的 javascript 值。

代码:

var viewModel = {
    vendors: ko.observableArray([]),
    count: ko.observable(10),
    page: ko.observable(1),
    filterText: ko.observable(""),
    submit: function () {
        $.ajax({
            // works fine, until deploy when it is no longer a site relative URL
            url: 'vendors/' + viewModel.count() + '/' + viewModel.filterText(),

            // does not work, because C# is unaware of the javascript variables.
            //url: @Url.Action("Vendors", "Home", new { count = viewModel.count(), filter = viewModel.filterText() })

            dataType: 'json',
            success: function (data) {
                viewModel.vendors(data);
            }
        });    
    }
    // next: // load sequence starting with (page+1 * count) 
    // previous: // load sequence starting with (page-1 * count)
};
ko.applyBindings(viewModel);

问题:

然后我的问题是,如何使用 javascript 变量值(例如 count、filterText)构建 ajax 调用的 url,并且仍然从应用程序的相对根目录映射?

【问题讨论】:

  • javascript viewModel 是在 .js 文件中定义的,还是在您的视图页面上定义的?您可以考虑映射 url @Url.Action("Vendors","Home") 然后在 javascript 中添加属性

标签: c# javascript asp.net-mvc knockout.js relative-path


【解决方案1】:

我们在我的 MVC 3 项目中这样做的方式是在主布局中包含以下内容:

<script type="text/javascript">
    var baseSiteURL = '@Url.Content("~/")';
</script>

然后您只需将其添加到 JavaScript 中的 URL。

您的示例中的内容如下:

url: baseSiteURL + 'vendors/' + viewModel.count() + '/' + viewModel.filterText()

【讨论】:

  • 是的。诀窍是 C# 代码周围的引号......无论如何 +1。
  • 如果您要更改路由规则,这可能会停止工作。
【解决方案2】:

一种可能性是将这些 javascript 值作为请求参数发送:

$.ajax({
    url: '@Url.Action("vendors")',
    data: { count: viewModel.count(), filter: viewModel.filterText() },
    dataType: 'json',
    success: function (data) {
        viewModel.vendors(data);
    }
});

当然,这意味着您使用的是默认路由,并且参数将简单地作为查询字符串参数(如果您使用的是 GET)或作为 POST 请求正文的一部分发送到服务器。在这两种情况下,您都将以相同的方式在服务器上获取它们:

public ActionResult Vendors(int count, string filter)
{
    ...
}

如果您绝对坚持为您的 AJAX 请求提供一些自定义路由,另一种可能性是使用简单的字符串替换:

var url = '@Url.Action("vendors", new { count = "__count__", filter = "__filterText__" })';
url = url.replace('__count__', viewModel.count())
         .replace('__filter__', viewModel.filterText());
$.ajax({
    url: url,
    dataType: 'json',
    success: function (data) {
        viewModel.vendors(data);
    }
});

【讨论】:

  • 你的回答是最有帮助的,虽然我不想要查询字符串参数。看看我的答案......如果你编辑你的答案以包括我的例子,我会把支票扔给你。如果没有,我会标记我的。感谢您的帮助。
  • @one.beat.consumer,不,不会将您的答案作为我的一部分,因为我不喜欢它。在您的答案中,您正在对您的网址进行硬编码,而不是使用网址助手和路由来生成它们。在您的代码中,您在 javascript 中假设 url 的格式为 {controller}/{action}/{count}/{filter}。这是脆弱的,它会在您触摸路线的那一刻破裂。使用我的解决方案,您正在使用 url helper 根据您的路由定义生成整个 url。您只需在客户端用相应的 javascript 值替换虚拟占位符。
  • 除了一个 / 我的答案中硬编码的内容是什么?我正在使用与您相同的 Url 助手(尽管我可能会将其更改为使用命名路由而不是操作模式 - 以说明您提到的脆弱性)并且 javascript 变量始终具有值,因为它们在 ko.可以调用此方法之前的可观察对象。再说一次,除了单次重击,我想了解您为什么认为它更加不同?
  • @one.beat.consumer,不同的是您依赖于您的路由令牌的特定顺序,并且它们由/ 分隔。如果您决定颠倒 Global.asax 中 {count}{filter} 路由标记的顺序怎么办?现在,您还必须修改硬编码此订单的所有客户端代码。另一方面,如果您使用 url 助手:@Url.Action("vendors", new { count = "__count__", filter = "__filterText__" }),那么您的路由配置方式并不重要。
  • 此外,路由看起来像这样 ("Api-Vendors", "/vendors/{count}/{filter}", new { controller = "Home", action = "Vendors", UrlParameter.Optional, UrlParameter.Optional }) 并且 Action 方法上的签名看起来像这样:public ActionResult Vendors(int count = 20, string filter = "") 只是为了确保即使有人破坏了 javascript 或尝试使用手指输入的 URL 访问它这些值始终具有默认值。还是太脆了?
【解决方案3】:

Darin 的回答是最可靠的,但它需要在 ajax 调用中使用查询字符串参数发送数据。

为避免这种情况,我只是将 @Url.Action() 方法用引号括起来,并按照我的意图附加了 javascript 值。

url: "@Url.Action("Vendors", "Home")/" + viewModel.count() + "/" + viewModel.filterText(),

最终,这产生了最好的结果,因为它让我保持一个非常干净的 url...Request.ApplicationPath 似乎太 hackish 并且在技术上可能是 null...@Url.Content() 用于静态“内容”路径(例如图像, 脚本)...等等。

【讨论】:

  • filterText 对我来说看起来像是用户输入的内容,并且可能会出现 ' 符号。这会造成 XSS 漏洞。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多