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:
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) }
});
...then including the URL in the ajax call using Url.Action()
inside the JS is pretty easy. How could i move this do its own JS file when without hard coding the URL?
Using AJAX In ASP.NET MVC. Implementation of Ajax can be done in two way in ASP.Net Application: using Update Panel and, using jQuery.
Uploading Files in MVC using jQuery AJAX FormDataGo to File->New->Project. Give a suitable name to the Application. Click OK. As you can see in the above image, two files are sent to C# ActionMethod, and both will be uploaded now.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With