ASP.NET 5 (vNext) Work in Progress - Exploring TagHelpers
TagHelpers are a new feature of ASP.NET 5 (formerly and colloquially ASP.NET vNext) but it's taken me (and others) some time to fully digest them and what they mean.
Note that this, and all of ASP.NET 5 is a work in progress. TagHelpers can and will change. There is NO tooling support in Visual Studio for them, as they are changing day to day, so just be aware. That's why this post (and series is called Work in Progress.)
Historically we've used HtmlHelpers within a Razor View, so when you wanted a Label or a TextBox you'd do this. This is from the ASP.NET 5 Starter Web example.
<li>@Html.ActionLink("Home", "Index", "Home")</li>
There you have some HTML, then we start some C# with @ and then switch out. It's inline C#, calling a function that will return HTML.
Here's the same thing, using a TagHelper.
<li><a controller="Home" action="Index">Home</a></li>
The source for TagHelpers is (as with all ASP.NET source) up on GitHub, here. This is an anchor, A, so it'll be in AnchorTagHelper. The code is very simple, in fact, gets a collection of attributes and decides which to act upon.
In this case, "controller" and "action" are not HTML5 attributes, but rather ones that ASP.NET is looking for.
Question for You - Would you rather have these attributes and ones like them (including your own) be prefixed? Perhaps asp:controller or asp-controller? That's an open issue you can comment on! You could do [HtmlAttributeName("asp:whatever")] on a property or [TagName("foo")] for a tag if you liked.
How do these attributes get mapped to a TagHelper? Well, an attribute name is mapped directly to a C# property and automatically injected. See how AnchorTagHelper has public properties Action and Controller?
It's important to note that this isn't the second coming of WebForms controls, while the possible asp:foo syntax may look familiar (even though a prefix is optional.) This is more like syntactic sugar that gives you a compact way to express your intent. It doesn't give you any "control lifecycle" or anything like that.
Personally, I'd love to see them look different in the editor. For example, rather than
I'd like to see italics, or maybe a desaturation to show what's server-side and what's not, which will be super important if I'm NOT using a prefix to distinguish my attributes.
The code below in this Before and After results in the same HTML and the same behavior. A nice aspect of TagHelpers it that you avoid the context switch from markup to C#.
Here is another example, a login partial form, before...
@using System.Security.Principal
@if (User.Identity.IsAuthenticated)
{
using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" }))
{
@Html.AntiForgeryToken()
<ul class="nav navbar-nav navbar-right">
<li>
@Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Manage", "Account", routeValues: null, htmlAttributes: new { title = "Manage" })
</li>
<li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li>
</ul>
}
}
else
{
<ul class="nav navbar-nav navbar-right">
<li>@Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" })</li>
<li>@Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li>
</ul>
}
and after...with the Microsoft.AspNet.Mvc.TagHelpers package added in project.json and then @addtaghelper "MyAssemblyName" in either your ViewStart.cshtml to get this in all views, or separately within a single view page.
@using System.Security.Principal
@if (User.Identity.IsAuthenticated)
{
<form method="post" controller="Account" action="LogOff" id="logoutForm" class="navbar-right">
<ul class="nav navbar-nav navbar-right">
<li>
<a controller="Account" action="Manage" title="Manage">Hello @User.Identity.GetUserName()!</a>
</li>
<li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li>
</ul>
</form>
}
else
{
<ul class="nav navbar-nav navbar-right">
<li><a id="registerLink" controller="Account" action="Register">Register</a></li>
<li><a id="loginLink" controller="Account" action="Login">Log in</a></li>
</ul>
}
This makes for much cleaner markup-focused Views. Note that this Sample is a spike that Damian Edwards has on his GitHub, but you have TagHelpers in the Beta 1 build included with Visual Studio 2015 preview or OmniSharp. Get involved!
Remember also to check out http://www.asp.net/vnext and subscribe to my YouTube Channel and this playlist of the ASP.NET Weekly Community Standup. In this episode we talked about TagHelpers in depth!
Related Posts
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
* defintely would want this prefixed to avoid clashes with other tags and for easy recognition (I like the idea of different styles in the IDE!). From a consistency point of view a simple @ prefix would lend itself as it is already a the prefix for any server side releavant items
* are these tags rendered on the client side? if not do we have an option to carry them on to the client side?
* I'm wondering though whether we need to have the separate controller tag, wouldn't a simple punctuated qualification like action="controller.action" be shorter and easier to read?
* you mention the relation between tag name and class that implements it. How would we go about providing the same funcitonality to a number of different tags?
Thanks!
< a action="index" target="_blank" controller="home" >
I love the idea of knowing exactly which method/constructor is being called when I use Razor (eg. @Html.DoSomethingThatICanDebugEasily() ), but having to remember what TagHelper maps to what tags seems like it could be a bit of cognitive overload (especially on larger apps).
Maybe something that still embraces the @ symbol?
< @MyNamespace.TagHelper(new { option1 = "optionVal" }) html-attribute-1="attribute-val" >
Once you introduce this syntax back into the platform its only a matter of time before devs start adding back all the stuff from Web Forms that they were fond of.
BTW, Mr. Hanselman, you're one of my favorite authors in tech! It had to be said ... ;)
Standard HTML "data-" attributes should be preferred for prefixing along with "ASP" specific string to distinguish.
e.g.:
... a data-asp-controller="" data-asp-action="" ...
This will feel more natural, semantic and play along nicely with HTML. Although a little verbose, I feel this should be the way forward rather than obscure custom prefixes. Without prefixes it just feels like webforms.
Just my opinion.
Can we use data-asp-... ?
It'll save a lot of trouble with custom HTML tags and attributes in the future, and make it more obvious where code is coming from if you're not using Visual Studio with some tool like Resharper.
Also, I've asked this before and I know there is no tooling yet, but please consider having a way to provide custom intellisense for a taghelper (like for cms keys or whatever) beeing able to supply squiggles would also be awesome :)
Is the tooling in general open source as well by the way? I looked in the repos but I wasn't able to find it
what about all the other attributes one can add to a tag ? Are they sent "as is" to the client ? Does the tag helper see them ? Can you have different tag helpers bound to the same tag? What would happen then ?
I'd like to see a prefix on the attributes, one like data-asp-*. In that way the page is always valid HTML5, before and after rendering.
For example in case a helper for a certain tag doesn't exist, the html at the client side just contains an valid data-* attribute.
In my opinion the best solution is the implementation of the validation of of href and controller-action relationship.
It seems that multiple custom tags - is not the best solution, and I would like to avoid them as much as possible.
All of these methods just return the href on the client side.
In my opinion the best solution is the implementation of the validation of href and controller-action conformity in IDE, when developer write "href" tag.
It seems that multiple custom tags - is not the best solution, and I would like to avoid them as much as possible.
IMHO razor syntax is good enough for today and tomorrow web techs. I would be better if MS will focus on things like:
- performance (small sites should run fast and need less memory)
- portability (i want to run simple sites on cheap linux hosting, and deploy using web deploy:)
- make iis faster
- more diagnostic tool for asp.net mvc, and iis
T4MVC all day!
< a href="@MVC.Home.Index()">Index</ a>
In other cass I would like to see some prefix, just @. We all know @ stands for serverside code. No need to compete with real html attributes. No confusion.
// Ryan
< a href="@Home.Index()">Home</a>
Today I use:
< a href="@Url.RouteUrl("Home")">Home</a>
It's still shorter and more readable than:
< a controller="Home" action="Index">Home</a>
I don't use controller/action routes that much, but instead give my actions a name using attribute based routing.
Both asp-controller or asp:controller would do. I personally prefer the first one as people won't confuse it with previous WebForms stuff.
imho they're screaming for a fluent interface and always have been. Something like the FluentHtmlHelpers class in contrib, but without insisting on a different page inheritance.
[/my2pworth]
You could use <asp:controller> or runat="server" but then you've just come full-circle and re-invented server side tags.
If the Tag Helpers get color coded in the IDE, would that cause confusion with developers with color vision issues (i.e. me)?
With that being said, I would rather see a dot notation syntax such as Home.Index() that is fluently-driven.
controller="@Account" action="@Manage" title="Manage" and then make @Account, @Manage yellow in the IDE
asp-href="Home/Index" would be my suggestion.
or even
asp-href="Products/Edit/1234#description"
If we're going to go down this route, let's really put the server to work. The server knows how to parse a url like above and can take what I write and spit out a fully qualified url. This could really come in handy when using areas. My view no longer has to know what area it is in. The server could determine that for me (or maybe I'm just really wrong about that).
Also what is the plan for using url parameters with this approach? I guess you could do something like: @controller = "Widget" @action = "Details" @parameters = new { Id = 123 } ?
What if I don't want my labels, anchors, etc. to go through all of the tag helper code / pipeline, I only want my anchors to be rendered to the client as normal?
Really simple demo video here
I'm sure the syntax could be simplified even further, and maybe even remove the need for the t4 generated files altogether?
I would want a complete different tag. Having the same html markup like an anchor tag with only different attributes is going to lead to a lot of "what am I missing, it's right in front of me"-like debugging.
My $0.02
Thanks
What happens if I do something like < a controller="Home" action="Index" href="foo">Home< /a>? Would the controller and action override the href or would the href take precedence?
Can I specify variables in these attributes e.g. < a action="@prevAction">?
How would route values be provided using tag helpers?
If I were making the call, I would keep the @ syntax and add in the tag helpers with namespace prefixes ala JSTL (https://jstl.java.net/)
Also, for prefix suggestions: @- is not currently valid in Razor it seems. It would feel enough like data- and its ilk that it would feel somewhat reasonable for HTML5:
<a @-action="Index" @-controller="Home">
Not a fan - for the same reasons already outlined
- Hard to distinguish between client side / server side
- Too magical if something isn't working
- Parameters don't look like they'd come out nicely
The < a href="@Account.Manage()">Hello @User.Identity.GetUserName()!< /a> syntax fixes all of that.
Plus they work nicely with BuildViews=true and can work nicely with refactoring (not saying TagHelpers won't, it just doesn't seem likely)
< a href="@Url.Map(controllerName, actionName[, parametersDictionary])">link text< /a>
makes a lot more sense. The designers and junior devs know which part is HTML, which is code, and it's clean and expressive.
This also invites plugins which have TagHelpers for generating markup for Angular or JSX for example. It also means we don't need to keep creating more HTMLHelper extensions for every new web component that needs some server data to render.
Regarding the prefixing, the tag itself should have a prefix eg @<a controller= so that it's easy to tell when the markup has "opted in" to a TagHelper. Prefably configurable of course so we can choose!
It is effectively pure markup, but that markup is now being altered in ways my eyes would probably miss if I'm not careful. The rendering engine would remove the "controller" and "action" attributes and add an "href" in their place? What's wrong with using what we want?
ie plain old href and helpers for determining the url?
Unnecessary complication.
It's not even syntactic sugar - it's syntactic liver.
I can see why you don't want prefix, and I hope you see why attributes not showing which is on server and which conflicts with client side etc is a problem.
I wonder how many designers vs developers use Razor. Razor is code focused. It's designed to be so and people used it as so. If I wanted a markup focused thing, I'd look at Spark View Engine. Likewise, if you wanted to make Razor more markup focused, you'd look at what Spark View Engine did in that area. However, that markup thingy didn't fly too high obviously so why bother?
And similarly, if we all wanted to embrace the code focus of Razor rather than reduce it, we'd be looking at something like HtmlTags, which Damian seems to refuse to check (I asked him wehther he did, he said no).
I hope someone is listening to these comments, and I mean thoughtfully.
Thanks for trying to solve the silly links and forms syntax though.
I think there is not need for the TagHelper rather we need to get rid of the magical string for controller and action name. It would be great if it could be replaced with some sort of lambdas.
I can see bugs created by generic attribute names. With the below code, the server vs client code is clear:
< a href="@MVC.Dinners.Delete" data-id="@MVC.Model.Id" foo="@MVC.Model.MyFoo" bar="7" alt="Just better" target="@MVC.Model.TargetType">@MVC.Model.LinkName - Go!</ a>
I love what MS are doing these days but this is one of those cases where they are making a feature desperately searching for a problem.
I already have a hard enough time explaining what HTML is vs what asp.net code is to students. We don't really need additional "magic" to confuse the matter further
Cheers
like this
@using prefix=Asp.TagHelper;
so one can choose the prefix it wants, or no prefix at all to have all automatic?
for example it could be
@using prefix=Asp.TagHelper;
<prefix:a href="link.html" prefix:controller="Home">Link</a>
and it could also be
@using Asp.TagHelper
< a href="link.html" controller="Home">Link</a>
Or withaout opting Tag Helper in, simply and plain HTML
< a href="link.html" >Link</a> @*it is the plain anchor tag because no helper was opted in*@
Also, make the prefix use a colon, not a dash: dashes are used in all client side libraries that define custom attributes (see Angular), so seeing a colon quickly helps to understand it's server side stuff. But please use something else than asp:controller, it might alienate developers who thought the old classic asp had finally died! Go for mvc: or razor: or rzr: or something like that.
And whats the workflow to figuring out if and what TagHelpers will be invoked in this given context and what properties they have and what they mean. Making Intellisense work for this seems clumsy, and how is typesafety and refactoring going to catch if a property is being renamed or removed on a TagHelper?
HtmlHelpers as method calls is the way to go IMO.
I definitely like < a @controller="Home" @action="Index">Home< /a> or < a @action="Home.Index">Home< /a> as suggested above... I'd like keeping the "@" symbol as a Razor thingie.
I am wondering how well tag helpers will handle selects and options, though....
I have to admit that i dislike the whole idea less after letting it sink in, but i agree with everyone asking for a explicit prefix for either the whole tag or each attribute.
The prefix would also solve the issue of separation between standard HTML5 attributes and TagHelpers.
Many have been bashing WebForms in favor of MVC and, all the time, running to WebForms.
Done great things in the past with tag mapping in WebForms.
Prefixes makes it easier to see what belongs to HTML and what is added to it.
I think @ will be better as the prefix of tagHelper property, because @ is already belongs to Razor syntax. or at least it should be optional for developers to have @ as prefix for tagHepers.
If i will write an anchor tag as < a id="registerLink" @controller="Account" @action="Register" data-wz-animate="zoomOut">Register< /a> will also allow others to differentiate among Html, angular and Razor attributes.
From one of Asp.net Weekly Community Standup, I remembered, tagHelpers are being introduced because of data- prefix and anuglar directives attributes are hard to write with the "Razor syntax" like @Html.Action("Home", "Index", new { data_wz_animate="zoomOut") and also looks odd. So the solution should be resemble to Razor syntax.
Many developers are still naming their ID and class with pascal case naming (because of web forms and win forms convention) instead separating words in ID and class names by a hyphen ID and Class Name Delimiters.
Current HtmlHelpers are clean and simple and explicit that something is Razor code.
Thus it would be possible to have "virtual" tags that would translate to one or more real tags (or even none if we decide so)
For links, it would be nice if controller and action would validate against actual action. Maybe something like : ControllerName, x => x.Action(p1, p2, p3).
And it should also update with refactoring if the method or controller is renamed.
Since routes are all defined inside the same project, the tooling could figure out which paths are valid and which are not. It could provide intellisense (aka a list of all valid routes) when you open an href-attribute. The list of possible values, should obviously include MVC-routes, Web api routes, static files and the bunch.
This makes it effectively what you see is what you get, and at the same time provides help to the developers.
I'm not saying this is easy, I'm saying how I'd like it :-)
Since I'm in asking mode, it would be nice if when you rename an action, the tooling could figure out which href-attributes are affected and rewrite them as well.
The only issue I see is with virtual directories, but you could do something with a prefix like href="*/some/path/that/is/not/recognized" or something similar.
If attributes were prefixed with the @ (ex: @controller="foo") the yellow highlight on the @ char would be enough, and no desaturation of asp attributes were need.
Regards
< a @action="Account.Login">Login< /a>
This is how I see a links)
new {id=1, param2=x, param3=y}
Also, how would attribute based routing fit into this? There may not be a controller or action defined. There may however be a route name.
BTW I like existing Html helper. The main problem I have with Html helper is the crazy number of overloads that still don't cover all the combinations (see questions on SO about folks want to add form attributes with @Html.BeginForm). I think some of the issues with the existing Html helper could be solved by adding an overload for each tag that uses optional parameters. That would be the one and only overload (per tag) that folks would ever need.
1: Code is written to be read and debugged. It should be obvious at a glance whether something is client or server-side. A prefix would begin to help this issue, but only solves the property side of the equation, not setting a value. You're already going to have @blah statements in the code as values are output, so it would make the most sense to us a @ prefix on the server-side attributes as well, as we have already trained our eyes to look for those when reading razor templates.
2: This method is parsing client-side code, interpreting it, and then outputting new client-side code. I don't want the engine to alter my client-side code. That's why I chose to use client-side code instead of helpers. I don't want to have to go back into the Web Forms mode of wondering whether the HTML/tags I think I am outputting are the ones that are actually being sent to browsers, in case someone tries to be helpful again and alter my content mid-stream for "better compatibility". Or a new attribute is created that collides with the ones that ASP.Net is specifically looking for. Or I'm not writing HTML at all and run into collisions/errors due to the system assuming I only ever outputting HTML.
3: A later error or difference introduced into this parsing and output is going to introduce bugs into stable, production applications (since it is transforming code for the client instead of just evaluating tokens and code sections)
4: It will be inconsistent. Some of these things are attributes, but a lot more of them are attribute values. So back to the @prefix, instead of having 2 methods of identifying server-side items, you would have one. And at that point, why even make it look like an attribute? Why not have an anchor tag with @Mvc.HrefFromAction('controller','action') inline in it? All the HTML, with sprinkled output methods that generate just a single clientside attribute and value (and don't require evaluating all of the attributes and determining which ones have special meaning and which get passthrough).
If the answer is "You Can't" then what's point of tag helpers? Why not use static html?
I would say having a prefix would help it to not get confused with HTML attributes for developers who are not using VS.
But more importantly could you guys do something to remove the magic strings and support the way of T4MVC (as a standard across all .NET languages)? Pretty please! :)
Interestingly no one from the team seems to be helping with the confusion as well. Just cracking through the other issues and *looking like* this one is ignored.
I know it's optional and all, but optional could always be an excuse for bloat.
@{
var linkA = Url.Action("DoSomethingA","ControllerA");
var linkB = Url.Action("DoSomethingB","ControllerB");
}
< a href="@linkA" > do something A </ a>
< a href="@linkB" > do something B </ a>
Why not just declare variables on top of a view .cshtml and use them like shown above? Easier to read, understand, refactor, debug, and maintain.
Better yet, can we have such syntax that support refactoring and intellisense?
< a href="@ControllerA.DoSomethingA" > do something A </ a>If we can do it on Model, why not on Controller? Framework should help a developer more productive by taking care of such boilerplate codes. Framework should not force a developer to type boilerplate codes (be it C# or XML/HTML attributes) again and again.
TagHelpers are not 'Convention over Configuration'. It is going backward to configuration over convention. I personally do not want to type 'controller', 'action' again and again inside every hyperlink. It does not add any value.
Imagine seeing multiple framework's custom 'tag helper' attributes inside one single HTML tag (ASP.NET MVC, Angular JS, etc)...I see spaghetti codes.
eg:
< a ...>
<a:bootstrap:tooltip tooltip="this is a tooltip" position="top" />
<a:bootstrap:style class="btn-sm btn-warn" />
<a:mvc:routing controller="someController" action="someAction" />
etc.
< /a>
This: @Html.ActionLink("Home", "Index", "Home")
can be written as: < a href="Home/Index">Home</ a>
This: < a controller="Home" action="Index">Home</ a>
can be written as: < a href="Home/Index">Home</ a>
This:
<form method="post" controller="Account" action="LogOff" id="logoutForm" class="navbar-right">
can be written as this:
<form method="post" action="Account/LogOff" id="logoutForm" class="navbar-right">
If you want a dynamic href/action then just define a variable:
@{
var path = "Account/Logoff";
}
< li>< a href="@path">Home</ a></ li>
<form method="post" action="@path" id="logoutForm" class="navbar-right">
You shouldn't be hard coding the url. Your example could be changed to:
< a href="@Url.Action("Index", "Home")">Home</ a>
This allows you to update your routes and the urls will automatically be updated. However the anchor tag is not the best example of where this shines. Image a textbox like:
@Html.TextBoxFor(m => m.Name, new { id = "name", @class = "name", data_title = "Title Here" })
This could be rewritten as:
<input class="name" data-title="Title Here" for="Name" id="name" type="text" />
This has a bunch of improvements:
- You don't have to use an anonymous object to specify the attributes
- You don't have issues with c# keywords such as "class"
- You would get intellisense for the classes from your style sheet
- You don't have to deal with underscore hack to specify HTML 5 data attributes
- It's a lot more readable and looks more like the HTML that's rendered
Hope this makes things a little clearer.
What we need is compile time checked routes, at least for the simple cases. Like T4MVC
It would be a mistake to try to add something which is ´Angular like´, as Angular itself is moving away from this in version 2 anyway. For example, the proposed syntax is now:
<div [ng-repeat|todo]="todosOf('good')">
and
<button (click)="deleteTodo(todo)">
So, it is going to be messy anyway...
Microsoft should really step back and stop chasing open source web development trends, which are complete chaos - start making the trends yourself! Think of the best way to do it, make it opinionated, coherent within the Microsoft toolset, and extensible. Visual Studio 2015 with NuGet, but then Bower, NPM, Grunt, etc - is already shaping up to be an embarrassment, as many people are already moving on to other Next Big Things (for this week).
Dont make life difficult for your existing customers, in a plaintive attempt to chase after a few more new customers, who are already hostile to Microsoft. Copy what they have already, and they will ignore you. Build something better, and they will come.
Let use stick to being able to see whats code and whats html without highlighting
Keep things simple. Make the syntax simpler not more complicated.
We don't need more server side stuff inside markup. Build better helpers with a human API.
Please do note fix what is not broken.
Microsoft should really step back and stop chasing open source web development trends, which are complete chaos - start making the trends yourself! Think of the best way to do it, make it opinionated, coherent within the Microsoft toolset, and extensible. Visual Studio 2015 with NuGet, but then Bower, NPM, Grunt, etc - is already shaping up to be an embarrassment, as many people are already moving on to other Next Big Things (for this week).
Dont make life difficult for your existing customers, in a plaintive attempt to chase after a few more new customers, who are already hostile to Microsoft. Copy what they have already, and they will ignore you. Build something better, and they will come.
Well put! That is exactly what this feels like to me. As an ASP.NET MVC dev for about 4 years, I look at vNext and think WTF? There's a whole lotta change here - some good (xcopy deployable .NET core) and some questionable (taghelpers). This much change risks alienating existing MVC devs.
If Microsoft can somehow successfully keep their current crop of MVC devs happy while reaching across to the hostile, non-MS web devs - well more power to them. I'm skeptical though. I observed a similar attempt with WinRT to woo MS hostile devs with a Html/JavaScript/CSS stack. I'm not sure that strategy paid off. The Windows Store doesn't seem particularly healthy to me and from what I've heard, north of 80% of store apps are written in C#/XAML.
I do think it would be helpful to have a prefix, I lean towards "@" prefix, it just kinda feels right. From my experiences with angular it is nice to know to start with "ng-". I also think the desaturation and/or italics are a good idea to separate the code from the client side html.
I vote for adopting the Fubu HtmlTags library: http://htmltags.fubu-project.org/
It leverages the best of a strongly-typed language with configurable conventions and instead of returning a plain string (primitive obsession) it returns a rich HtmlTag type with a fluent API that reads like jQuery, something with wich a lot of front-end devs are now familiar.
Color coding in the editor is nice, but it's not enough. I think prefixes or namespaces should be used. Namespaces are maybe too much, because they involve changing the page root/declarations, and views are usually coded on conventions.
"asp-" prefix are fine for me.
< a .controller="Home" .action="Index">
Shows quite nicely in my unbiased opinion ;-) that this is a tag helper member rather than an html attribute.
Would it make more sense to add attributes in a single property?
< a server="{Controller: "Home, Action: "Index"}">Home< /a>
It's already hard to read HTML and guess what will be left in the client, this will make it much, much worse. Don't do it!
What I would like is for HtmlHelpers be Strongly typed, I like not to be able to enter the wrong code, and at least be notified if it is wrong.
I love the @helper in MVC. The only thing i hate is, the requirement to put the .cshtml/.vbhtml file in the App_Code folder. I would love it, if i could add that files any where. (e.g. /Views/Helpers/MyHelper.cshtml).
Any new about that? Shouldn't be impossible with Roslyn now...
please don't make a mess again like webforms
keep MVC neat & clean please
If you are going to make changes to how Razor views are generated, it needs to be something that is strongly-typed. The helpers from MVC Futures were closer than these string-based solutions. Let me repeat that: Razor needs *fewer* strings, not more.
C# is statically typed. Let's use that to our advantage.
In my opinion, a key point about writing great HTML is understanding exactly what your markup does. Filling up a bunch of magic attributes in the view is a step in the opposite direction.
As an alternative, I would propose simplifying HTML helpers. Generating HTML in them is a bit awkward because of mixing method code with markup.
How about introducing a concept of "HTML templates with placeholders", where you'd (1) put all the HTML you want, (2) sprinkle the necessary placeholders here and there, then (3) call that from an HTML helper? Something along the line of T4. This would keep concerns cleanly separated.
Another vote for: Skip the TagHelper and just use something like Fubu HtmlTags to make HtmlHelpers better, rather than try to make everything look like HTML.
Another vote for: If you must do TagHelpers, yes, please use a prefix. I agree that "@" would be nice if you can make it work.
know-how.
Comments are closed.
how about < a asp-href="Home.Index()">Index</ a>