I'm looking at the following jQuery call:
$.get('/Home/GetResult', null, function (data) {
alert(data);
});
I see this being called the 'Hard Coded' way of doing this compared to:
$.get('@Url.Action("GetResult", "Home")', function (data) {
alert(data);
});
which I see referred to as the non hard coded way of doing this.
Could someone please explain to me what this is all about? Seems to me both ways are equally hardcoded ways of calling this because you have the explicit names of the Controller and Method in both.
Does anyone know why one is called hardcoded and the other isn't. Is one better?
jQuery prop() Method Note: The prop() method should be used to retrieve property values, e.g. DOM properties (like tagName, nodeName, defaultChecked) or your own custom made properties. Tip: To retrieve HTML attributes, use the attr() method instead. Tip: To remove a property use the removeProp() method.
jQuery get() Method get() method loads data from the server using a HTTP GET request.
jQuery post() method. The post() method is one of the commonly used HTTP methods. It is used to load a page from the server using an HTTP POST request. This method never caches the data and is generally used to send the data with the request.
If we hard code a URL then we lose the ability to later change our routing scheme. So always use URL Helper methods. If you use URL helper, the Helper method will take care of the change, You do not need to go and make the change in 100 places. Also you do not need to worry about how many ../ i have to add as the prefix when the same method is being called from a Home page and an inner page
Checkout these answers by Darin
https://stackoverflow.com/a/7492024/40521
https://stackoverflow.com/a/6454041/40521
"/Home/GetResult" is considered "hard coded" because the developer entered a configuration value directly in the code, where it is more difficult to alter in the future.
It is worse to specifically hardcode URL values because if this view (and associated controller action) is moved to another "area" within the application, "/Home/GetResult" will break. The @Url.Action method is better because will not.
I like Peter J 's answer. In addition
You should have the URL as part of the href or as an attribute on a html element.
E.g <a data-getresult="@Url.Action("GetResult", "Home")">click</a>
And then
var clickAction = $(this).attr('data-getresult');
$.get(clickAction, null, function (data) {
alert(data);
});
Wrap the above in a function and link it to a click event via the attrib name.
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.
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