Setting ajax url for jQuery in JS file using ASP.NET MVC

前端 未结 5 1511
星月不相逢
星月不相逢 2020-12-12 16:43

When doing a Ajax call to an MVC action currently I have my javascript inside the View, not inside its own JS file.

It is then very easy to do this:

         


        
相关标签:
5条回答
  • 2020-12-12 17:11

    The way I do it is generate the URL server-side and store in the generated HTML using an HTML5 data attribute, eg: (Razor syntax)

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

    Then you can use the jQuery attr() function to pick up the url, eg:

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

    If you're generating HTML client-side in response to AJAX calls, you can include the relevant URLs in your JSON payload and populate the data- attribute the same way.

    0 讨论(0)
  • 2020-12-12 17:11

    Use the module pattern.

    
    // 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(...) %>");
    
    

    In general the inline onclick handler is not good javascript as you are using a global function.

    
    onclick='doAjax( 
    

    I recommend reading http://jqfundamentals.com/book/index.html#N20D82 to get a better handle on the module pattern.

    0 讨论(0)
  • 2020-12-12 17:13

    Here's another way:

    In your master page, include an area for inline scripts:

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

    Then in the Page_Load, create a utility function:

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

    Now you can use this function in your ajax:

    $.ajax({
      url: $.url('path/to/my-handler'),
      ...
    });
    
    0 讨论(0)
  • 2020-12-12 17:16

    This way fully uses MVC Routing so you can fully take advantage of the MVC framework. Inspired by stusmith's answer.

    Here I have an action in ApplicationController for dynamic javascript for this URL :

     /application/js
    

    I'm including static files here because I want just one master javascript file to download. You can choose to just return the dynamic stuff if you want:

         /// <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"
            };
        }
    

    This is the helper function that creates our lookup table. Just add in a line for each RouteUrl you want to use.

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

    This generates the following dynamic javascript, which is basically just a lookup table from an arbitrary key to the URL I need for my action method :

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

    In cart.js I can have a function like this. Note that the url parameter is taken from the lookup table :

     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;
    

    };

    I can call it from anywhere with just :

     RRStore.updateCart(1001, 5);
    

    This seemed to be the only way I could come up with that would allow me to use routing in a clean way. Dynamically creating URLS in javascript is icky and hard to test. Testing types can add in a layer somewhere in here to easily facilitate testing.

    0 讨论(0)
  • 2020-12-12 17:22

    Wrap the AJAX call in a function that takes the URL (and any other data) as a parameter(s) and returns the response. Then in your view, call the function instead of calling the AJAX call directly.

    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 ...
    

    I'm not sure that this is any better than having the Ajax call on the page instead of in a JS file, unless you use the exact same pattern frequently.

    0 讨论(0)
提交回复
热议问题