【问题标题】:Setting ajax url for jQuery in JS file using ASP.NET MVC使用 ASP.NET MVC 在 JS 文件中为 jQuery 设置 ajax url
【发布时间】:2010-09-27 11:01:32
【问题描述】:

当前,当对 MVC 操作进行 Ajax 调用时,我的 javascript 在视图中,而不是在它自己的 JS 文件中。

然后很容易做到这一点:

var xhr = $.ajax({
     url: '<%= Url.Action("DisplayItem","Home") %>/' + el1.siblings("input:hidden").val(),
     data: { ajax: "Y" },
     cache: false,
     success: function(response) { displayMore(response, el1, xhr) }
});

...然后在 JS 中使用 Url.Action() 在 ajax 调用中包含 URL 非常简单。如果没有对 URL 进行硬编码,我怎么能移动它自己的 JS 文件?

【问题讨论】:

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


    【解决方案1】:

    我这样做的方法是在服务器端生成 URL 并使用 HTML5 data attribute 存储在生成的 HTML 中,例如:(Razor 语法)

    <li class='customClass' data-url='@Url.Action("DisplayItems", "Home", new { id = Model.Id })'>...</li>
    

    然后你可以使用jQuery attr() 函数来获取url,例如:

    $(".customClass").click(function () {
        $.ajax({
            url: $(this).attr("data-url"),
            success: function (data) {
                // do stuff
            }
        });
    });
    

    如果您生成 HTML 客户端以响应 AJAX 调用,您可以在 JSON 有效负载中包含相关 URL,并以相同方式填充 data- 属性。

    【讨论】:

    • 这应该是第一答案。对于那些在服务器端添加 html 属性的人......data_url 在 html 源代码中转换为 data-url
    • 小更新:jQuery 的更高版本支持直接使用data() 函数(例如$(this).data('url'))访问数据属性。
    • 光滑!将近 4 年后帮助了我
    • @Valamas-AUS 这是一个很好的答案,可以满足许多情况,但我不确定这是不是最好的答案。我认为生成查找表的想法仍然是一个更好的答案,尽管我不同意上面介绍的实现。我对data-url 方法的问题是它假设每个需要的路由都附加了一个DOM 元素。根据我的经验,情况通常并非如此。
    • @crush - 没有最好的东西 :) “现代” js 可能会做不同的事情。毫无疑问,有一个框架。
    【解决方案2】:

    这种方式充分利用了 MVC 路由,因此您可以充分利用 MVC 框架。 受到 stusmith 回答的启发。

    我在ApplicationController 中有一个针对此 URL 的动态 javascript 的操作:

     /application/js
    

    我在这里包含静态文件是因为我只想要一个主 javascript 文件来下载。如果需要,您可以选择只返回动态内容:

         /// <summary>
        /// Renders out javascript
        /// </summary>
        /// <returns></returns>
        [OutputCache(CacheProfile = "Script")]
        [ActionName("js")]
        public ContentResult RenderJavascript()
        {
            StringBuilder js = new StringBuilder();
    
            // load all my static javascript files                    
            js.AppendLine(IO.File.ReadAllText(Request.MapPath("~/Scripts/rr/cart.js")));
            js.AppendLine(";");
    
            // dynamic javascript for lookup tables
            js.AppendLine(GetLookupTables());
            js.AppendLine(";");
    
            return new ContentResult()
            {
                Content = js.ToString(),
                ContentType = "application/x-javascript"
            };
        }
    

    这是创建查找表的辅助函数。只需为您要使用的每个 RouteUrl 添加一行。

        [NonAction]
        private string GetLookupTables() 
        {
            StringBuilder js = new StringBuilder();
    
            // list of keys that correspond to route URLS
            var urls = new[] {
                new { key = "updateCart", url = Url.RouteUrl("cart-route", new { action = "updatecart" }) },
                new { key = "removeItem", url = Url.RouteUrl("cart-route", new { action = "removeitem" }) }
            };
    
            // lookup table function
            js.AppendLine("// URL Lookuptable");
            js.AppendLine("$.url=function(url) {");
            js.AppendLine("var lookupTable = " + new JavaScriptSerializer().Serialize(urls.ToDictionary(x=>x.key, x=>x.url)) + ";");
            js.AppendLine("return lookupTable[url];");
            js.AppendLine("}");
    
            return js.ToString();
        }
    

    这会生成以下动态 javascript,它基本上只是一个从任意键到我的操作方法所需的 URL 的查找表:

    // URL Lookuptable
    $.url=function(url) {
    var lookupTable = {"updateCart":"/rrmvc/store/cart/updatecart","removeItem":"/rrmvc/store/cart/removeitem"};
    return lookupTable[url];
    }
    

    在 cart.js 中我可以有这样的功能。 请注意,url 参数取自查找表:

     var RRStore = {};
     RRStore.updateCart = function(sku, qty) {
    
        $.ajax({
    
            type: "POST",
            url: $.url("updateCart"),
            data: "sku=" + sku + "&qty=" + qty,
            dataType: "json"
    
            // beforeSend: function (){},
            // success: function (){},
            // error: function (){},
            // complete: function (){},
        });
    
        return false;
    

    };

    我可以从任何地方调用它:

     RRStore.updateCart(1001, 5);
    

    这似乎是我能想出的唯一方法,可以让我以干净的方式使用路由。在 javascript 中动态创建 URL 很麻烦,而且很难测试。测试类型可以在这里的某处添加一个层,以方便测试。

    【讨论】:

    • 这真是太好了,真的很干净!
    • 请注意,您在此处显示了所有操作方法的路径。确保您对需要安全的操作方法有足够的安全性 - 并且您可能会收到对这些方法的更多爬虫请求(未经验证)
    • 你可以用 robots.txt 文件来反驳?
    • 以疏忽为安全,或以默默无闻为安全,无论如何都不是一个好的策略。即使您没有将所有可用的路由发送到浏览器,也不应该假设它们不能被“发现”。我相信你会同意,但只是想补充一点。
    【解决方案3】:

    将 AJAX 调用包装在一个函数中,该函数将 URL(和任何其他数据)作为参数并返回响应。那么在你看来,调用函数而不是直接调用AJAX调用。

    function doAjax( url, data, elem, callback )
    {
        return $.ajax({
            url: url,
            data: { ajax: data },
            cache: false,
            success: function(response) { callback(response, elem, xhr); }
        });
    }
    
    ...
    
    <input type='button' value='Go get it' onclick='doAjax( <%= Url.Action ...
    

    我不确定这是否比在页面上而不是在 JS 文件中调用 Ajax 更好,除非您经常使用完全相同的模式。

    【讨论】:

    • 这不是我们试图通过连接 document.ready 上的事件来删除的内联 JS 吗???
    • 您的解决方案在技术上是正确的,但我同意您的看法,这并不是真的更好。
    • 这取决于您要抽象到库函数中的内容。在这种情况下,您并没有抽象出任何业务逻辑,只是隐藏了您正在使用 jquery 的事实
    【解决方案4】:

    使用模块模式。

    // separate js file var PAGE_MODULE = (function () { var url = {}, init = function(url) { ... }, load = function() { $.ajax({ url: url, ... }); } return { init: init }; })(); // calling init goes on the page itself PAGE_MODULE.init(" %: Url.Action(...) %>");

    一般来说,内联 onclick 处理程序不是好的 javascript,因为您使用的是全局函数。

    onclick='doAjax(

    我建议阅读http://jqfundamentals.com/book/index.html#N20D82 以更好地了解模块模式。

    【讨论】:

      【解决方案5】:

      这是另一种方式:

      在您的母版页中,为内联脚本添加一个区域:

      <head>
        ...
        <asp:ContentPlaceHolder runat="server" ID="_inlineScripts" />
        ...
      </head>
      

      然后在Page_Load中,创建一个实用函数:

      protected void Page_Load( object sender, EventArgs e )
      {
        AddInlineScript( string.Format( "$.url=function(url){{return '{0}'+url;}}", GetBaseUri() ) );
        ...
      }
      
      private Uri GetBaseUri()
      {
        var requestUrl = Request.Url.AbsoluteUri;
        var i = requestUrl.IndexOf( request.Path );
      
        return new Uri( requestUrl.Substring( 0, i ) );
      }
      
      private void AddInlineScript( string content )
      {
        var script = new HtmlGenericControl( "script" );
      
        script.Attributes.Add( "type", "text/javascript" );
        script.InnerHtml = content;
      
        _inlineScripts.Controls.Add( script );
      }
      

      现在你可以在你的 ajax 中使用这个函数了:

      $.ajax({
        url: $.url('path/to/my-handler'),
        ...
      });
      

      【讨论】:

      • -1 用于在 ASP.NET MVC 中使用 PageLoad。虽然可以改用别的东西……
      • 我必须承认我没有正确阅读这个问题......我认为这是一个 ASP.NET 问题。道歉。
      猜你喜欢
      • 1970-01-01
      • 2011-01-26
      • 2021-11-21
      • 2021-12-10
      • 2013-01-28
      • 2011-06-12
      • 1970-01-01
      相关资源
      最近更新 更多