使用 ASP.NET MVC 在 JS 文件中为 jQuery 设置 ajax url

Posted

技术标签:

【中文标题】使用 ASP.NET MVC 在 JS 文件中为 jQuery 设置 ajax url【英文标题】:Setting ajax url for jQuery in JS file using ASP.NET MVC 【发布时间】: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 文件?

【问题讨论】:

【参考方案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 问题。道歉。

以上是关于使用 ASP.NET MVC 在 JS 文件中为 jQuery 设置 ajax url的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 jquery 或 ajax 在 c#/asp.net 中为 MVC 项目更新 razor 部分视图

如何在 ASP.NET MVC 中为有效字段设置绿色边框

使用实体框架在 ASP.NET MVC 中为具有一对多关系的数据库播种

我们如何在 ASP.NET MVC 中为整个区域设置授权?

Ajax 传递空值但控制器在 ASP.NET MVC 中为空

如何在 C# 中为枚举值添加描述以与 ASP.NET MVC 中的下拉列表一起使用? [复制]