What's the best way to avoid hardcoding URL's in JavaScript (primarily used when making AJAX calls)?
In the past:
- Render JavaScript variable with result of
@Url.Action
or@Url.RouteUrl
- Pass result of
@Url.Action
or@Url.RouteUrl
to JavaScript in init/ctor.
Is there a better way?
It would be good to do something like this:
var url = $.routes("actionName", "controllerName") // or "routeName" for named routes
$.post(url, { id = 1 }, function() { //.. });
Which of course isn't really possible (JavaScript doesn't have direct access the to the ViewContext and thus doesn't have access to the route tables).
But i'm wondering if there's a way i can kind of setup my own "route table" for JavaScript, with only the ones i know it would need? (e.g i set it up in the View)
How do people handle this?
Implementing a Javascript routing engine wouldn't be too difficult. First, serialize the Routes from C# to Javascript. Second, recreate the
Url.Action
method.However, that's a bit overkill for any of the projects I've worked on. My team's projects have always rendered a common Javascript variable that holds all necessary URL's.
This approach ensures strongly-typed action methods and lends better to refactoring too.
This is easier said than achieved in practice, but your website should be fully functional with JavaScript turned off. When this is achieved, you should be able to add AJAX support to your website and re-use existing HREF attributes in your anchor tags or action attributes in your FORM tags. The website will be easier to maintain as you won't need to update links in your JavaScript files.
I've decided to implement my own UrlFactory, using ASP.NET helpers directly (Html/Url) in my code, now I don't have the src with me, I'll post'em tomorrow.
Pros on this: I can track each and every url easily and perform some rewriting in a centralized fashion.
Example of usage:
Then using 'em in javascript with
Once you've defined your own Factory, you can hijack "important" urls (eg. for rewriting), and leave common to the Url helper implementation.
However for having this fully client side, there's an extra step of rendering a Js routing context, for accessing client side variables.
EDIT: As promised my very simple Url class builder:
in-spite of injecting javascript in views i rather prefer - let HTML do its job and javascript do its. Below is the pattern.
For Links
//Controller
This way both type of users can be handled javascript enabled and javascript disabled.
Same can be done for forms.