Setting ajax url for jQuery in JS file using ASP.NET MVC
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.
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.
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.