Skip to content

Commit e4cbaa7

Browse files
phatcherwing328shibayan
authored
Implement Asp.Net Core 3.0/3.1 generator (#6009) (#6025)
* Minor changes to 2.1 templates to make them work or improve documentation * Support for ASP.NET Core 3.0 and 3.1 * Update aspnetcore test scripts and results * Update generated documentation * update doc * Update modules/openapi-generator/src/main/resources/aspnetcore/3.0/Startup.mustache Co-Authored-By: Tatsuro Shibamura <[email protected]> * Update modules/openapi-generator/src/main/resources/aspnetcore/3.0/Startup.mustache Co-Authored-By: Tatsuro Shibamura <[email protected]> Co-authored-by: William Cheng <[email protected]> Co-authored-by: Tatsuro Shibamura <[email protected]>
1 parent f8a7475 commit e4cbaa7

File tree

81 files changed

+5139
-51
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+5139
-51
lines changed

bin/aspnetcore3-petstore-server.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/usr/bin/env bash
2+
3+
SCRIPT="$0"
4+
echo "# START SCRIPT: $SCRIPT"
5+
6+
while [ -h "$SCRIPT" ] ; do
7+
ls=`ls -ld "$SCRIPT"`
8+
link=`expr "$ls" : '.*-> \(.*\)$'`
9+
if expr "$link" : '/.*' > /dev/null; then
10+
SCRIPT="$link"
11+
else
12+
SCRIPT=`dirname "$SCRIPT"`/"$link"
13+
fi
14+
done
15+
16+
if [ ! -d "${APP_DIR}" ]; then
17+
APP_DIR=`dirname "$SCRIPT"`/..
18+
APP_DIR=`cd "${APP_DIR}"; pwd`
19+
fi
20+
21+
executable="./modules/openapi-generator-cli/target/openapi-generator-cli.jar"
22+
23+
if [ ! -f "$executable" ]
24+
then
25+
mvn -B clean package
26+
fi
27+
28+
# if you've executed sbt assembly previously it will use that instead.
29+
export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties"
30+
ags="generate -g aspnetcore -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -t modules/openapi-generator/src/main/resources/aspnetcore/3.0/ -o samples/server/petstore/aspnetcore3 --additional-properties packageGuid={3C799344-F285-4669-8FD5-7ED9B795D5C5} --additional-properties aspnetCoreVersion=3.0 $@"
31+
32+
java $JAVA_OPTS -jar $executable $ags
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
set executable=.\modules\openapi-generator-cli\target\openapi-generator-cli.jar
2+
3+
If Not Exist %executable% (
4+
mvn clean package
5+
)
6+
7+
REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -DloggerPath=conf/log4j.properties
8+
set ags=generate -i modules\openapi-generator\src\test\resources\2_0\petstore.yaml -g aspnetcore -o samples\server\petstore\aspnetcore3\ --additional-properties packageGuid={3C799344-F285-4669-8FD5-7ED9B795D5C5} --additional-properties aspnetCoreVersion=3.0
9+
10+
java %JAVA_OPTS% -jar %executable% %ags%

docs/generators/aspnetcore.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ sidebar_label: aspnetcore
55

66
| Option | Description | Values | Default |
77
| ------ | ----------- | ------ | ------- |
8-
|aspnetCoreVersion|ASP.NET Core version: 3.0 (preview4 only), 2.2, 2.1, 2.0 (deprecated)| |2.2|
8+
|aspnetCoreVersion|ASP.NET Core version: 3.1, 3.0, 2.2, 2.1, 2.0 (deprecated)| |2.2|
99
|buildTarget|Target to build an application or library| |program|
1010
|classModifier|Class Modifier can be empty, abstract| ||
1111
|compatibilityVersion|ASP.Net Core CompatibilityVersion| |Version_2_2|
@@ -16,7 +16,7 @@ sidebar_label: aspnetcore
1616
|licenseName|The name of the license| |NoLicense|
1717
|licenseUrl|The URL of the license| |http://localhost|
1818
|modelClassModifier|Model Class Modifier can be nothing or partial| |partial|
19-
|newtonsoftVersion|Version for Microsoft.AspNetCore.Mvc.NewtonsoftJson for ASP.NET Core 3.0+| |3.0.0-preview5-19227-01|
19+
|newtonsoftVersion|Version for Microsoft.AspNetCore.Mvc.NewtonsoftJson for ASP.NET Core 3.0+| |3.0.0|
2020
|operationIsAsync|Set methods to async or sync (default).| |false|
2121
|operationModifier|Operation Modifier can be virtual, abstract or partial| |virtual|
2222
|operationResultTask|Set methods result to Task&lt;&gt;.| |false|
@@ -29,11 +29,11 @@ sidebar_label: aspnetcore
2929
|returnICollection|Return ICollection&lt;T&gt; instead of the concrete type.| |false|
3030
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
3131
|sourceFolder|source folder for generated code| |src|
32-
|swashbuckleVersion|Swashbucke version: 3.0.0, 4.0.0| |3.0.0|
32+
|swashbuckleVersion|Swashbuckle version: 3.0.0, 4.0.0, 5.0.0| |3.0.0|
3333
|useCollection|Deserialize array types to Collection&lt;T&gt; instead of List&lt;T&gt;.| |false|
3434
|useDateTimeOffset|Use DateTimeOffset to model date-time properties| |false|
35-
|useDefaultRouting|Use default routing for the ASP.NET Core version. For 3.0 turn off default because it is not yet supported.| |true|
36-
|useFrameworkReference|Use frameworkReference for ASP.NET Core 3.0+ and PackageReference ASP.NET Core 2.2 or earlier.| |false|
35+
|useDefaultRouting|Use default routing for the ASP.NET Core version.| |true|
36+
|useFrameworkReference|Use frameworkReference for ASP.NET Core 3.0+ and PackageReference ASP.NET Core 2.2 or earlier.| |false|
3737
|useNewtonsoft|Uses the Newtonsoft JSON library.| |true|
3838
|useSwashbuckle|Uses the Swashbuckle.AspNetCore NuGet package for documentation.| |true|
3939

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AspNetCoreServerCodegen.java

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,16 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
6060
public static final String NEWTONSOFT_VERSION = "newtonsoftVersion";
6161

6262
private String packageGuid = "{" + randomUUID().toString().toUpperCase(Locale.ROOT) + "}";
63+
private String userSecretsGuid = randomUUID().toString();
6364

6465
@SuppressWarnings("hiding")
6566
protected Logger LOGGER = LoggerFactory.getLogger(AspNetCoreServerCodegen.class);
6667

6768
private boolean useSwashbuckle = true;
6869
protected int serverPort = 8080;
6970
protected String serverHost = "0.0.0.0";
70-
protected CliOption swashbuckleVersion = new CliOption(SWASHBUCKLE_VERSION, "Swashbucke version: 3.0.0, 4.0.0");
71-
; // default to 2.1
72-
protected CliOption aspnetCoreVersion = new CliOption(ASPNET_CORE_VERSION, "ASP.NET Core version: 3.0 (preview4 only), 2.2, 2.1, 2.0 (deprecated)");
71+
protected CliOption swashbuckleVersion = new CliOption(SWASHBUCKLE_VERSION, "Swashbuckle version: 3.0.0, 4.0.0, 5.0.0");
72+
protected CliOption aspnetCoreVersion = new CliOption(ASPNET_CORE_VERSION, "ASP.NET Core version: 3.1, 3.0, 2.2, 2.1, 2.0 (deprecated)");
7373
private CliOption classModifier = new CliOption(CLASS_MODIFIER, "Class Modifier can be empty, abstract");
7474
private CliOption operationModifier = new CliOption(OPERATION_MODIFIER, "Operation Modifier can be virtual, abstract or partial");
7575
private CliOption modelClassModifier = new CliOption(MODEL_CLASS_MODIFIER, "Model Class Modifier can be nothing or partial");
@@ -83,7 +83,7 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
8383
private boolean useFrameworkReference = false;
8484
private boolean useNewtonsoft = true;
8585
private boolean useDefaultRouting = true;
86-
private String newtonsoftVersion = "3.0.0-preview5-19227-01";
86+
private String newtonsoftVersion = "3.0.0";
8787

8888
public AspNetCoreServerCodegen() {
8989
super();
@@ -186,10 +186,11 @@ public AspNetCoreServerCodegen() {
186186

187187
addOption(COMPATIBILITY_VERSION, "ASP.Net Core CompatibilityVersion", compatibilityVersion);
188188

189-
aspnetCoreVersion.addEnum("2.0", "ASP.NET COre 2.0");
189+
aspnetCoreVersion.addEnum("2.0", "ASP.NET Core 2.0");
190190
aspnetCoreVersion.addEnum("2.1", "ASP.NET Core 2.1");
191191
aspnetCoreVersion.addEnum("2.2", "ASP.NET Core 2.2");
192192
aspnetCoreVersion.addEnum("3.0", "ASP.NET Core 3.0");
193+
aspnetCoreVersion.addEnum("3.1", "ASP.NET Core 3.1");
193194
aspnetCoreVersion.setDefault("2.2");
194195
aspnetCoreVersion.setOptValue(aspnetCoreVersion.getDefault());
195196
addOption(aspnetCoreVersion.getOpt(), aspnetCoreVersion.getDescription(), aspnetCoreVersion.getOptValue());
@@ -227,7 +228,7 @@ public AspNetCoreServerCodegen() {
227228
isLibrary);
228229

229230
addSwitch(USE_FRAMEWORK_REFERENCE,
230-
"Use frameworkReference for ASP.NET Core 3.0+ and PackageReference ASP.NET Core 2.2 or earlier.",
231+
"Use frameworkReference for ASP.NET Core 3.0+ and PackageReference ASP.NET Core 2.2 or earlier.",
231232
useFrameworkReference);
232233

233234
addSwitch(USE_NEWTONSOFT,
@@ -239,7 +240,7 @@ public AspNetCoreServerCodegen() {
239240
newtonsoftVersion);
240241

241242
addSwitch(USE_DEFAULT_ROUTING,
242-
"Use default routing for the ASP.NET Core version. For 3.0 turn off default because it is not yet supported.",
243+
"Use default routing for the ASP.NET Core version.",
243244
useDefaultRouting);
244245

245246
addOption(CodegenConstants.ENUM_NAME_SUFFIX,
@@ -263,7 +264,7 @@ public AspNetCoreServerCodegen() {
263264
addOption(operationModifier.getOpt(), operationModifier.getDescription(), operationModifier.getOptValue());
264265

265266
buildTarget.addEnum("program", "Generate code for a standalone server");
266-
buildTarget.addEnum("library", "Generate code for a server abstract class lbrary");
267+
buildTarget.addEnum("library", "Generate code for a server abstract class library");
267268
buildTarget.setDefault("program");
268269
buildTarget.setOptValue(buildTarget.getDefault());
269270
addOption(buildTarget.getOpt(), buildTarget.getDescription(), buildTarget.getOptValue());
@@ -286,7 +287,6 @@ public AspNetCoreServerCodegen() {
286287
modelClassModifier.setDefault("partial");
287288
modelClassModifier.setOptValue(modelClassModifier.getDefault());
288289
addOption(modelClassModifier.getOpt(), modelClassModifier.getDescription(), modelClassModifier.getOptValue());
289-
290290
}
291291

292292
@Override
@@ -320,6 +320,7 @@ public void processOpts() {
320320
setPackageGuid((String) additionalProperties.get(CodegenConstants.OPTIONAL_PROJECT_GUID));
321321
}
322322
additionalProperties.put("packageGuid", packageGuid);
323+
additionalProperties.put("userSecretsGuid", userSecretsGuid);
323324

324325
if (!additionalProperties.containsKey(NEWTONSOFT_VERSION)) {
325326
additionalProperties.put(NEWTONSOFT_VERSION, newtonsoftVersion);
@@ -367,6 +368,9 @@ public void processOpts() {
367368
supportingFiles.add(new SupportingFile("gitignore", packageFolder, ".gitignore"));
368369
supportingFiles.add(new SupportingFile("validateModel.mustache", packageFolder + File.separator + "Attributes", "ValidateModelStateAttribute.cs"));
369370
supportingFiles.add(new SupportingFile("typeConverter.mustache", packageFolder + File.separator + "Converters", "CustomEnumConverter.cs"));
371+
if (aspnetCoreVersion.getOptValue().startsWith("3.")) {
372+
supportingFiles.add(new SupportingFile("OpenApi" + File.separator + "TypeExtensions.mustache", packageFolder + File.separator + "OpenApi", "TypeExtensions.cs"));
373+
}
370374
supportingFiles.add(new SupportingFile("Project.csproj.mustache", packageFolder, packageName + ".csproj"));
371375
if (!isLibrary) {
372376
supportingFiles.add(new SupportingFile("Dockerfile.mustache", packageFolder, "Dockerfile"));
@@ -532,19 +536,34 @@ private void setBuildTarget() {
532536

533537
private void setAspnetCoreVersion(String packageFolder) {
534538
setCliOption(aspnetCoreVersion);
535-
if ("2.0".equals(aspnetCoreVersion.getOptValue())) {
536-
embeddedTemplateDir = templateDir = "aspnetcore/2.0";
539+
540+
if (aspnetCoreVersion.getOptValue().startsWith("3.")) {
541+
compatibilityVersion = null;
542+
} else if ("2.0".equals(aspnetCoreVersion.getOptValue())) {
537543
supportingFiles.add(new SupportingFile("web.config", packageFolder, "web.config"));
538-
LOGGER.info("ASP.NET core version: 2.0");
539544
compatibilityVersion = null;
540545
} else {
541546
// default, do nothing
542-
LOGGER.info("ASP.NET core version: " + aspnetCoreVersion.getOptValue());
543547
compatibilityVersion = "Version_" + aspnetCoreVersion.getOptValue().replace(".", "_");
544548
}
549+
LOGGER.info("ASP.NET core version: " + aspnetCoreVersion.getOptValue());
550+
embeddedTemplateDir = templateDir = "aspnetcore/" + determineTemplateVersion(aspnetCoreVersion.getOptValue());
545551
additionalProperties.put(COMPATIBILITY_VERSION, compatibilityVersion);
546552
}
547553

554+
private String determineTemplateVersion(String frameworkVersion) {
555+
switch (frameworkVersion) {
556+
case "3.1":
557+
return "3.0";
558+
559+
case "2.2":
560+
return "2.1";
561+
562+
default:
563+
return frameworkVersion;
564+
}
565+
}
566+
548567
private void setUseSwashbuckle() {
549568
if (isLibrary) {
550569
LOGGER.warn("buildTarget is " + buildTarget.getOptValue() + " so changing default isLibrary to false ");
@@ -572,7 +591,7 @@ private void setOperationIsAsync() {
572591

573592
private void setIsFramework() {
574593
if (aspnetCoreVersion.getOptValue().startsWith("3.")) {// default, do nothing
575-
LOGGER.warn("ASP.NET core version is " + aspnetCoreVersion.getOptValue() + " so changing to use frameworkReference instead of packageReference ");
594+
LOGGER.warn("ASP.NET core version is " + aspnetCoreVersion.getOptValue() + " so changing to use frameworkReference instead of packageReference ");
576595
useFrameworkReference = true;
577596
additionalProperties.put(USE_FRAMEWORK_REFERENCE, useFrameworkReference);
578597
} else {
@@ -582,7 +601,6 @@ private void setIsFramework() {
582601
additionalProperties.put(USE_FRAMEWORK_REFERENCE, useFrameworkReference);
583602
}
584603
}
585-
586604
}
587605

588606
private void setUseNewtonsoft() {
@@ -617,8 +635,8 @@ private void setSwashbuckleVersion() {
617635
setCliOption(swashbuckleVersion);
618636

619637
if (aspnetCoreVersion.getOptValue().startsWith("3.")) {
620-
LOGGER.warn("ASP.NET core version is " + aspnetCoreVersion.getOptValue() + " so changing default Swashbuckle version to 4.0.0.");
621-
swashbuckleVersion.setOptValue("4.0.0");
638+
LOGGER.warn("ASP.NET core version is " + aspnetCoreVersion.getOptValue() + " so changing default Swashbuckle version to 5.0.0.");
639+
swashbuckleVersion.setOptValue("5.0.0");
622640
additionalProperties.put(SWASHBUCKLE_VERSION, swashbuckleVersion.getOptValue());
623641
} else {
624642
// default, do nothing

modules/openapi-generator/src/main/resources/aspnetcore/2.1/Authentication/ApiAuthentication.mustache

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,39 @@ using System.Threading.Tasks;
77

88
namespace {{packageName}}.Authentication
99
{
10+
/// <summary>
11+
/// A requirement that an ApiKey must be present.
12+
/// </summary>
1013
public class ApiKeyRequirement : IAuthorizationRequirement
1114
{
12-
public IReadOnlyList<string> ApiKeys { get; set; }
13-
14-
public string PolicyName { get; set; }
15+
/// <summary>
16+
/// Get the list of api keys
17+
/// </summary>
18+
public IReadOnlyList<string> ApiKeys { get; }
1519

20+
/// <summary>
21+
/// Get the policy name,
22+
/// </summary>
23+
public string PolicyName { get; }
24+
25+
/// <summary>
26+
/// Create a new instance of the <see cref="ApiKeyRequirement"/> class.
27+
/// </summary>
28+
/// <param name="apiKeys"></param>
29+
/// <param name="policyName"></param>
1630
public ApiKeyRequirement(IEnumerable<string> apiKeys, string policyName)
1731
{
1832
ApiKeys = apiKeys?.ToList() ?? new List<string>();
1933
PolicyName = policyName;
2034
}
2135
}
2236

37+
/// <summary>
38+
/// Enforce that an api key is present.
39+
/// </summary>
2340
public class ApiKeyRequirementHandler : AuthorizationHandler<ApiKeyRequirement>
2441
{
25-
42+
/// <copydoc cref="AuthorizationHandler{T}.HandleRequirementAsync" />
2643
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ApiKeyRequirement requirement)
2744
{
2845
SucceedRequirementIfApiKeyPresentAndValid(context, requirement);
@@ -32,27 +49,22 @@ namespace {{packageName}}.Authentication
3249
private void SucceedRequirementIfApiKeyPresentAndValid(AuthorizationHandlerContext context, ApiKeyRequirement requirement)
3350
{
3451
{{#authMethods}}{{#isApiKey}}
35-
{{#-first}}
3652
if (context.Resource is AuthorizationFilterContext authorizationFilterContext)
3753
{
38-
var apiKey = "";
39-
{{/-first}}
4054
{{#isKeyInHeader}}
41-
apiKey = authorizationFilterContext.HttpContext.Request.Headers["{{keyParamName}}"].FirstOrDefault();
55+
var apiKey = authorizationFilterContext.HttpContext.Request.Headers["{{keyParamName}}"].FirstOrDefault();
4256
{{/isKeyInHeader}}
4357
{{#isKeyInQuery}}
44-
apiKey = authorizationFilterContext.HttpContext.Request.Query["{{keyParamName}}"].FirstOrDefault();
58+
var apiKey = authorizationFilterContext.HttpContext.Request.Query["{{keyParamName}}"].FirstOrDefault();
4559
{{/isKeyInQuery}}
4660
{{#isKeyInCookie}}
47-
apiKey = authorizationFilterContext.HttpContext.Request.Cookies["{{keyParamName}}"] ?? null;
61+
var apiKey = authorizationFilterContext.HttpContext.Request.Cookies["{{keyParamName}}"] ?? null;
4862
{{/isKeyInCookie}}
4963
if (requirement.PolicyName == "{{name}}" && apiKey != null && requirement.ApiKeys.Any(requiredApiKey => apiKey == requiredApiKey))
5064
{
5165
context.Succeed(requirement);
5266
}
53-
{{#-last}}
5467
}
55-
{{/-last}}
5668
{{/isApiKey}}{{/authMethods}}
5769
}
5870
}

modules/openapi-generator/src/main/resources/aspnetcore/2.1/Project.csproj.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@
2929
{{/useSwashbuckle}}
3030
</ItemGroup>
3131
<ItemGroup>
32-
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.3" />
32+
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.4" />
3333
</ItemGroup>
3434
</Project>

modules/openapi-generator/src/main/resources/aspnetcore/2.1/README.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# {{packageName}} - ASP.NET Core 2.0 Server
1+
# {{packageName}} - ASP.NET Core {{aspnetCoreVersion}} Server
22

33
{{#appDescriptionWithNewLines}}
44
{{{appDescriptionWithNewLines}}}

modules/openapi-generator/src/main/resources/aspnetcore/2.1/Startup.mustache

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,13 @@ namespace {{packageName}}
4444
{
4545
{{#authMethods}}
4646
{{#isApiKey}}
47-
{{#-first}}
4847
services.AddTransient<IAuthorizationHandler, ApiKeyRequirementHandler>();
4948
services.AddAuthorization(authConfig =>
5049
{
51-
{{/-first}}
5250
authConfig.AddPolicy("{{name}}",
5351
policyBuilder => policyBuilder
5452
.AddRequirements(new ApiKeyRequirement(new[] { "my-secret-key" },"{{name}}")));
55-
{{#-last}}
5653
});
57-
{{/-last}}
5854
{{/isApiKey}}
5955
{{/authMethods}}
6056

@@ -81,7 +77,7 @@ namespace {{packageName}}
8177
{
8278
Version = "{{#version}}{{{version}}}{{/version}}{{^version}}v1{{/version}}",
8379
Title = "{{#appName}}{{{appName}}}{{/appName}}{{^appName}}{{packageName}}{{/appName}}",
84-
Description = "{{#appName}}{{{appName}}}{{/appName}}{{^appName}}{{packageName}}{{/appName}} (ASP.NET Core 2.0)",
80+
Description = "{{#appName}}{{{appName}}}{{/appName}}{{^appName}}{{packageName}}{{/appName}} (ASP.NET Core {{aspnetCoreVersion}})",
8581
Contact = new Contact()
8682
{
8783
Name = "{{#infoName}}{{{infoName}}}{{/infoName}}{{^infoName}}OpenAPI-Generator Contributors{{/infoName}}",

0 commit comments

Comments
 (0)