 Want to learn how you can make your very own custom.NET template? It turns out it's actually very simple, so learn more on this episode of Visual Studio Toolbox. Hey, everyone. Welcome back to another episode of Visual Studio Toolbox. I'm your host, Leslie Richardson, and today I'm joined once again by senior PM Syed Hashimi. Welcome back. How's it going? It's going all right. It's a very sunny day in Florida right now. Coming to you from my childhood room, so I was well. Yeah, and I'm over in Florida as well. Just a little bit north of you, I think. Yeah. Sweet. Last time we talked more about.NET Core Templates and specifically how you can use custom templates that people in the.NET community created. What about if you want to create a.NET template? How do you do it? That is exactly what we're going to be covering today here. What we're going to do is basically, we're going to talk about how to create your own project templates, and then we can use those from either.NET new and also now, we've got the availability to use the same exact project templates, not only in.NET new, but also in Visual Studio 2019 and Visual Studio for Mac. I believe even JetBrains Writer has a functionality to show the templates that have been created and installed with.NET new. Basically, you create one template, and then just expose that everywhere. In this particular video, we're going to show how to create a basic template, and then how to get that working with.NET new, and then in future videos, I will also show how to fine-tune those for Visual Studio, and how to improve your overall templates as well. Yeah, that's the general idea here. Great. This sounds like it would be incredibly useful if there is just a specific template thing that you personally need, whether it's for a particular project, or whatever team you're working on, that BS doesn't have by default, right? Yeah, exactly. There's a lot of scenarios here. One would be, let's say you've got a big enterprise and you've got maybe like a team of architects, and they're the ones out there that will be creating these project templates and putting that up onto maybe like a private NuGet repository or some type of private NuGet server that they've got there. That's one scenario. Another scenario would be, let's say if you own an open-source utility there. You might want to go through and create some templates for your open-source projects. That's another one there. For example, there's lots of popular open-source projects that's available. One would be.NET boxed. There's also identity server templates, so on and so forth. There's just a lot of different scenarios for creating custom templates. It's actually a lot easier than what it used to be. In the past, it used to be pretty complicated to create and maintain these templates. But now we've significantly cut that down to make it a lot simpler to go ahead and get started there, so that's the idea. Awesome. I do like simplicity, so shall we check it out? Yeah, definitely. Cool. All right. Before we get started, what we're going to do is I've got this open-source repository here on GitHub. You can get to it by going to this link here, aka.ms-netcore-templates. We're essentially going to recreate what we have inside this repository here, so users can follow along there. Then in the readme, all the information that you need for creating templates and fine-tuning them for Visual Studio, everything that you need is inside this readme here. For example, here's a couple of links for how to create your own templates, and we'll be covering that content today. We also have our own ASP.NET Core templates, our open-source and GitHub as well, so if anybody wants to go and take a look at how the ASP.NET Core project templates have been created, they can always go through and take a look at these particular examples here for that as well, so it's just more information. Yeah, exactly. We're going to go ahead and get started on this one, so let me go ahead and fire up my, actually, let me explain something here real quick. The way that we're going to structure our code is essentially going to follow what we have here, so in this repository, I've got a source folder, so I'll create a source folder, and then there's also a content folder, and inside the content folder is actually where these projects exist, so each folder here is a project that has become a template, so I'm just going to go ahead and mimic this particular structure here, so I've got my demo folder here inside my source, I'm going to add a content, right, so that's great, so now what we want to do is let's go ahead and add the solution file to this as well, so I'm going to go ahead and open up a terminal prompt here, and then we'll go ahead and change directories. Okay, so now, you know, last video, we showed you know how to use .NET new, one thing that I didn't show was .NET new, you can also create certain types of files here, right, and the solution file is one of those, so I'm going to go ahead and do that, so I'm going to create my solution, I'll say .NET new, solution-n for name will be demo, going to get that created, so that should go ahead and create my solution file here in the source directory, and then at this point, what I'll do is go ahead and create a new project and put that into content, and then we'll go from there, but I'll just go ahead and do that here with .NET new, because I'm already in here, so I can say .NET new, console, and we'll say my console01, that should be right, so this should create another folder called my console01, and then everything is here, so now what we'll do is go ahead and fire up the solution file in Visual Studio and add that project to it, okay, so here we've got my program.cs, I'm just going to make a small modification to this, so I'm going to take the project name, which was my console, so I'll say hello from my console01, now let me just go ahead and run this to verify that it builds and runs, all right, so hello from my console, so this builds and runs, now what we're going to do now is go back and add a couple additional files that we need here to create a template out of this, so the files that we'll need is the template.json file, and that's going to go into a folder named .template.config, let's go ahead and create that folder here, I'm going to go into the project folder and I'll say new, just going to create a new JSON file here for the template.json, go back to Visual Studio, I'm going to create a solution folder here so that way I can interact with these files, but this is not necessarily needed here, you can just directly open the files if you like, all right, so now I've got my template.json file loaded up here, whenever you're editing one of these JSON files, whether it's the template.json file or one of the other JSON files that we work with, you always want to start by putting the schema declaration inside the file, so this is going to do a number of things, so one thing it's going to do is it's going to provide completions, for example, this completions here, the other thing it does is within the completions, there's an indication of required properties here, and those are the ones that have been bolded here, so we can see there's a list of bolded items at the top, so these are all required, we have to set all those, we're also going to set a couple of different ones, and then in addition to that, the schema will also give a validation, so let's say if you did introduce an error in this file, you should see the error down here in the error list here, all right, so let's go ahead and run through these here, so author is me, classifications, so for this, it's a console app, so I'll put console here, and there's more information on the read me about what are the classifications and what are the different values that can be used, but essentially, this is going to appear in Visual Studio as a filter here, but we'll get to that, identity should be a unique name for this, so I'm just going to come up with some kind of long name here that's never been used, name is like the full name, what happens if the name has been used, will VS flag you or something about it? Yeah, so that's a great question, so let's say if identity has been used, and you reuse that same identity, what might end up happening is you might get some unexpected behavior, it might not necessarily be clear if you're using the first one that you had installed or the second one that you had installed, so it's always good for identity to give kind of a longer name that you're going to be pretty sure is unique, and usually I would put some sort of identifier in here as well, I'll always put kind of my alias here, so yeah, I would always try to make this unique because you could get unexpected results if you do reuse some identity value that's already been there. Gotcha. And then we're going to add a short name, so the short name is the value that users will use on the console, so I'll say Syed Khan is fine for that one. Tags, so tags are things like the type here, so is it a project template or is it an item template, and pick project for this one? So currently we support item and project, but we are considering to support the solution there as well, and then language is, what's the main kind of language that this project is using here, and like C-sharp, VB, F-sharp, but you're not limited to any particular languages when you create templates with, you create these types of templates here. Okay, so we've gone ahead and filled in all the kind of required parameters here, there's going to be an additional parameter that you're always going to want to specify and that's source name, so let me copy this. Let me kind of explain how source name works here. So with most template like processors or template engines, what happens is you normally have to go into your source code and actually modify or tokenize things. You know, like for example, for example, when I create a project template out of this, you know, odds are I want users to be able to specify the value for the namespace, right? Like, you know, normally that's the name of the project. So with most kind of template preprocessors, what you have to do is you have to go into your code and kind of tokenize these, right? So, you know, for example, with the kind of, with the older existing VS template approach, you'd have to go through your code and change all your namespace declarations to be something like, you know, dollar sign root namespace. I forget if it's a dollar sign or a percent sign or something, but the point is, you know, you have to go and modify your code in such a way that it no longer builds. Right. So this, yeah, this creates, this really creates just a huge maintenance nightmare because, you know, you've got your project here that's the source and you kind of build and run that one. And then you have this tokenized version of your project. So you're constantly maintaining two different things, right? And it's not easy. And, you know, I've even heard of cases where there was an open source template and, you know, they had C sharp support and a contributor contributed VB support. But then it was so hard to maintain the VB template that they just got rid of it, right? So those are the types of things that we're trying to avoid with the template engine. So with template engine, what we do is we kind of turn it on top of its head here. You know, instead of having users go through and tokenize all of their code, what we do is we provide abilities for users to indicate what replacements should be happening. And all that stuff happens in the template.json. And source name is a very kind of special one. So source name is, you know, the string my console 01. That was the name of the project that I had given when I created this. So now what happens is when a user will use this template, you know, either with .NET new or with Visual Studio, whatever project name was given, we'll replace my console 01. And that will happen across, you know, all the template files. So wherever my console 01 shows up, it'll be replaced with the name of the project. And, you know, this is not only in the contents of the files, but also for the file names themselves. All right, so now we've got everything that we need for this template.json. So now we should be able to kind of go in and run, we should go ahead and be able to install this template and then use that. We're putting clear out of this. Inside the GitHub repository, I do have my GitHub repository in the readme. There's some PowerShell here that might be helpful for users. There's a reset templates function here that I'm gonna be using here. And, you know, users can copy and paste this into their PowerShell prompt or in their PowerShell profile. So let me go ahead and call that. So if you're developing templates locally, if you're a template developer, you're gonna wanna reset the templates, you know, pretty often, essentially, while you're kind of going through this process here. So I've just kind of reset .NET new to everything and only the default things are kind of available right now. I'm gonna install that. So I say .NET new dash dash install and then point it to a folder and then it will search for the templates underneath that. All right, so now here we are. So now we see we've got sayet-ha.console.01 with the short name of sayet-con. So now I can do .NET new sayet-con output and we could say console demo. So that would be the name of the project, console demo. Let's go into that then console demo, let's look. Let's go ahead and run this with .NET run. See what the output is. All right, hello from console demo exclamation point. Awesome. All right, so go ahead. That was a good sign. Yeah, not exactly. So we didn't really have to do much for that replacement, right? And if I was to open up the program.cs here, we can see that that replacement did take place, not only in the namespace, but also in the code itself. So wherever was my console 01, it's now console demo. Then also we noticed that the project was named console demo.csproj as well. So that's kind of what we expected as well. All right, so now what we wanna do is, we've created a template, but this template is kind of here locally on my machine. So what we wanna do is we wanna take this template and share it with friends and colleagues. So the way to do that is to actually take this template, put it inside of a new get package and then you can upload that to newget.org or to any kind of new get server that you're working with there. So let's go back to the samples here and I'll show you where is that the new spec and we're gonna just kind of copy the file that's there. Let me copy the contents here. All right, let me go back to Windows Explorer. I will create this file. So we'll put it in the source folder here. So I'll say new, let's get this loaded up in Visual Studio as well. I'm just gonna drag it into my template files here. All right, so now I got my new spec here. Let me go ahead and paste in the contents. Let me change some of this. The file name itself, there we go. All right, so this is just kind of a very kind of basic new spec file. So the new spec just kind of describes the new get, describes the new get package here. And there's a lots of kind of docs for this as well but let me go through and kind of customize some things. Demo and look back. And whenever you're creating a new get package that contains templates, you always wanna indicate that this package contains a template and this kind of will show up in the search on newget.org that we showed in a previous video. And then for the contents of the new get package, you should pick up all the files in the content folder excluding the bin and OBJ folders. Just make sure that's correct. Yeah, so that's correct and that's what I'm expecting. All right, let me go through. I'm gonna reset my templates again. Just list them just to kind of double check that there's no side console template here. All right, so it's not there. All right, so now what we wanna do is we wanna go ahead and pack this. So let me see where am I at. Go into... Okay, so now to do this, we're gonna use newget.exe here. So I've got that on my path. For users, you can download this from newget.org. And the command that we're gonna send here is pack. We're gonna give the new spec file, specify output directory. So can you do all of this within Visual Studio itself or do you have to do it in the console window? Yeah, right, so that's a great question here. So yeah, so for this particular step of creating a package from a new spec file, there's no way that I know of to achieve this directly in Visual Studio. So I think it's easier to just do these from the command line. But after we've created these artifacts, it would be possible for you to automate this with Visual Studio as well by creating maybe some kind of custom MS build files there. But yeah, there's no kind of direct support built in for this exact scenario in Visual Studio itself. Gotcha. I'm gonna create a package here. And in my template samples repository, I do have all this kind of automated in a PS1 file in case anybody's interested in that. Yeah, that repo looked extremely helpful. So yeah, people should definitely go look into that. Yeah, there's definitely a lot of good stuff there. All right, so now we can see that the newget package has been created here. So what I wanna do now is go ahead and install this from the newget package itself. That's same.net new install command. This time we're just gonna pass it the newget package instead of the folder path. All right, so now we can see I've got my sciadha.console.01 project template here. We can just go ahead and try that again one more time. Let me go to a, you know, what I'll do is I'll just do it like this.net new. And then the output will go into the demo. And then we'll see a test console. All right, let's just go there and double check that we're confined one time real quick from the newget package. All right, so there we go. So now what we can do is we can take this. We can take this and then just publish it directly to newget.org at this point. So basically, you know, let's say you've kind of customized your template, you're ready to kind of go and you're ready to publish this guy out. What you'll do is you just go to newget.org, sign in obviously, then go to upload. So at this point, what I can do is I can take my newget package that was just created, drag it here, there's gonna be some verification and give you a little preview of it. And then you can go ahead and publish this. So I'm not gonna publish this one because there's nothing here, but after that was done, then what your users can do is then they can say .net new, dash, dash install. Let's take this one for an example, right? So this one, the ID would be this sayed demo con.01, right? Great. So that's what users would do to go and create a newget, to create a project template, use it from .net new locally to verify that it works, wrap it inside of a newget package, publish it to newget.org or you can publish it to any newget server there to myget or any server that you've got. And then your friends and colleagues can then go ahead and start installing and partying on these templates. That's really cool. And honestly, I kind of expected you to have to jump through more hoops just to publish a package like that. So yeah, it's a pretty straightforward. That's right. So what we've done is here we did just kind of the very kind of basics here. There's still a lot more that we can do to kind of improve the experience, not only for .net new, but also for Visual Studio. So you know you're right. It is fairly, it's very kind of easy and fast to get started with these templates and also to publish them. But to make kind of a great template will require a little bit of additional effort, but those are kind of things that we'll be covering in our kind of future videos as well. Great. So speaking of which, what are we gonna talk about next? Yeah, so I think what we're gonna do next is we're gonna take this template that we've created here and add some parameters to it. So if I were to go back to my GitHub and take a look at this console project here, we can see in the template.json there are some parameters here. So these parameters are things that users can specify either on the command line and also in Visual Studio. So we'll talk about how to create parameters in the template. And there's also a template kind of analyzer tool that I've created. So we'll show how to install and run that tool. And then we'll discuss how to address the warnings that are coming out of it for this template that we have, like if I was to show you some things, we are missing some things here. So for example, we're missing the framework one and we'll show how to add that. And then there'll be some other kind of customizations and modifications that we make to make this experience even better. Sounds good. Well, I can't wait to see how we continue to flush out that template. Oh yeah. So until next time, happy coding. Thank you.