Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SwaggerToCSharpWebApiControllerGenerator - add attributes on routes problem #870

Closed
gozdebozkurt opened this issue Aug 7, 2017 · 11 comments

Comments

@gozdebozkurt
Copy link
Contributor

Hello,
We are currenlty trying to use design driven approach to drive the design of our microservices REST interface.
In order to generate api controllers and models from swagger spec file we decided to use "NSwag.CodeGeneration.CSharp.SwaggerToCSharpWebApiControllerGenerator".
This is working well so far but we also need to find a way to extend autogenerated class so that we can add attributes on some routes.(like Cache, Authorize etc)
Looks like there is no way to autogenerate these attributes from the spec file(would be nice to do it at least for the Authorize attribute which is part of the swagger specs)
Using partial classes for controller doesn't solve our problem, we would like to leverage attribute inheritance for that.

Currenlty an example of autogenerated code is something like:

//generated code
[System.CodeDom.Compiler.GeneratedCode("NSwag", "11.3.3.0")]
public interface IHomeController
{
/// OK
[System.Web.Http.HttpGet, System.Web.Http.Route("")]
System.Threading.Tasks.Task IndexAsync();
}
[System.CodeDom.Compiler.GeneratedCode("NSwag", "11.3.3.0")]
public partial class HomeController : System.Web.Http.ApiController
{
private IHomeController _implementation;

    public HomeController(IHomeController implementation)
    {
        _implementation = implementation; 
    }    
    /// <returns>OK</returns>
    [System.Web.Http.HttpGet, System.Web.Http.Route("home")]
    public System.Threading.Tasks.Task<HomeModel> Index()
    {    
        return _implementation.IndexAsync();            
    }    
}

//implemented code
public class HomeController : IHomeController
{
public async Task IndexAsync()
{
return await Task.FromResult(new HomeModel()
{
AssemblyVersion = GetType().Assembly.GetName().Version.ToString(),
AssemblyFullName = GetType().Assembly.FullName,
Environment = _configurationSettings.EnvironmentType,
FakeModeSeed = _configurationSettings.FakeModeSeed
});
}
}

The autogenerated code we are trying to achieve would be something like:

//generated code
public abstract class HomeControllerBase : ApiController
{
[Route("home")]
[HttpGet]
public abstract HomeModel Index();
}
//implemented code
public class HomeController : HomeControllerBase
{
[CacheOutput(ClientTimeSpan = 300)]
[Authorize("write")]
public override HomeModel Index()
{
return new HomeModel
{
AssemblyVersion = GetType().Assembly.GetName().Version.ToString(),
AssemblyFullName = GetType().Assembly.FullName,
Environment = "DEV",
FakeModeSeed = false
};
}
}

Can we use a custom template to get the above result?
Do you think this is the right way to tackle the problem and achieve our goals?

Thanks,

@RicoSuter
Copy link
Owner

Currently you can only replace existing templates with the TemplateFactory in C#, but this is not really a good solution because you have to copy the existing template and always have to merge changes back to your copy. I am planning to change the template engine so that it is much more flexible and provide hooks/extension points to inject own snippets (for example only additional attributes).

But because I currently am working on other aspecs of NSwag and no one is paying for this feature I don't know when it is coming. It is extremely time consuming as it must not change any output (no breaking changes) and it also must be changed in the NJsonSchema project (DTO class/interface generation).

See https://github.com/RSuter/NSwag/wiki/Roadmap

@RicoSuter
Copy link
Owner

I think for now it is easier to just search for

public override HomeModel Index()

and replace it with

[Foobar]
public override HomeModel Index()

in the generated output.

(maybe with regexes...)

@RicoSuter
Copy link
Owner

See #263

@gozdebozkurt
Copy link
Contributor Author

Actually we are using NSwag.MSBuild and we are generating code at Build time. For this reason we can't edit the auto-generated file.
Are you keen to accept pull requests if we decide to make the template engine more flexible as part of the current NSwag version so using T4 templates or do you want to wait for NSwag v12 with the new DotLiquid template engine?

@RicoSuter
Copy link
Owner

What do you have in mind?

@gozdebozkurt
Copy link
Contributor Author

gozdebozkurt commented Aug 10, 2017

We want to add some additional settings to SwaggerToCSharpWebApiControllerGeneratorSettings
(like AdditionalNamespaceUsage) and the default values would keep the current behavior. In this way we can change the existing template just adding if clauses to the template file without breaking changes.

For example;

bool GenerateControllerInterfaces default true
bool RenderControllersAsAbstract default false
bool RenderControllerMethodsAsAbstract default false

What do you think about that?

@RicoSuter
Copy link
Owner

Sounds good. I'd call the settings

GenerateControllerInterfaces
GenerateAbstractControllers
GenerateAbstractMethods

What do you think?

@RicoSuter
Copy link
Owner

Maybe we also need to differentiate between asp.net web api and asp.net core mvc controllers?

@ma499
Copy link

ma499 commented Aug 10, 2017

@RSuter's suggested setting names make sense to me.

What differentiation would make sense between Web API and MVC 6? I think the settings are equally applicable to both frameworks.

@RicoSuter
Copy link
Owner

Yes, these settings do not need a differentiation. But maybe there are currently other aspects which are not applicable to both fws..

@gozdebozkurt
Copy link
Contributor Author

I sent a pull request. Could you review, please?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants