dotnet / templating

This repo contains the Template Engine which is used by dotnet new
https://docs.microsoft.com/dotnet/
MIT License
1.63k stars 369 forks source link

Enable using .NET SDK templates with Visual Studio #4686

Closed richlander closed 2 years ago

richlander commented 2 years ago

There should be a way to use .NET SDK templates (dotnet new -i) with Visual Studio. I don't believe there is any such experience.

This issue would be best served by such a capability: https://github.com/dotnet/iot/issues/1173

dotnet-issue-labeler[bot] commented 2 years ago

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

baronfel commented 2 years ago

@richlander the .NET SDK Templates do show up in the VS NPD today, and have for several releases now. In fact, many templates ship IDE-specific config files to customize the display of the templates inside VS/VSMac. Is there a specific template that you're not seeing that we should investigate?

richlander commented 2 years ago

I did this and couldn't find the template in VS.

dotnet new search
No templates found matching: 'search'.

To list installed templates, run:
   dotnet new --list
To search for the templates on NuGet.org, run:
   dotnet new search --search
PS C:\Users\rich> dotnet new search --search
Searching for the templates...
Matches from template source: NuGet.org
These templates matched your input: 'search'

Template Name             Short Name          Author           Language  Package                              Downloads
------------------------  ------------------  ---------------  --------  -----------------------------------  ---------
EasyQuery Advanced Se...  eq.view.advsearch   Korzh.com        [C#]      Korzh.EasyQuery.AspNetCoreTemplates         7k
EasyQuery FullTextSea...  eq.view.textsearch  Korzh.com        [C#]      Korzh.EasyQuery.AspNetCoreTemplates         7k
dotnetlife datascienc...  researchproject     Kevin Schneider  F#        datascience-project-template                3k

dotnet new -i Korzh.EasyQuery.AspNetCoreTemplates

As an aside, I think this error message is very misleading:

To search for the templates on NuGet.org, run:
   dotnet new search --search

Should it be dotnet new search [search]?

baronfel commented 2 years ago

I can dig into that template in particular not showing up in VS. As for the error message, that should be different starting in the 7.0.100 previews. The syntax change corresponded with the switch to System.CommandLine, and the combined set of changes was large enough to be pushed back to 7.x. it looks and feels great, though!

baronfel commented 2 years ago

I've verified that the templates are part of the template cache that VS uses, so my suspicion is some mismatch between the VS Template Provider and the New Project Dialog. I'll move this over to dotnet/templating and get with @phenning to figure out the root cause.

And to give you a sneak peak of the search experience in .NET 7:

➜ dotnet new search --help
Description:
  Searches for the templates on NuGet.org.

Usage:
  dotnet new search [<template-name>] [options]

Arguments:
  <template-name>  If specified, only the templates matching the name will be shown.

Options:
  --author <author>                      Filters the templates based on the template author.
  -lang, --language <language>           Filters templates based on language.
  --type <type>                          Filters templates based on available types. Predefined values are "project" and "item".
  --tag <tag>                            Filters the templates based on the tag.
  --package <package>                    Filters the templates based on NuGet package ID.
  --columns-all                          Display all columns in the output.
  --columns <author|language|tags|type>  Specifies the columns to display in the output.
  -?, -h, --help                         Show command line help.
baronfel commented 2 years ago

@phenning after installing these templates, the templatecache.json for the VS provider has the following data for the three templates here:

templatecache.json snippet of the three template configs ```json { "Parameters": [ { "Documentation": "", "Name": "DbContextName", "Priority": 2, "Type": "parameter", "IsName": false, "DefaultValue": "ApplicationDbContext", "DataType": "string", "DefaultIfOptionWithoutValue": null, "Choices": null, "Description": "", "DisplayName": "" } ], "MountPointUri": "C:\\Users\\chethusk\\.templateengine\\packages\\Korzh.EasyQuery.AspNetCoreTemplates.4.3.1.nupkg", "Author": "Korzh.com", "Classifications": [ "EasyQuery/View/Controller" ], "DefaultName": null, "Description": "", "Identity": "EasyQuery.AdvSearch", "GeneratorId": "0c434df7-e2cb-4dee-b216-d7c58c8eb4b3", "GroupIdentity": "EasyQuery.Templates.EasyQueryAdvancedSearch", "Precedence": 0, "Name": "EasyQuery Advanced Search View", "ShortNameList": [ "eq.view.advsearch" ], "ConfigPlace": "/content/EasyQuery.AdvancedSearch/.template.config/template.json", "LocaleConfigPlace": null, "HostConfigPlace": null, "ThirdPartyNotices": null, "BaselineInfo": {}, "TagsCollection": { "language": "C#" }, "HostData": null }, { "Parameters": [ { "Documentation": "", "Name": "DbContextName", "Priority": 2, "Type": "parameter", "IsName": false, "DefaultValue": "ApplicationDbContext", "DataType": "string", "DefaultIfOptionWithoutValue": null, "Choices": null, "Description": "", "DisplayName": "" }, { "Documentation": "The name of the model class for which we create a view with the full text search functionality", "Name": "ModelClassName", "Priority": 2, "Type": "parameter", "IsName": false, "DefaultValue": "ModelClassName", "DataType": "string", "DefaultIfOptionWithoutValue": null, "Choices": null, "Description": "The name of the model class for which we create a view with the full text search functionality", "DisplayName": "" } ], "MountPointUri": "C:\\Users\\chethusk\\.templateengine\\packages\\Korzh.EasyQuery.AspNetCoreTemplates.4.3.1.nupkg", "Author": "Korzh.com", "Classifications": [ "EasyQuery/View/Controller" ], "DefaultName": null, "Description": "", "Identity": "EasyQuery.FullTextSearch", "GeneratorId": "0c434df7-e2cb-4dee-b216-d7c58c8eb4b3", "GroupIdentity": "EasyQuery.Templates.EasyQueryFullTextSearch", "Precedence": 0, "Name": "EasyQuery FullTextSearch View", "ShortNameList": [ "eq.view.textsearch" ], "ConfigPlace": "/content/EasyQuery.FullTextSearch/.template.config/template.json", "LocaleConfigPlace": null, "HostConfigPlace": null, "ThirdPartyNotices": null, "BaselineInfo": {}, "TagsCollection": { "language": "C#" }, "HostData": null }, { "Parameters": [ { "Documentation": "", "Name": "DbContextName", "Priority": 2, "Type": "parameter", "IsName": false, "DefaultValue": "ApplicationDbContext", "DataType": "string", "DefaultIfOptionWithoutValue": null, "Choices": null, "Description": "", "DisplayName": "" }, { "Documentation": "The name of the model class for which we create a view with data filtering functionality", "Name": "ModelClassName", "Priority": 2, "Type": "parameter", "IsName": false, "DefaultValue": "ModelClassName", "DataType": "string", "DefaultIfOptionWithoutValue": null, "Choices": null, "Description": "The name of the model class for which we create a view with data filtering functionality", "DisplayName": "" } ], "MountPointUri": "C:\\Users\\chethusk\\.templateengine\\packages\\Korzh.EasyQuery.AspNetCoreTemplates.4.3.1.nupkg", "Author": "Korzh.com", "Classifications": [ "EasyQuery/View/Controller" ], "DefaultName": null, "Description": "", "Identity": "EasyQuery.GridFilter", "GeneratorId": "0c434df7-e2cb-4dee-b216-d7c58c8eb4b3", "GroupIdentity": "EasyQuery.Templates.EasyQueryGridFilter", "Precedence": 0, "Name": "EasyQuery GridFilter View", "ShortNameList": [ "eq.view.gridfilter" ], "ConfigPlace": "/content/EasyQuery.GridFilter/.template.config/template.json", "LocaleConfigPlace": null, "HostConfigPlace": null, "ThirdPartyNotices": null, "BaselineInfo": {}, "TagsCollection": { "language": "C#" }, "HostData": null } ```

I've tried a few searches based on the short name, long name, tag collections, etc, but none cause the template to appear in the list. I also notice a few other templates that I have installed (like Falco and MiniScaffold) that don't show up in VS - is there some critical piece of information missing in template that would cause this behavior? I see these in the CLI listings.

sayedihashimi commented 2 years ago

@baronfel I noticed that these templates don't have a $.tags.type declared (typically it's set to Project).

In VS, we do support templates that don't have a $.tags.type. We try to infer it. We will use Project if we see a .proj file in the folder containing (or folder under it) .template.config, and we will assume solution if we see a .sln folder there.

In the case of these templates, there is no .csproj or .sln in the same folder containing the .template.config. So I wouldn't expect these to appear in VS because we cannot make sense of it.

Edit: I misspoke about the type property being inferred, type is always required, but we do try to infer the primaryOutputs value of its missing.

image

baronfel commented 2 years ago

Interesting - so as I'm looking at these templates they feel almost more like item templates for specific kinds of pages. Do .NET Templates integrate in VS with the New Item dialog?

sayedihashimi commented 2 years ago

For item templates it’s not technically supported yet. We have enabled a way for MAUI, but the implementation will change when constraints are in place. We are waiting until then to formally support them.

baronfel commented 2 years ago

Excellent! Ok then, I'm looking forward to taking another look at this issue as constraints land. Thank you for the clarification!

In our docs for template authors on this wiki and on docs.ms.com, is the rule above solid enough to codify for end users? We don't have guidance on 'making your template appear in editors', but I'd be happy to write it up if there's a known list of things to do.

sayedihashimi commented 2 years ago

@baronfel take a look at https://aka.ms/netcore-templates for additional info.

baronfel commented 2 years ago

Every time you point me to your template validation repo I get the itch to add its feature set to our msbuild template tasks in this repo.

vlada-shubina commented 2 years ago

@richlander is objective of original issue to allow users to install template packages from Visual Studio (besides dotnet new install way)? If so, I'll move the ticket to VS repo.

The type issue might be solved by validation https://github.com/dotnet/templating/issues/3828 or constraints https://github.com/dotnet/templating/issues/3107 depending on expected behavior (if the template should be allowed in VS or not).

phenning commented 2 years ago

There are several separate issues here.

  1. The original feedback issue that @richlander linked had to do with dotnet/iot and the directory based templates note being available in Visual Studio. This is now supported in Visual Studio 2022. This feedback issue could now be resolved.

  2. There is some confusion about the metadata which needs to be supplied for projects to show up in Visual Studio, the "EasyQuery" templates don't seem to have any $.tags.type declared which is why they don't show up at all. This is an authoring problem, not a product issue, customers could be pointed to the validation tool or the build task when it exists.

  3. For $.tags.type = item, like @sayedihashimi said, we support this today in Visual Studio 2022, but there is additional metadata that needs to be defined via the host file for it to show up. The metadata controls where in the hierarchy the template shows up, a capabilities filter for restricting to particular project types (optional) and the extension to use in combination with defaultName (required for auto numbering of default names in the new item dialog). We should have another discussion on whether we want to formerly support this outside of Maui scenarios now.

richlander commented 2 years ago

This is now supported in Visual Studio 2022. This feedback issue could now be resolved.

Great. Thanks!

@Ellerbach @shaggygi

baronfel commented 2 years ago

So, action items for this issue in particular seem to be:

richlander commented 2 years ago

It would also be good to document (both docs and blogs) about what template users can expect from templates with VS.

shaggygi commented 2 years ago

@richlander thanks for looking into the issue. I had no idea it was added in VS17. 👍

the following adds it to the dialog.

dotnet new -i C:\[PATH]\iot\tools\templates\DeviceBindingTemplate\dotnet_new_device-binding_csharp

image
vlada-shubina commented 2 years ago

@baronfel updated docs with the reference in https://github.com/dotnet/docs/pull/29654

Validation tooling is tracked in https://github.com/dotnet/templating/issues/3828, until that's done we recommend to use this tooling

DavidBoike commented 1 year ago

@sayedihashimi:

For item templates it’s not technically supported yet. We have enabled a way for MAUI, but the implementation will change when constraints are in place. We are waiting until then to formally support them.

And @phenning:

For $.tags.type = item, like @sayedihashimi said, we support this today in Visual Studio 2022, but there is additional metadata that needs to be defined via the host file for it to show up. The metadata controls where in the hierarchy the template shows up, a capabilities filter for restricting to particular project types (optional) and the extension to use in combination with defaultName (required for auto numbering of default names in the new item dialog). We should have another discussion on whether we want to formerly support this outside of Maui scenarios now.

I gather from these comments that item templates showing up in Visual Studio is still somewhat of a special case for MAUI only. Is there an issue somewhere tracking general scenarios outside MAUI?

sayedihashimi commented 1 year ago

Hi @DavidBoike I spoke with @phenning today regarding this.

We haven't done the work on our side to formalize the support for Item Templates that use the Template Engine constraints. Since we have a lot of other important work that we are doing, we will not be able to get to implementing that for a while.

Because of that, we have decided that we will make public the support that we currently have and make that supported.

@phenning can you give a pointer to some example Item Templates that @DavidBoike can look at to implement the templates?

I can work on getting some docs created for this as well.

DavidBoike commented 1 year ago

@sayedihashimi that would be great, thanks!

DavidBoike commented 1 year ago

@phenning Any idea when I could get a link for those example item templates? I would love to work this into our latest release but I'm running out of time to work on it. While documentation would be nice, I'm guessing I could get things going with just a peek at a few examples.

phenning commented 1 year ago

@phenning Any idea when I could get a link for those example item templates? I would love to work this into our latest release but I'm running out of time to work on it. While documentation would be nice, I'm guessing I could get things going with just a peek at a few examples.

First you need to specify "type": "item" in the tags of your template.json:

You'll also need to add an ide.host.json file next to your template.json, with at least the following values. This is an example of a MAUI item template.

{
  "$schema": " https://json.schemastore.org/ide.host",
  "appliesTo": "UseMaui",
  "defaultItemExtension": "cs",
  "itemHierarchyPaths": [ "Maui" ]
}

The key thing is specifying an itemHeirchyPath in the ide.host.json, the presence of this is what triggers us to show the item template in Visual Studio.

For defaultItemExtension, this should be cs, or whatever the item template's extension is for the primary file.

appliesTo is a project capability expression that must match in the project for this template to be shown in the item dialog. Note that we automatically filter on the ".NET" project capability as well, since this is only intended for .NET Core CPS based projects.

itemHierarchyPaths is an array of strings which control which node, I can provide more details, but this is pretty self-explanatory.

You’ll probably also want to do the following in the template.json as well: • Add a primary outputs and the open file in editor post action to open the generated file(s) to the template.json.

ItemHierarchyPath notes: You can specify something like "itemHierarchyPaths": [ "AspNetCore/General", "AspNetCore/Data" ] to have the template appear in multiple nodes.

Also, we treat some path segments as tokens in order to provide localization (as of 17.7) AspNet = "ASP.NET" AspNetCore = "ASP.NET Core" Code = "Code" Content = "Content" Data = "Data" General = "General" Markup = "Markup" Scripts = "Scripts" Web = "Web" WebForms = "Web Forms"

The maui item template is here; maui/src/Templates/src/templates/maui-contentpage-csharp at main · dotnet/maui · GitHub

DavidBoike commented 1 year ago

Thanks @phenning, that's what I needed!

image