forked from loafle/openapi-generator-original
[aspnetcore] Support async tasks and some code cleanups (#2629)
* Add first cutasync support and small cleanups * Add apiPackage, modePacke to use for namespaces, for library don't generate wwwroot and dont make model class partial and default to no swashbuckle, , workarodun empty string cliOption * Update docs * Don't add async for library * Fix generated program for async and task * Default models names space should be <package>.Models * Remove commented out code * Remove unnecessary code, fix a comparison and add an else fo an if statment. * Update docs
This commit is contained in:
parent
89eb603c17
commit
1e4f4ab9f2
@ -23,7 +23,11 @@ sidebar_label: aspnetcore
|
||||
|useCollection|Deserialize array types to Collection<T> instead of List<T>.| |false|
|
||||
|returnICollection|Return ICollection<T> instead of the concrete type.| |false|
|
||||
|useSwashbuckle|Uses the Swashbuckle.AspNetCore NuGet package for documentation.| |true|
|
||||
|isLibrary|Is the build a library| |false|
|
||||
|classModifier|Class Modifier can be empty, abstract| ||
|
||||
|operationModifier|Operation Modifier can be virtual, abstract or partial| |virtual|
|
||||
|buildTarget|Target to build an application or library| |program|
|
||||
|generateBody|Generates method body.| |true|
|
||||
|operationIsAsync|Set methods to async or sync.| |false|
|
||||
|operationResultTask|Set methods result to Task<>.| |false|
|
||||
|modelClassModifier|Model Class Modifier can be nothing or partial| |partial|
|
||||
|
@ -20,6 +20,7 @@ package org.openapitools.codegen.languages;
|
||||
import com.samskivert.mustache.Mustache;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
import io.swagger.v3.parser.util.SchemaTypeUtil;
|
||||
import org.openapitools.codegen.*;
|
||||
import org.openapitools.codegen.utils.URLPathUtils;
|
||||
import org.slf4j.Logger;
|
||||
@ -39,13 +40,17 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
|
||||
public static final String ASPNET_CORE_VERSION = "aspnetCoreVersion";
|
||||
public static final String CLASS_MODIFIER = "classModifier";
|
||||
public static final String OPERATION_MODIFIER = "operationModifier";
|
||||
public static final String OPERATION_IS_ASYNC = "operationIsAsync";
|
||||
public static final String OPERATION_RESULT_TASK = "operationResultTask";
|
||||
public static final String GENERATE_BODY = "generateBody";
|
||||
public static final String BUILD_TARGET = "buildTarget";
|
||||
public static final String MODEL_CLASS_MODIFIER = "modelClassModifier";
|
||||
|
||||
public static final String PROJECT_SDK = "projectSdk";
|
||||
public static final String SDK_WEB = "Microsoft.NET.Sdk.Web";
|
||||
public static final String SDK_LIB = "Microsoft.NET.Sdk";
|
||||
public static final String COMPATIBILITY_VERSION = "compatibilityVersion";
|
||||
public static final String IS_LIBRARY = "isLibrary";
|
||||
|
||||
private String packageGuid = "{" + randomUUID().toString().toUpperCase(Locale.ROOT) + "}";
|
||||
|
||||
@ -55,13 +60,18 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
|
||||
private boolean useSwashbuckle = true;
|
||||
protected int serverPort = 8080;
|
||||
protected String serverHost = "0.0.0.0";
|
||||
private CliOption aspnetCoreVersion = new CliOption(ASPNET_CORE_VERSION, "ASP.NET Core version: 2.2 (default), 2.1, 2.0 (deprecated)");
|
||||
protected CliOption aspnetCoreVersion = new CliOption(ASPNET_CORE_VERSION, "ASP.NET Core version: 2.2 (default), 2.1, 2.0 (deprecated)");
|
||||
; // default to 2.1
|
||||
private CliOption classModifier = new CliOption(CLASS_MODIFIER, "Class Modifier can be empty, abstract");
|
||||
private CliOption operationModifier = new CliOption(OPERATION_MODIFIER, "Operation Modifier can be virtual, abstract or partial");
|
||||
private CliOption modelClassModifier = new CliOption(MODEL_CLASS_MODIFIER, "Model Class Modifier can be nothing or partial");
|
||||
private boolean generateBody = true;
|
||||
private CliOption buildTarget = new CliOption("buildTarget", "Target to build an application or library");
|
||||
private String projectSdk = SDK_WEB;
|
||||
private String compatibilityVersion = "Version_2_1";
|
||||
private boolean operationIsAsync = false;
|
||||
private boolean operationResultTask = false;
|
||||
private boolean isLibrary = false;
|
||||
|
||||
public AspNetCoreServerCodegen() {
|
||||
super();
|
||||
@ -160,6 +170,10 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
|
||||
"Uses the Swashbuckle.AspNetCore NuGet package for documentation.",
|
||||
useSwashbuckle);
|
||||
|
||||
addSwitch(IS_LIBRARY,
|
||||
"Is the build a library",
|
||||
isLibrary);
|
||||
|
||||
classModifier.addEnum("", "Keep class default with no modifier");
|
||||
classModifier.addEnum("abstract", "Make class abstract");
|
||||
classModifier.setDefault("");
|
||||
@ -182,6 +196,21 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
|
||||
"Generates method body.",
|
||||
generateBody);
|
||||
|
||||
addSwitch(OPERATION_IS_ASYNC,
|
||||
"Set methods to async or sync.",
|
||||
operationIsAsync);
|
||||
|
||||
addSwitch(OPERATION_RESULT_TASK,
|
||||
"Set methods result to Task<>.",
|
||||
operationResultTask);
|
||||
|
||||
modelClassModifier.setType("String");
|
||||
modelClassModifier.addEnum("", "Keep model class default with no modifier");
|
||||
modelClassModifier.addEnum("partial", "Make model class partial");
|
||||
modelClassModifier.setDefault("partial");
|
||||
modelClassModifier.setOptValue(modelClassModifier.getDefault());
|
||||
addOption(modelClassModifier.getOpt(), modelClassModifier.getDescription(), modelClassModifier.getOptValue());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -210,34 +239,36 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
boolean isLibrary = false;
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_GUID)) {
|
||||
setPackageGuid((String) additionalProperties.get(CodegenConstants.OPTIONAL_PROJECT_GUID));
|
||||
}
|
||||
additionalProperties.put("packageGuid", packageGuid);
|
||||
|
||||
if (additionalProperties.containsKey(USE_SWASHBUCKLE)) {
|
||||
useSwashbuckle = convertPropertyToBooleanAndWriteBack(USE_SWASHBUCKLE);
|
||||
} else {
|
||||
additionalProperties.put(USE_SWASHBUCKLE, useSwashbuckle);
|
||||
}
|
||||
|
||||
|
||||
// CHeck for the modifiers etc.
|
||||
// The order of the checks is important.
|
||||
isLibrary = setBuildTarget();
|
||||
setBuildTarget();
|
||||
setClassModifier();
|
||||
setOperationModifier();
|
||||
|
||||
setModelClassModifier();
|
||||
setUseSwashbuckle();
|
||||
setOperationIsAsync();
|
||||
|
||||
// CHeck for class modifier if not present set the default value.
|
||||
additionalProperties.put(PROJECT_SDK, projectSdk);
|
||||
|
||||
additionalProperties.put("dockerTag", packageName.toLowerCase(Locale.ROOT));
|
||||
|
||||
apiPackage = packageName + ".Controllers";
|
||||
modelPackage = packageName + ".Models";
|
||||
if (!additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) {
|
||||
apiPackage = packageName + ".Controllers";
|
||||
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
|
||||
}
|
||||
|
||||
if (!additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) {
|
||||
modelPackage = packageName + ".Models";
|
||||
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage);
|
||||
}
|
||||
|
||||
String packageFolder = sourceFolder + File.separator + packageName;
|
||||
|
||||
@ -259,8 +290,6 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
|
||||
supportingFiles.add(new SupportingFile("Program.mustache", packageFolder, "Program.cs"));
|
||||
supportingFiles.add(new SupportingFile("Properties" + File.separator + "launchSettings.json",
|
||||
packageFolder + File.separator + "Properties", "launchSettings.json"));
|
||||
} else {
|
||||
supportingFiles.add(new SupportingFile("Project.nuspec.mustache", packageFolder, packageName + ".nuspec"));
|
||||
// wwwroot files.
|
||||
supportingFiles.add(new SupportingFile("wwwroot" + File.separator + "README.md", packageFolder + File.separator + "wwwroot", "README.md"));
|
||||
supportingFiles.add(new SupportingFile("wwwroot" + File.separator + "index.html", packageFolder + File.separator + "wwwroot", "index.html"));
|
||||
@ -268,6 +297,8 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
|
||||
|
||||
supportingFiles.add(new SupportingFile("wwwroot" + File.separator + "openapi-original.mustache",
|
||||
packageFolder + File.separator + "wwwroot", "openapi-original.json"));
|
||||
} else {
|
||||
supportingFiles.add(new SupportingFile("Project.nuspec.mustache", packageFolder, packageName + ".nuspec"));
|
||||
}
|
||||
|
||||
|
||||
@ -342,15 +373,23 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
|
||||
|
||||
private void setCliOption(CliOption cliOption) throws IllegalArgumentException {
|
||||
if (additionalProperties.containsKey(cliOption.getOpt())) {
|
||||
cliOption.setOptValue(additionalProperties.get(cliOption.getOpt()).toString());
|
||||
if (cliOption.getOptValue() == null) {
|
||||
cliOption.setOptValue(cliOption.getDefault());
|
||||
throw new IllegalArgumentException(cliOption.getOpt() + ": Invalid value '" + additionalProperties.get(cliOption.getOpt()).toString() + "'" +
|
||||
". " + cliOption.getDescription());
|
||||
// TODO Hack - not sure why the empty strings become boolean.
|
||||
Object obj = additionalProperties.get(cliOption.getOpt());
|
||||
if (!SchemaTypeUtil.BOOLEAN_TYPE.equals(cliOption.getType())) {
|
||||
if (obj instanceof Boolean) {
|
||||
obj = "";
|
||||
additionalProperties.put(cliOption.getOpt(), obj);
|
||||
}
|
||||
}
|
||||
cliOption.setOptValue(obj.toString());
|
||||
} else {
|
||||
additionalProperties.put(cliOption.getOpt(), cliOption.getOptValue());
|
||||
}
|
||||
if (cliOption.getOptValue() == null) {
|
||||
cliOption.setOptValue(cliOption.getDefault());
|
||||
throw new IllegalArgumentException(cliOption.getOpt() + ": Invalid value '" + additionalProperties.get(cliOption.getOpt()).toString() + "'" +
|
||||
". " + cliOption.getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
private void setClassModifier() {
|
||||
@ -362,8 +401,6 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
|
||||
operationModifier.setOptValue(classModifier.getOptValue());
|
||||
additionalProperties.put(OPERATION_MODIFIER, operationModifier.getOptValue());
|
||||
LOGGER.warn("classModifier is " + classModifier.getOptValue() + " so forcing operatonModifier to " + operationModifier.getOptValue());
|
||||
} else {
|
||||
setCliOption(operationModifier);
|
||||
}
|
||||
}
|
||||
|
||||
@ -382,15 +419,28 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean setBuildTarget() {
|
||||
boolean isLibrary = false;
|
||||
private void setModelClassModifier() {
|
||||
setCliOption(modelClassModifier);
|
||||
|
||||
// If operation modifier is abstract then dont generate any body
|
||||
if (isLibrary) {
|
||||
modelClassModifier.setOptValue("");
|
||||
additionalProperties.put(MODEL_CLASS_MODIFIER, modelClassModifier.getOptValue());
|
||||
LOGGER.warn("buildTarget is " + buildTarget.getOptValue() + " so removing any modelClassModifier ");
|
||||
}
|
||||
}
|
||||
|
||||
private void setBuildTarget() {
|
||||
setCliOption(buildTarget);
|
||||
if ("library".equals(buildTarget.getOptValue())) {
|
||||
isLibrary = true;
|
||||
projectSdk = SDK_LIB;
|
||||
additionalProperties.put(CLASS_MODIFIER, "abstract");
|
||||
} else {
|
||||
isLibrary = false;
|
||||
projectSdk = SDK_WEB;
|
||||
}
|
||||
return isLibrary;
|
||||
additionalProperties.put(IS_LIBRARY, isLibrary);
|
||||
}
|
||||
|
||||
private void setAspnetCoreVersion(String packageFolder) {
|
||||
@ -407,4 +457,29 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
|
||||
}
|
||||
additionalProperties.put(COMPATIBILITY_VERSION, compatibilityVersion);
|
||||
}
|
||||
|
||||
private void setUseSwashbuckle() {
|
||||
if (isLibrary) {
|
||||
LOGGER.warn("buildTarget is " + buildTarget.getOptValue() + " so changing default isLibrary to false ");
|
||||
useSwashbuckle = false;
|
||||
} else {
|
||||
useSwashbuckle = true;
|
||||
}
|
||||
if (additionalProperties.containsKey(USE_SWASHBUCKLE)) {
|
||||
useSwashbuckle = convertPropertyToBooleanAndWriteBack(USE_SWASHBUCKLE);
|
||||
} else {
|
||||
additionalProperties.put(USE_SWASHBUCKLE, useSwashbuckle);
|
||||
}
|
||||
}
|
||||
|
||||
private void setOperationIsAsync() {
|
||||
if (isLibrary) {
|
||||
operationIsAsync = false;
|
||||
additionalProperties.put(OPERATION_IS_ASYNC, operationIsAsync);
|
||||
} else if (additionalProperties.containsKey(OPERATION_IS_ASYNC)) {
|
||||
operationIsAsync = convertPropertyToBooleanAndWriteBack(OPERATION_IS_ASYNC);
|
||||
} else {
|
||||
additionalProperties.put(OPERATION_IS_ASYNC, operationIsAsync);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,9 @@
|
||||
<TargetFramework>netcoreapp{{aspnetCoreVersion}}</TargetFramework>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||
{{#isLibrary}}
|
||||
<OutputType>Library</OutputType>
|
||||
{{/isLibrary}}
|
||||
<AssemblyName>{{packageName}}</AssemblyName>
|
||||
<PackageId>{{packageName}}</PackageId>
|
||||
</PropertyGroup>
|
||||
|
@ -17,7 +17,7 @@ Windows:
|
||||
```
|
||||
build.bat
|
||||
```
|
||||
|
||||
{{^isLibrary}}
|
||||
## Run in Docker
|
||||
|
||||
```
|
||||
@ -25,3 +25,4 @@ cd {{sourceFolder}}/{{packageName}}
|
||||
docker build -t {{dockerTag}} .
|
||||
docker run -p 5000:8080 {{dockerTag}}
|
||||
```
|
||||
{{/isLibrary}}
|
@ -44,7 +44,7 @@ namespace {{packageName}}
|
||||
services
|
||||
.AddMvc()
|
||||
{{#compatibilityVersion}}
|
||||
.SetCompatibilityVersion(CompatibilityVersion.{{compatibilityVersion}})
|
||||
.SetCompatibilityVersion (CompatibilityVersion.{{compatibilityVersion}})
|
||||
{{/compatibilityVersion}}
|
||||
.AddJsonOptions(opts =>
|
||||
{
|
||||
@ -109,7 +109,7 @@ namespace {{packageName}}
|
||||
// c.SwaggerEndpoint("/openapi-original.json", "{{#appName}}{{{appName}}}{{/appName}}{{^appName}}{{packageName}}{{/appName}} Original");
|
||||
}){{/useSwashbuckle}};
|
||||
|
||||
if (env.IsDevelopment())
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
@ -1,21 +1,24 @@
|
||||
{{>partial_header}}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;{{#operationResultTask}}
|
||||
using System.Threading.Tasks;
|
||||
{{/operationResultTask}}
|
||||
using Microsoft.AspNetCore.Mvc;{{#useSwashbuckle}}
|
||||
using Swashbuckle.AspNetCore.Annotations;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;{{/useSwashbuckle}}
|
||||
using Newtonsoft.Json;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;{{/useSwashbuckle}}{{^isLibrary}}
|
||||
using Newtonsoft.Json;{{/isLibrary}}
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using {{packageName}}.Attributes;
|
||||
using {{packageName}}.Models;
|
||||
using {{modelPackage}};
|
||||
|
||||
namespace {{packageName}}.Controllers
|
||||
namespace {{apiPackage}}
|
||||
{ {{#operations}}
|
||||
/// <summary>
|
||||
/// {{description}}
|
||||
/// </summary>{{#description}}
|
||||
[Description("{{description}}")]{{/description}}
|
||||
public {{classModifier}} class {{classname}}Controller : ControllerBase
|
||||
[ApiController]
|
||||
public {{#classModifier}}{{classModifier}} {{/classModifier}}class {{classname}}Controller : ControllerBase
|
||||
{ {{#operation}}
|
||||
/// <summary>
|
||||
/// {{#summary}}{{summary}}{{/summary}}
|
||||
@ -27,8 +30,9 @@ namespace {{packageName}}.Controllers
|
||||
[Route("{{{basePathWithoutHost}}}{{{path}}}")]
|
||||
[ValidateModelState]{{#useSwashbuckle}}
|
||||
[SwaggerOperation("{{operationId}}")]{{#responses}}{{#dataType}}
|
||||
[SwaggerResponse(statusCode: {{code}}, type: typeof({{&dataType}}), description: "{{message}}")]{{/dataType}}{{^dataType}}{{/dataType}}{{/responses}}{{/useSwashbuckle}}
|
||||
public {{operationModifier}} IActionResult {{operationId}}({{#allParams}}{{>pathParam}}{{>queryParam}}{{>bodyParam}}{{>formParam}}{{>headerParam}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{^generateBody}};{{/generateBody}}
|
||||
[SwaggerResponse(statusCode: {{code}}, type: typeof({{&dataType}}), description: "{{message}}")]{{/dataType}}{{^dataType}}{{/dataType}}{{/responses}}{{/useSwashbuckle}}{{^useSwashbuckle}}{{#responses}}{{#dataType}}
|
||||
[ProducesResponseType(statusCode: {{code}}, type: typeof({{&dataType}}))]{{/dataType}}{{^dataType}}{{/dataType}}{{/responses}}{{/useSwashbuckle}}
|
||||
public {{operationModifier}} {{#operationResultTask}}{{#operationIsAsync}}async {{/operationIsAsync}}Task<{{/operationResultTask}}IActionResult{{#operationResultTask}}>{{/operationResultTask}} {{operationId}}({{#allParams}}{{>pathParam}}{{>queryParam}}{{>bodyParam}}{{>formParam}}{{>headerParam}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{^generateBody}};{{/generateBody}}
|
||||
{{#generateBody}}
|
||||
{ {{#responses}}
|
||||
{{#dataType}}
|
||||
@ -47,7 +51,7 @@ namespace {{packageName}}.Controllers
|
||||
{{#isListCollection}}{{>listReturn}}{{/isListCollection}}{{^isListCollection}}{{#isMapContainer}}{{>mapReturn}}{{/isMapContainer}}{{^isMapContainer}}{{>objectReturn}}{{/isMapContainer}}{{/isListCollection}}
|
||||
{{!TODO: defaultResponse, examples, auth, consumes, produces, nickname, externalDocs, imports, security}}
|
||||
//TODO: Change the data returned
|
||||
return new ObjectResult(example);{{/returnType}}{{^returnType}}
|
||||
return {{#operationResultTask}}Task.FromResult<IActionResult>({{/operationResultTask}}new ObjectResult(example){{#operationResultTask}}){{/operationResultTask}};{{/returnType}}{{^returnType}}
|
||||
throw new NotImplementedException();{{/returnType}}
|
||||
}
|
||||
{{/generateBody}}
|
||||
|
@ -9,13 +9,13 @@ using Newtonsoft.Json;
|
||||
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
namespace {{packageName}}.Models
|
||||
namespace {{modelPackage}}
|
||||
{ {{#isEnum}}{{>enumClass}}{{/isEnum}}{{^isEnum}}
|
||||
/// <summary>
|
||||
/// {{description}}
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
public partial class {{classname}} : {{#parent}}{{{parent}}}, {{/parent}}IEquatable<{{classname}}>
|
||||
public {{#modelClassModifier}}{{modelClassModifier}} {{/modelClassModifier}} class {{classname}} : {{#parent}}{{{parent}}}, {{/parent}}IEquatable<{{classname}}>
|
||||
{ {{#vars}}{{#isEnum}}{{>enumClass}}{{/isEnum}}{{#items.isEnum}}{{#items}}{{>enumClass}}{{/items}}{{/items.isEnum}}
|
||||
/// <summary>
|
||||
/// {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user