【问题标题】:Relative URL in JQuery Post CallJQuery Post调用中的相对URL
【发布时间】:2013-08-22 16:20:22
【问题描述】:

我有以下情况。

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

http://localhost:59441/

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

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

CeduleGlobale 是我的 ControllerName 和 UpdateCheckBox 是我的方法名

当我将应用程序放在 testServer 上时,它被放在了 VirtualDirectory 中

因此应用程序现在

http://testServer/JprApplication/

无需指定更多端口以及应用程序名称

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

我修改了它们,所以现在的 URL 是

/JprMvc/CeduleGlobale/UpdateCheckBox

问题是 2 倍。

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

我确信我遗漏了一些基本的东西来简化这个。

谢谢

【问题讨论】:

    标签: jquery asp.net-mvc url-routing


    【解决方案1】:

    根据您的 JavaScript 实际位于何处(在视图或单独的 JS 文件中),您有几个选项。

    选项 1 - 视图内部

    只需使用 Html Helpers 为您生成链接

    <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") 代替。
    • 谢谢,但关于选项 3:很确定您不想使用 Server.MapPath,因为这会暴露映射到该虚拟路径的物理目录。您可能打算使用Request.ApplicationPath,它通常用于在运行时生成“approot”字符串以供 JS 方法使用(尤其是对于应用名称无法硬编码的 COTS 产品)。
    • 选项 3 - 不要将 @Request.ApplicationPath 写入每个视图,只需将其写入一次 _Layout.cshtml(或任何“主”页面)。现在你有一个可用于所有 JS 文件的全局变量。
    【解决方案2】:

    据我所知,没有其他方法可以解决这个问题。除非您愿意使用相对 URL 即:

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

    但是当你重构代码时,这可能会因为各种原因变得一团糟。 或者,预先添加全局定义的 URL,因此您只需在投入生产之前更改一次即可。

    //Globally defined serverRoot
    serverRoot = "http://someaddress/somevirtualdirectory";
    
    $.ajax({
            type: "POST",
            url: serverRoot + "/CeduleGlobale/UpdateCheckBox", ...
    

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

    【讨论】:

    • 第一部分不起作用。第二部分似乎起作用。谢谢
    • 是的,第一个选项只有在调用它的页面相对于服务器根目录时才有效。相对 url 充其量是令人头疼的,因此出于多种原因,我只会真正推荐我上面的第二个建议!
    • 而不是"./CeduleGlobale...如果您使用的是无扩展网址,您可能需要window.location.pathname + "/CeduleGlobale...
    • 本质上这是首选解决方案(第二部分),但 -1 用于硬编码 serverRoot 路径,也用于硬编码协议 (http)。建议改用 Request.ApplicationPath 并将该变量发送给 JS。然后当你修改你的协议、主机和应用程序名称时,你不必更改定义serverRoot的每一个该死的文件
    【解决方案3】:

    我在使用 JQuery 的 MVC 5 上遇到了这种问题,所以我使用了这个解决方案,当您在 Localhost 和任何 Navigator 中时,即使您在子文件夹中部署应用程序也能解决这个问题。

    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             
    });
    

    【讨论】:

      【解决方案4】:

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

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

      希望这会有所帮助。 :)

      【讨论】:

        【解决方案5】:

        将@Url.Action("action","controller") 从视图传递给javascript。这将允许它在运行时动态更新。

        <script>
           myJavascriptfunction(@Url.Action("action","controller"),param1,param2);
        </script>
        

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

        【讨论】:

          【解决方案6】:

          @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
              }
          });
          

          显然您可能希望创建自己的命名空间或保存polluting window 的东西。我试图让下面的示例尽可能简单。

          【讨论】:

            【解决方案7】:

            http://localhost:59441/
            http://testServer/JprApplication/ 都适用于您的

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

            如果您在 iis 中托管,您只需在您的
            C:\Windows\System32\drivers\etc\hosts 中创建一个虚拟主机

            文件。 在你的主机文件底部添加这一行

            127.0.0.1 CeduleGlobale

            像这样创建一个新站点选择站点,右键单击并创建一个新站点

            填写您的详细信息并设置与您在“CeduleGlobale”上创建的主机名相同的主机名

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

            【讨论】:

              猜你喜欢
              • 2012-06-24
              • 1970-01-01
              • 1970-01-01
              • 2010-09-09
              • 2013-03-03
              • 1970-01-01
              • 2011-01-22
              • 1970-01-01
              • 2014-01-15
              相关资源
              最近更新 更多