JQuery Post调用中的相对URL

31

我有以下情况。

我开发了我的第一个MVC Asp.Net应用程序。它在我的服务器上运行,地址如下:

http://localhost:59441/

我写了一些类似于这样的 JQuery Post 方法

  $.ajax({
        type: "POST",
        url: "/CeduleGlobale/UpdateCheckBox", ...

CeduleGlobale是我的Controller名称 和 UpdateCheckBox是我的方法名称

当我将应用程序放在测试服务器上时,它被放置在虚拟目录中

因此应用程序现在是

http://testServer/JprApplication/

不再需要指定端口号,也需要应用程序名称。

测试开始后,我很快注意到我的JQuery Post调用不再起作用了...

我进行了修改,现在URL为

/JprMvc/CeduleGlobale/UpdateCheckBox

问题有两个方面:

  1. 这使得在我的开发机上进行测试很困难,因为IIS Express不允许我指定虚拟目录。
  2. 我不喜欢在JQuery中硬编码虚拟目录名称,因为我不知道应用程序在生产环境中会有什么名称,因此我必须在安装应用程序之前修改我的脚本。

我确定我错过了一些基本的东西来简化这个问题。

谢谢。

7个回答

53

根据您实际放置 JavaScript 的位置(在视图内部还是单独的 JS 文件中),您有几个选项。

选项 1 - 在视图内部

只需使用 Html 辅助程序为您生成链接即可。

<script type="text/javascript">
   $(function(){
        $.ajax({
           type: "POST",
           url: "@Url.Action("UpdateCheckBox", "CeduleGlobale")"
        });
   });
</script>

选项2-独立的 JS 文件

通常我们每个页面都有一个函数来设置该页面的处理程序。因此,我们可以像下面这样做:

查看

<script type="text/javascript">
    $(function(){
        SetOrderPage('@Url.Action("UpdateCheckBox", "CeduleGlobale")');
    });
</script>

独立的JS文件

function SetOrderPage(ajaxPostUrl){
       $.ajax({
           type: "POST",
           url: ajaxPostUrl
       )};
}

选项3-独立JS文件方法2

您可以在JS文件中设置一个全局变量作为站点根目录。这里的缺点是需要手动创建每个操作方法路径。在每个页面上,您可以将站点根全局变量设置如下:

独立JS文件

var siteRoot;

查看

<script type="text/javascript">
    siteRoot = '@Request.ApplicationPath';
</script>

请记住,在独立的JS文件中无法使用Razor语法。我认为最好让Razor/MVC/.NET动态地提供站点路径或URL路由,这样能够真正减少在移动站点/虚拟目录之间可能出现的错误。


我个人不太喜欢使用路由名称,除非它们确实很复杂,大多数时候我只关心简单的控制器/操作,因此我使用 Url.Action("MyAction", "MyController")。 - viggity
1
谢谢,但是关于选项3:我很确定你不想使用Server.MapPath,因为它会暴露映射到该虚拟路径的物理目录。你可能想使用Request.ApplicationPath,这通常用于在运行时生成“approot”字符串以供JS方法使用(特别是对于COTS产品,其中应用程序名称不能硬编码)。 - nothingisnecessary
选项3 - 不要在每个单独的视图中编写@Request.ApplicationPath,只需在您的_Layout.cshtml(或任何“主”页面)中编写一次即可。现在,您可以在所有JS文件中使用全局变量。 - Dimskiy

7
据我所知,除非您愿意使用相对URL,否则没有其他解决方法。例如:

$.ajax({
        type: "POST",
        url: "./CeduleGlobale/UpdateCheckBox", ...

但是当你重构代码时,这样做可能会因各种原因变得混乱。

或者可以在全局定义的 URL 之前添加,因此您只需要在上线之前更改一次即可。

即:

//Globally defined serverRoot
serverRoot = "http://someaddress/somevirtualdirectory";

$.ajax({
        type: "POST",
        url: serverRoot + "/CeduleGlobale/UpdateCheckBox", ...

这样,如果您不需要它,只需设置serverRoot ='';,一切都会恢复到现在的状态。


第一部分不起作用。第二部分似乎起作用了。谢谢。 - SerenityNow
是的,第一个选项只有在调用它的页面相对于服务器根目录时才能正常工作。相对URL最多会带来麻烦,因此出于许多原因,我实际上更建议采用上面提到的第二个建议! - Rob Schmuecker
如果你使用无扩展名的URL,那么你可能需要使用window.location.pathname + "/CeduleGlobale",而不是"./CeduleGlobale" - Chris Marisic
本质上,这是首选解决方案(第二部分),但硬编码serverRoot路径和协议(http)得到-1分。建议改用Request.ApplicationPath并将该变量发射到JS中。然后,当您修改协议、主机和应用程序名称时,您不必更改定义serverRoot的每个文件。 - nothingisnecessary

2
@Tommy的回答是一个很好的指引,但是对于.NET Core,我必须以不同的方式处理,因为Request对象具有不同的属性。
由于部署到虚拟目录,但在开发中使用IIS Express,使得事情变得更加棘手;因此需要在设置基本url时使用if语句。

Shared/_Layout.cshtml

<!-- Set the site root for javascript in _Layout.cshtml.-->
@if (!String.IsNullOrWhiteSpace(@Context.Request.PathBase.Value))
{
    /* LIVE - includes virtual directory */
    <script>
        window.siteRoot = "@Context.Request.Scheme" + "://" + "@Context.Request.Host.Value" + "@Context.Request.PathBase.Value" + "/";
    </script>
}
else
{
   /* DEBUG - no virutal directory, e.g. IIS Express */
    <script>
        window.siteRoot = "@Context.Request.Scheme" + "://" + "@Context.Request.Host.Value" + "/";
    </script>
}

然后从任何JavaScript文件中

/* from any javascript file */
var url = window.siteRoot + 'MySearch/GetMySearchResults';

$.ajax({
    url: url,
    type: 'GET',
    cache: false,
    data: searchObj,
    success: function (result) {
        alert('yatta!');
    },
    fail: function (e, k, n) {
        alert('hmph!');
    },
    done: function() {
        // hide spinner
    }
});

显然,您可能希望创建自己的命名空间或其他内容来保存污染window。我尝试尽可能简化下面的示例。


2

我在使用JQuery的MVC 5时遇到了这种问题,于是我找到了这个解决方案。当你在本地主机上或在任何导航器中部署应用程序时,它可以消除问题,甚至可以在子文件夹中部署。

var pathname = window.location.pathname;
var VirtualDirectory;
if (pathname.indexOf("localhost") >= 0 && pathname.indexOf(":") >= 0) {
    VirtualDirectory = "";
}
else {
    if ((pathname.lastIndexOf('/')) === pathname.length + 1) {
        VirtualDirectory = pathname.substring(pathname.indexOf('/'), pathname.lastIndexOf('/'));
    } else {
        VirtualDirectory = pathname;
    }
}

然后在任何ajax调用中:

$.post(VirtualDirectory + "/Controller/Action", { data: data}, "html")
             .done(function (result) {
                 //some code             
});

1

我知道这是一个旧帖子,但是我遇到了同样的问题,最终来到这里。并通过 UrlHelper.Action 方法解决了这个问题。 它应该像这样使用。(请注意,此特定解决方案将在视图内起作用。)

url: "@Url.Action("UpdateCheckBox", "CeduleGlobale")",

希望这有所帮助。 :)

1
将 @Url.Action("action","controller") 从视图传递到 JavaScript 中。这样可以在运行时动态更新它。
<script>
   myJavascriptfunction(@Url.Action("action","controller"),param1,param2);
</script>

可能有一个函数可以获取根路径,您可以使用它来初始化先前答案中的根变量。

0

http://localhost:59441/
http://testServer/JprApplication/ 两者都能使用您的

$.ajax({ type: "POST", url: "/CeduleGlobale/UpdateCheckBox", ...

如果您在IIS中托管,只需在您的
C:\Windows\System32\drivers\etc\hosts

文件中创建一个虚拟主机。 在主机文件底部添加此行

127.0.0.1 CeduleGlobale

create a new site like so 像这样创建一个新站点:选择站点,右键单击并创建一个新站点

fill in your details and set the same hostname as you created above 'CeduleGlobale'

请填写您的详细信息,并将主机名设置为上面创建的“CeduleGlobale”

然后将您的MVC应用程序部署到此站点


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