To just answer your question, yes, I look at both of the examples that you specified as "hardcoded". Second, @ Url.Action LESS is hard-coded . This implies less specificity. If you change the root of your project, the second will work, and the first will break, as mentioned in @Peter J. In addition, I believe that the second will work if you use regions and change the name of the region, and the first will break.
To be a little more useful, I use the third approach. I had exactly your question a month ago, and thanks to ASP.NET MVC AJAX calls without static controller URLs (magic strings) I have a process that works fine for me.
Index.cshtml
<input data-action='@Url.Action(Mvc.AutoComplete.PostalCode())' type='text' name='postalCode' class='autoComplete'><input> <input data-action='@Url.Action(Mvc.AutoComplete.ProductCategory())' type='text' name='productCategory' class='autoComplete'><input>
main.js
$('input.autoComplete').each(function () { var el = $(this); el.autocomplete({source: el.data('action')}); });
Voila! Compile-time verification and clear separation of responsibilities using T4MVC and HTML5 data attributes. The controller definition is read from the widget that uses it. Great for partial views that may appear several times on a page.
I highly recommend using T4MVC, which is "Mvc". The syntax you see in the example. If you are trying to avoid hard coding, it is about as dynamic as you can do it. I use T4MVC ( http://t4mvc.codeplex.com/ ), so I can avoid the "magic lines" to refer to controllers and actions in my views. T4MVC is not perfect, but it is a big improvement. There are still hardcoded values inside the hidden T4MVC files, but you will never see them, they are automatically generated from your controllers and the compilation time is checked.
Also, as @Valamas already suggested here, I then use the data attributes for the HTML elements to pass these URLs from my views into javascript.
I especially use this approach to data attributes when I have AJAX requests on my page. One page can easily have 10 URL dependencies, and it's hard to tell when links are broken by user testing, which may not have the full coverage of conditional functions. But hooray! T4MVC throws errors at compilation time when links do not exist, and if your code is organized with all checks of data attributes in init, javascript throws errors at loading when there are no corresponding data attributes (and you will not receive runtime errors for variables undefined). This offers much earlier / easier detection of grip defects, even if you are not testing the javascript block (and I do not).
Usually I have a standard heading on every page that includes current globally useful information (e.g. UserId) as data attributes of a BODY element or on the display: there is no SPAN with a known identifier.
Then, as a rule, I load all the data from the attributes in one place at the top of my javascript code (or every javascript file that it needs).
What is the advantage of this? Now you have one place to see that all the necessary built-in data parameters are provided to your javascript. Your javascript does not reference undefined variables, so if you use the javascript IDE, you will not get false errors. Developers looking at your javascript don't scratch their heads trying to find the mystery variable declaration in other javascript files; especially troublesome when they are not ASP.NET MVC developers. In this note, if you have separate language commands, implementation responsibilities are clearer (javascript developers do not change your views when they change naming conventions or vice versa). In addition, variables are defined at a well-known time during the life cycle of the client page, which is a big advantage for javascript debugging. And your view does not contain javascript spattered all over the page, where a slight HTML defect on the middle page can unexpectedly cause javascript to crash completely.
In addition, as shown in the example, this is the only way to fly for partial views that may occur more than once on a page. You can clearly associate embedded data with individual HTML widgets that use it. If you connected javascript directly to the view, you mistakenly redefined the variables.
The list of benefits goes on and on, but basically it comes down to sharing responsibilities. Everything else follows from this.