views:

790

answers:

6

It is quite possible that I may not have got the point, but I really can't figure out how ASP.Net MVC's HTML Helpers can help me. Here's a sample: -

HTML:

<a href="ActionName" target="_blank">Click Me</a>

HTML Helper:

<%= Html.ActionLink("Click me", "ActionName", null, new {target="blank"}) %>

My eyes are reading HTML more easily, and it seems counter-intuitive to use the HTML helpers.

Look at the following arguments:

  • A lot of people (even novices) know how to read HTML. The HTML helper syntax can confuse easily.
  • In many cases you need to do more typing writing an HTML 'helper', then you need to write the actual HTML.
  • The HTML helper is going to spew real HTML anyway, so why not write HTML directly?
  • Writing HTML gives you more control over the syntax, and the standards. You can make in confirming to whatever HTML standard you want.

Are there any special compelling reasons that I have not understood (since I am self-educated in MVC and there could be gaps) that should make me want to prefer HTML Helpers?

Or are they just code noise?

+8  A: 

The primary reason you don't use <a> tags directly is that you don't want to hardcode URLs in your application. The Html.ActionLink method will abstract away the URL generation and you'll specify the controller, action, and other parameters.

So, basically, the two lines you posted in your question are not really equivalent. You should consider adding the dynamic URL generation code to the <a> tag to make them functionally equivalent. Beside that, if you output HTML directly, you'll have to be extremely careful about HTML encoding stuff. Html.ActionLink will do this job for you too.

Mehrdad Afshari
Youu can still use <a> tags and keep the URL dynamic (non-hardcoded) by doing <%= Model.LinkUrl %> or <%= MyUrlProvider.Someurl %> inside the href attribute.
Alex
I've been hard-coding URLs this way <a href='./home/login/'>login</a>. What could go wrong? Also what are the other HTML helpers for apart from action-link?
Cyril Gupta
@Cyril: What if you reorganize your site so there is another level, like "/company/home/login"? You'd have to go through manually and change your links, instead of in one centralized location.
womp
@Cyril: What if the URL contained some parameters? For example, SO generates dynamic URL for each question. You are not able to hardcode it. @Alex: Don't forget the need to sanitize inputs or you'll be vulnerable to XSS attacks.
Mehrdad Afshari
For parameters i use generated URLs, the approach prescribed by Alex.
Cyril Gupta
@Cyril: As I said, adding textual parameters adds the need for HTML encoding. Additionally, a single view file might be referenced by different actions from different URLs so relative URLs may not work.
Mehrdad Afshari
+1 Mehrdad for being so informative (though I did that yesterday itself)
Cyril Gupta
URLs that are generated with ActionLink also respect the routes you have set up in Global.asax.
Robert Harvey
+8  A: 

lets say that you have many query parameters in the url like

site.com?a=1&b=2&c=3&d=4&e=1&f=1

<%= Html.ActionLink("Click me", "ActionName", null, new {a=1, b=2, c=3, d=4, e=1, f=1}) %>

The actionlink can build this url for you. if you didn't have the helper you would have to manually add keys and vlaues to the url. And this is a real pain. The url helper can also match url routes too.

+1 for this very good instance of a "for" rather than an "against."
Funka
+2  A: 

For what HTML Helpers can do (not just ActionLink), check out this. How would you do that will just HTML?

Martin
+1 to you and Charlino for this rad implementation.
Cyril Gupta
+4  A: 

Even better, use MvcContrib and ditch the error prone "magic strings" and replace them with lambdas.

<%= Html.ActionLink<MyController>(x => x.ActionName() ,"Click me",new {target="blank"}) %>
mxmissile
Yes I saw the interesting 'fluent html'. But seriously, that's absolutely for geeks! Though I am a self-confessed one, they make me very afraid. They don't look so readable.
Cyril Gupta
Using the lambda expressions might cause problems because of the [ActionName("..")] attribute. IMHO it's better to avoid them.
stej
gotta love *more* magic strings...
mxmissile
A: 

Actually, there's no big difference between

<a href="ActionName" target="_blank">Click Me</a>

and

<%= Html.ActionLink("Click me", "ActionName", null, new {target="blank"}) %>

because in both cases you're hardcoding (URL in the first, action name in the latter).

That's why I create specific helper methods for links, and then I use

<%= Html.LinkSomeAction("Click me") %>

This way I'm sure that when I'll change my mind on which name the action should have, I'll be fine; also, I'll never have to worry about misstyping action names or links.

The solution proposed by mxmissile is also good.

giorgian
This could lead to a lot of un-necessary method overloading, what if you wanted to add css classes or control the data that gets generated in the route. Your action names should not be changing that much, IMO. Action names should be meaningful and routes should be helpful for users.
Kyle LeNeau
+1  A: 

The biggest reason is dynamic nature of RESTful URL's. Consider this HTML code:

<a href="products/list/all">all products</a>

Let's say this link appears in the given link as well (products/list/all). When you click that link again it will take you to:

products/list/all/products/list/all

See? The obvious solution is to prepend every URL with a forward slash to make them absolute. However in that case you lose the ability to host your web site under a subdirectory.

Html.ActionLink uses RequestContext object to produce correct action links regardless which context you're in.

ssg