To simply answer your question, yes, I consider both of the examples you listed "hardcoded". The second, @Url.Action is LESS hard-coded. It has less specificity implied. If you changed the root of your project, the second one would still work, while the first would break as mentioned by @Peter J. Also, I suppose the second would work if you were using areas and changed the area name, while the first would break.
To maybe be a little more helpful, though, I use a 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 really well 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 checking and clear separation of responsibility via T4MVC and HTML5 data attributes. The controller definition is read from the widget that uses it. Great for partial views that might appear multiple times on a page.
I highly recommend using T4MVC, which is the "Mvc." syntax you see in the example view. If you are trying to avoid 'hard-coding', that's about as dynamic as you can get for this. I use T4MVC ( http://t4mvc.codeplex.com/ ) so I can avoid "magic strings" to refer to controllers and actions in my views. T4MVC isn't perfect, but it's a big improvement. Inside of hidden T4MVC files, there's still hard-coded values, but you never see them, they get generated automatically from your controllers, and get compile-time checked.
Also, as has already been suggested here by @Valamas, I then use data attributes on HTML elements to pass those URLs from my views to javascript.
I especially use this data-attribute approach when I have AJAX calls on my page. A single page might easily have 10 URL dependencies, and it's hard to tell when the links are broken by user-testing that might not have full coverage of conditional features. But, hooray! T4MVC throws compile-time errors when the links don't exist, and if your code is organized with all the data attribute inspections in init, javascript throws load-time errors when the corresponding data attributes are missing (rather than the run-time errors you would get for undefined variables). This offers much earlier/easier detection of linkage defects, even if you aren't unit testing your javascript (and I don't).
I usually have a standard header on every page that includes the current globally-useful information (UserId, for example) as data attributes on the BODY element, or on a display:none SPAN with a well-known ID.
Then, I will typically load all of the data from attributes at a single location near the top of my javascript code (or each javascript file that needs it).
What is the benefit of this? Now you have a single place to look to make sure all of the embedded data parameters required are provided to your javascript. Your javascript doesn't reference variables that are undefined, so if you use a javascript IDE you won't get false errors. Developers looking at your javascript don't scratch their heads trying to find the declaration of the mystery variable in other javascript files; especially troublesome when they aren't also ASP.NET MVC developers. On that note, if you have separate language teams, the implementation responsibilities are clearer (your javascript developers don't come edit your views when they change naming conventions, or the converse). Also, variables are defined at a well-known point-in-time during the client page lifecycle, which is a big benefit for debugging javascript. And your view doesn't contain javascript splattered all over the page, where a minor mid-page HTML defect may unexpectedly result in a complete javascript failure.
Additionally, as shown in the example, this is the only way to fly for partial views that might occur more than once on the page. You can clearly associate the embedded data with the individual HTML widget that uses it. If you plugged in javascript directly to the view you'd be erroneously redefining variables.
The list of benefits goes on and on, but basically it comes down to a separation of responsibility. Everything else follows from that.