On this episode of Eat Sleep Code, Scott Addie discusses the various options for creating UI components in ASP.NET Core. Scott talks about TagHelpers, View Components, and if Razor is still used in the ASP.NET Core.
00:00 Ed Charbeneau: This podcast is part of the Telerik Developer Network, Telerik by Progress.
00:17 EC: Hello and welcome to Eat Sleep Code, the Official Telerik Podcast. I'm your host Ed Charbeneau and with me today is Scott Addie. How you doing Scott?
00:26 Scott Addie: Doing great Ed, thanks for having me on the show.
00:29 EC: Thanks for coming. So today we're gonna talk a little bit about TagHelpers. Scott, you've got some great stuff lined up for us to talk about and let's start off with little introduction, tell us a little bit about you, I heard you have an exciting new job, give us a little rundown of what you're doing.
00:50 SA: Sure. So in the first week of June, I joined Microsoft working on the docs.microsoft.com team. My focus area is really ASP.NET Core which me and a couple other folks there are currently working on. We're ramping up for the ASP.NET Core 2.0 release that's coming later this year. Prior to that I was Microsoft MVP focused on visual studio development technologies. It was kind of like the transition from the MVP period into the Microsoft gig, was really nice because all of a sudden I was getting paid to do what I was doing in my free time before and I guess even better, it was stuff that I enjoyed doing and now I'm making a living doing that stuff.
01:43 EC: And you actually were not only a Microsoft MVP but a Telerik Developer Expert.
01:50 SA: That's right. So working in the enterprise, I came from the financial services industry, Kendo UI was used extensively in many of our projects and shortly before I left we were starting to get into ASP.NET Core which is when I started to research the UI for ASP.NET Core offering that you guys have and of course, as you know, there are some TagHelpers that ship with that.
02:16 EC: Yeah, we'll talk about some of those in a little bit. What type of things are you doing in your new role at Microsoft?
02:26 SA: As I kind of alluded to earlier, it's focused on developing new contents for ASP.NET Core 2.0. Just a few days ago I was wrapping up a migration guide that would show developers how to go from the 1.X releases to the 2.0 release, which is going to be a pretty important document. And something else we've been tossing around is the idea of a migration guide to go from ASP.NET proper into ASP.NET Core. The reality is there's a lot of developers out there still who haven't taken a look at ASP.NET Core, so we still need to make sure we pay attention to that audience and cater to their needs.
03:11 EC: One of the features that we're going to talk about is a brand new feature for ASP.NET Core and that is TagHelpers right?
03:20 SA: That's correct. So TagHelpers shipped with the 1.0 release, when the 1.1 release came out we saw some minor tweaks to TagHelpers, specifically being able to use view components as TagHelpers and view components are something we'll touch on later I'm sure but the ability to use view components as TagHelpers, that came in 1.1 and with this upcoming 2.0 release we'll see some other minor improvements to TagHelpers. An example there would be the Environment TagHelper, that's been around for quite a while. We're gonna see a couple of new attributes added to that, include and exclude to replace the existing names attribute.
04:09 EC: So, for developers that are currently on MVC and they're getting ready to look into ASP.NET Core, what what exactly are TagHelpers? And how did this new TagHelper way of creating HTML come about?
04:30 SA: I like to explain TagHelpers as a way of expressing server-side processing through HTML elements. For developers who have come from an AngularJS or Angular Background, I would compare these two directives or components that you have in that world when you're building a SPA, the difference here is gonna be its server-side processing that you're talking about as opposed to Angular, where you would be talking typically about client-side processing. So you're expressing again the processing through what looks like custom HTML elements or attributes in your web page but you can take it even a step further in addition to creating your own custom elements, you can add your own custom attributes that extend the behavior of an existing HTML element. An example there might be the label tag, we've all used it at some point in our HTML. Maybe you have a use case where you want to add some custom attribute to the label tag to extend the functionality of it in some way and you might come up with a convention for your prefix that you use for your attributes and that prefix might represent your company or your team name, X, Y, Z dash... Whatever the name of the attribute is.
06:02 EC: So we're able to namespace these custom attributes. That's a pretty cool feature.
06:08 SA: Exactly.
06:09 EC: So this sounds similar to HTML Helpers except for the ability to augment tags by attributes. They kinda have a similar purpose don't they? You're writing a piece of code and it's essentially outputting some HTML?
06:32 SA: Yeah. And to be clear, just because we have TagHelpers, that doesn't make HTML Helpers obsolete. Two big things I talk about here is, think about the last time you were writing C# code in a cshtml Razor view. The common complaint that I hear there is, "You know what? This feels awfully clunky. I'm really weaving in and out of HTML and C# code and that context switching is slowing me down but in addition to that it's muddying up my view, it's making it more difficult to reason about what's going on in this Razor view." The second point I wanted to touch on there was testability. HTML Helpers, sure you can unit test them if you're creating your own custom HTML Helper but they weren't necessarily designed with testability in mind, and when TagHelpers were introduced, testability was a first class citizen. It's simple to do.
07:44 EC: So let's talk about the HTML Helpers just for second. When I'm using HTML Helpers I get intellisense. So, do I see intellisense with TagHelpers as well?
08:00 SA: You do, and in fact the intellisense that you're gonna find is far superior to what you would get with HTML Helpers. Big problem with HTML Helpers is you'd commonly define an anonymous C# object that you would pass as one of the parameters in the HTML Helper. Say, "new curly braces" and inside of the "curlys" maybe you say "Class = some value." Well...
08:27 EC: Right, and that, that's not even straightforward 'cause you have to escape that class. So it's "@class = something."
08:34 SA: Exactly and that's when intellisense falls apart. The tools we have just, let's say Visual Studio for example. At that point, they just throw their hands up and say "I'd like to help you but I'm not sure exactly what you're trying to do here." And in a situation like that, that's where TagHelpers really shine because when you're building your own TagHelper, any attributes that you can use on that TagHelper are backed by a C# property that you've defined in a custom class. And because of that, intellisense is able to tell you what the available attributes or properties are on that TagHelper.
09:17 EC: So we have all over the power of HTML Helpers but instead of writing those in C# and all this escaping nonsense, we have the same functionality but we're using HTML-like syntax with elements and attributes.
09:35 SA: Yup, yup, that's it.
09:37 EC: And we get to still have our cake and eat it too, because intellisense works and not only works but better?
09:43 SA: That's right.
09:44 EC: Sign me up. [chuckle]
09:45 SA: So, I guess to summarize what we were just talking about if Razor is appealing to you and you see no problem with typing @whateverHTML., that's fine, stick with HTML Helpers, not going away. If Razor is unappealing to you and you would rather have a cshtml file with nothing but HTML syntax, TagHelpers are the way to go. But again, testability, it's far superior with TagHelpers. And the one last point I would leave you with when we're talking about TagHelpers versus HTML Helpers is think of the case where you're porting an existing application from ASP.NET proper to ASP.NET Core. Well, more than likely your boss isn't gonna be too thrilled with you if you say, "Hey, I'm gonna rewrite all of these HTML Helpers into TagHelpers just because I can." There may not be a return on investment there and this is why it's a great thing that HTML Helpers are still supported and alive and well in ASP.NET Core. It allows you to more easily port your application to the core stack.
11:07 EC: Yeah one of the things that we've been looking at as far as progress in the Telerik brand of UI components is some of our more complex controls like our grids and scheduler, they have a really nice fluent syntax for building those with HTML helpers. And you get really rich intellisense with those and there's a lot of configuration options, and those options can be really hard to remember if you don't have that fluent API where you're just typing dot and you get your next set of options that you need to set up. So we found that HTML Helpers are really really good at that and those are some of the controls that will eventually support with TagHelpers but right now they work really, really well as HTML Helpers.
12:00 EC: But then there's some of the smaller pieces of UI componentry where TagHelpers are just amazingly simple. One of my favorites for example is a control we have called the Responsive Panel. So if you've ever been on a mobile responsive website and you've got that little hamburger button and you click it, you get the fly out menu from the side. We essentially have a TagHelper that you can wrap a menu with and it immediately becomes one of those mobile responsive menu panels.
12:38 SA: Nice.
12:39 EC: And it's really cool to see that happen just by wrapping a set of HTML elements with this TagHelper, all of a sudden it's this rich piece of UI. So it's really cool to see the TagHelpers and HTML Helpers kinda combine and make those things so much easier for developers and the developer experience there. That Responsive Panel does exist in ASP.NET MVC 5, with the Telerik UI for MVC. However, it's an HTML Helper and the HTML Helper version of it, you have to start writing the HTML Helper out and then you have to set a content property up. And then all of the content that goes into the panel has to be in that content property and the escaping in and out of all of the options and stuff that need to go in there and all the content that needs to go in it.
13:40 EC: If they have HTML Helpers inside of them, then you gotta start escaping in and out of that. And then by the end of the day you're frustrated, and it's no fault of ours, it's just the way the framework works. So when.NET Core came out it's like, "Oh, it's the perfect chance for us to use a TagHelper", we can just throw all the content inside of it, and we don't get all that weird escaping in and out of stuff, it just works like HTML.
14:08 SA: Right. So you bring up a great point there. Obviously, you can create your own custom TagHelpers; we've talked about that briefly. And Telerik has something that they ship with the UI for ASP.NET Core offering. The point I wanted to make here is before you try and create your own TagHelper, take a look at what's already out there. What's been built either by a vendor or the community and you'd be surprised at what already exists. To give you an example here, there are TagHelpers out there that will allow you to easily create a Bootstrap Modal using a TagHelper. Dave Pickett, one of the Microsoft MVPs, has done a lot of work in that area. So again, don't try and reinvent the wheel. Microsoft ships roughly 17 or 18 TagHelpers with ASP.NET Core, that list is likely to continue to grow. But then as you mentioned Ed, Telerik has, for example, the Responsive Panel TagHelper. And look on GitHub, there's plenty out there to take advantage of that could save you a lot of time.
15:24 EC: Absolutely. So HTML Helpers, or TagHelpers rather, those are great for chunks of UI and reusable components. What if we have more complex things? What if it kinda has to do some fetching of a web API or something like that and we wanna reuse that throughout the site?
15:47 SA: Yeah. So that's where you would use... The recommendation would be to use view components, which is yet another new feature that was introduced with ASP.NET Core, it was there in 1.0. View components, you can think of them as that's your UI widget solution when you have any complex rendering needs. Say for example, you have a div tag associated with your widget, and that needs to be rendered dynamically based on some data that's fetched from a web API. An example I give here is calling out to current weather API and fetching the forecast for your city and state. Well, obviously there's a dynamic rendering need there, you need to build the UI based on the forecast that's returned. That's really where view components shine. Another great example here would be tag clouds; you wanna build a tag cloud based on what are the hottest topics on my blog on this given day, at this hour. You wanna build that on the fly. View component serves you well in that regard.
17:05 EC: So view component is not only the HTML portion of it, the actual view that's being rendered, but you can have some kind of custom action that runs and populates that view?
17:20 SA: Yeah. So you've got your C# class which backs your view. You're writing C# to do all of this. The thing that you should consider and we touched upon porting from ASP.NET proper to ASP.NET Core. The thing you should consider here, is child actions don't exist in ASP.NET Core. View components take their place, so keep that in mind. You might actually be forced to do some extra development when you're migrating, going from a partial view with a child action to a view component. And again view components really shine here because they're enforcing separation of concerns, which means testability is much more easily achieved.
18:11 EC: Yeah. You've mentioned testability in regards to TagHelpers and view components. This is a theme that I see running through these new ways of creating pieces of view content. What can we expect from the testability of these things?
18:33 SA: You're gonna find that it's a lot easier to test than you would think. You can more often than not just look at other open source projects and copy a few lines of boilerplate code from them and just reuse that to create your test, to set up your test. You've got your three As; arrange, act and assert. And for that arrange portion of your test you can just plop in that boilerplate code and add a few lines beneath that to actually execute your unit test. Like I said, it's a lot easier than you would think.
19:15 EC: And another thing that I think we didn't circle back on was the fact that the view components, those are written out how exactly? Because we talked about TagHelpers and Razor, and our view component's Razor, can we use a TagHelper to render those out, how are those actually added to a page?
19:37 SA: Yeah, you mentioned using view components as TagHelpers, if you're using ASP.NET Core 1.1, and let's say you absolutely love the idea of plopping a widget in your Razor view with HTML-like syntax but you have this need for dynamic processing calling out to Web API, ASP.NET Core has you covered. You would simply register your view component as a TagHelper in the view imports cshtml file, which typically lives in your views folder, you would add a add TagHelper directive in there pointing to or registering your view component, so that it can be used as a TagHelper.
20:29 EC: This is wired up automatically, I don't have to go create a custom TagHelper and wrap my view component in it or something weird like that?
20:36 SA: You don't, there is a prefix that they expect you to use out of the box unless you define otherwise. And that prefix I believe is "VC:". So if you typed "Less than VC:", followed by the name of your view component, you're at that point rendering it as a TagHelper.
20:58 EC: That's cool stuff because, I mean in ASP.NET Core 1.0 I noticed that there was either... I think it was a GitHub issue or something like that. Somebody raised, wanting a feature like this. And now in.NET 1.1, we actually have this ability to add a view component TagHelper without actually customizing anything, like it's kinda automated for us. That's really cool.
21:28 SA: It's a big step in reducing friction when you're creating your UIs.
21:34 EC: Absolutely. You've actually done some talks on this and wrote about it. One of those articles was posted on the Telerik Developer Network and there's some really good information in there. And something that we haven't touched on yet is accessibility too, that was another kind benefit of these TagHelpers, right?
22:00 SA: That's right, when we're talking about accessibility, let's say you build your own TagHelper. Accessibility is something you need to take into account when you're building that. And the reality is most developers really don't have great knowledge of what it takes to, for example, support a screen reader. I can personally tell you that if I was asked to build a website with all of the appropriate role attributes, so that it supports assistive devices, I would probably fail; just fall flat on my face. That's where these third party offerings like the Telerik TagHelpers really shine. All of those things are taken care off for you; they're abstracted away. You don't need to worry about them. Which means if I'm using one of your TagHelpers in UI for ASP.NET Core, it might be a single line of HTML code that I'm adding to my view. And if you actually open that in the Dev tools in your browser, that might be responsible, that one line might be responsible for generating 40 plus lines of markup, that abstract away all of this complexity from your development team. So the benefits are huge.
23:25 EC: Yeah. So if I'm an HTML developer, why would I use all these TagHelpers and these other nonsense that look like HTML, but they're not really, I could just put an input on the page. But then you have to know what ARIA tags or attributes to set and all the accessibility stuff that goes along with that input, right?
23:51 SA: Right. And that's unfortunately a feature that commonly doesn't get funded. A lot of the decision-makers just don't seem to see a return on investment there. The reality is there is a sizeable audience that uses assistive devices. By not taking things like this into consideration, you're missing out a large audience. It's, in my opinion, a no-brainer.
24:23 EC: Yeah, in addition too, this stuff changes very frequently. You think HTML specs change frequently, Java Script changes frequently, the Accessibility Space changes as well, and you have to keep up with that and if you're not keeping up with it then you can make an app that's not very good at accessibility features. So it's good to let other people deal with that and look at these third party sources especially... [chuckle] I'm a little bias on this one, but especially the Telerik stuff. We go through a lot of effort to make sure we're compliant and we have the right attributes on our controls so people can navigate with the keyboard, and use screen readers, and all that stuff that you probably don't wanna have to think about while you're solving your business problems. You don't wanna have to go through the effort of researching all that stuff every time you start building up a UI. And you don't wanna have to go out and find out what the latest accessibility standards are, and try to follow all the rules and all that stuff. It's already been thought of for you, you just pick up something that's canned and use it.
25:39 SA: Yup, I think it's ideal for a small shop, say you're strapped for time and you really don't have time to allow your developers, the few that you have, to look into, "What would it take to make this website accessible?" Instead, you want those developers to focus on adding business value or what the business sees as valuable. That's where offerings like this are great.
26:05 EC: Yeah, and another thing that's nice about having an abstraction like this is you don't have all of those attributes cluttering your source code, and in addition to that if there is an update in the standards, you don't have to go back and find and replace all of these things or something. Essentially, if it's something that you've written custom yourself as a TagHelper then you just go back to the TagHelper and update the source, and all your views get changed. If it's something that you've purchased or installed third party, open source even, you just go update those libraries and all those updates happen for you. You're putting everything in one place where you can update it easily. And that's something developers should be easy to get on board with.
28:30 SA: Yup, exactly.
28:33 EC: I did mention you wrote an article about this, you're doing some talks. One of those articles you can find at developer.telerik.com. What was the title of that article again?
28:45 SA: It was "Building Reusable UI Components in ASP.NET Core."
28:51 EC: We'll put a link to that in the show notes. Do you have any events coming up that you're gonna be at?
29:00 SA: Yup. I've got... Coming up in the next couple of months, I've got That Conference that's actually in a few weeks in the Wisconsin Dells. September, I'll be at the MKE DOT NET Conference in Milwaukee; actually giving a talk about what we talked about today. And then this fall, I'll be at DevReach talking about more ASP.NET Core topics.
29:25 EC: DevReach, it's close to my heart. [chuckle] DevReach is an event that we are putting on. When I say we, I mean, Progress. It's a Progress event. It's not 100% Progress tooling and Progress software talks, it's not a big vendor event. We have a lot of cool sessions about all types of different tech stuff and we're including mobile, and web, and pretty much the full stack. So we'll be out in Sofia, Bulgaria in September doing that. So it will be a lot of fun.
30:09 SA: Should be, see you there Ed.
30:12 EC: Yup. So we'll put links to That Conference and some of the other ones you mentioned, Milwaukee and all those in the show notes as well. Hopefully people get out to those events if they are, just hit up Scott Addie at those events, say hi. And I'm sure he'll be glad to talk to everybody.
30:34 SA: One other thing I'd say if you do find me out at these events and let's say you're a consumer of the ASP.NET Core documentation on docs.microsoft.com, I'm always interested in getting feedback. How can we improve and make this content more useful to you guys?
30:55 EC: Absolutely, yeah. That's what we go to these events for, right? We wanna talk to people, get feedback, find out what people are actually using and finding useful. Don't be shy, you see speakers at conferences make sure you drop a bug in our ear and tell us what you're working on.
31:15 SA: Yup. I may just have stickers for you too. There's an incentive.
31:20 EC: [chuckle] I've gotta find a spot on my laptop for some more stickers.
31:24 EC: Thing is it's wallpapered right now. I need to make room for it.
31:28 SA: There's always more room.
31:30 EC: There's always more room, you're right. Well thanks a lot Scott for coming on the show and talking about ASP.NET Core and stuff with us. We'll put some links in our show notes to everything we talked about today, so people can find you online.
31:49 SA: Thanks a lot Ed. I appreciate it.
31:51 EC: Thanks Scott.
Subscribe to be the first to get our expert-written articles and tutorials for developers!