aspnet / Tooling

Issue tracker and info on Visual Studio tooling for ASP.NET
Other
256 stars 124 forks source link

How do we add Custom Code Generators and invoke them through dotnet cli #922

Closed jjkcharles closed 7 years ago

jjkcharles commented 7 years ago

Since the Controller generators available within dotnet core wouldn't suffice my needs (I would need to generate a CRUD but not all views are required & view names will need to be different than Create/Index/Edit etc... - so customizing the existing templates is not an option) I am trying to write my own CodeGenerator, but doesn't seem to be able to invoke it through "dotnet aspnet-codegenerator" command. Below is my custom code generator (currently has no implementation - my goal is to be able to trigger this from dotnet cli and end up with the exception),

namespace TestWebApp.CodeGenerator
{
    [Alias("test")]
    public class TestCodeGenerator : ICodeGenerator
    {
        public async Task GenerateCode(TestCodeGeneratorModel model)
        {
            await Task.CompletedTask;
            throw new NotImplementedException();
        }
    }

    public class TestCodeGeneratorModel
    {
        [Option(Name = "controllerName", ShortName = "name", Description = "Name of the controller")]
        public string ControllerName { get; set; }

        [Option(Name = "readWriteActions", ShortName = "actions", Description = "Specify this switch to generate Controller with read/write actions when a Model class is not used")]
        public bool GenerateReadWriteActions { get; set; }
    }
}

Below is how I'm trying to invoke the code generator, dotnet aspnet-codegenerator -p . TestCodeGenerator TestController -m TestWebApp.Models.TestModel OR dotnet aspnet-codegenerator -p . test TestController -m TestWebApp.Models.TestModel

This though, doesn't seem to work and the CodeGeneratorLocator complains about not being able to locate the custom code generator. See error message below,

Finding the generator 'TestCodeGenerator'...
No code generators found with the name 'TestCodeGenerator'
   at Microsoft.VisualStudio.Web.CodeGeneration.CodeGeneratorsLocator.GetCodeGenerator(String codeGeneratorName)
   at Microsoft.VisualStudio.Web.CodeGeneration.CodeGenCommand.Execute(String[] args)
RunTime 00:00:06.23

Tooling version used is 1.0.0-preview2-final

Is there any other requirements, apart from inheriting ICodeGenerator (or name ending with CodeGenerator) & Assembly having a reference of Microsoft.VisualStudio.Web.CodeGeneration,for the custom code generator to be visible to Code Generator?

mlorbetske commented 7 years ago

Hi @jjkcharles this isn't a scenario that we support, but maybe @prafullbhosale can share more details on how this worked in preview 2.

jjkcharles commented 7 years ago

@mlorbetske Thanks for the response. Does it mean that, we are limited to using the "view" and "controller" code generators currently available in "aspnet-codegenerator"? Is the code generator extensible in any other way apart from being able to override the default Razor Templates for views/controllers?

prafullbhosale commented 7 years ago

@jjkcharles I think you are on the right path. For preview2 the requirements you mentioned should be sufficient.

dotnet aspnet-codegenerator -p . test TestController -m TestWebApp.Models.TestModel There are a couple of issues, TestController should be the value of --controllerName and the TestCodeGeneratorModel doesn't contain an option for -m

Can you try this invocation and let me know what error is thrown? dotnet aspnet-codegenerator -p . test --controllerName TestController

Also could you provide the project.json for the project on which you are trying to run this?

jjkcharles commented 7 years ago

@prafullbhosale dotnet aspnet-codegenerator -p . test --controllerName TestController doesnt seem to be working too - I get the same error message. Please refer to the project.json here

prafullbhosale commented 7 years ago

@jjkcharles You do not need this in the project.json https://github.com/jjkcharles/DotnetCoreCustomScaffold/blob/master/TestWebApp/project.json#L25

Instead you need to add the package that has your custom scaffolder as a dependency of the project. The CLI tool looks at the project's dependencies to find any packages that have a dependency on Microsoft.VisualStudio.Web.CodeGeneration and uses them to find scaffolders.

jjkcharles commented 7 years ago

@prafullbhosale Earlier, I was having the custom code generator within the web project (should this be separate, will the web assembly not be scanned for code generators?).

I have now split it out into a separate class library, added Microsoft.VisualStudio.Web.CodeGeneration as a dependency, and added the class library as a dependency for my web project. Doesn't seem to have helped though.

Refer to the code here.

prafullbhosale commented 7 years ago

No, the web project itself doesn't get scanned for code generators. It needs to be a dependency. Also, I think there is a limitation that the dependency needs to be of type package and not type project In your case, the CustomScaffolder would end up being a project dependency.

To workaround, you can create a package from CustomScaffolder using dotnet pack and make the
"target": "package" for the CustomScaffolder dependency in the TestWebApp.

I am also creating a code sample with steps for writing custom scaffolders. Will push it to github in a few minutes.

prafullbhosale commented 7 years ago

You can take a look at this for additional information: https://github.com/prafullbhosale/CustomScaffolder

jjkcharles commented 7 years ago

@prafullbhosale thanks a lot for the explanation and sample. I've managed to get it working now.

On your Repo, one little change would be required though NuGet.config is referring to '..\artifacts' whereas it should be '..\src\artifacts'

mlorbetske commented 7 years ago

Glad to hear you got it working @jjkcharles, I'll close the issue - feel free to re-open if needed