V4 Azure functions + some tweaks (#11345)

* Copying files from LeonB's fork

* Changes as per PR comments

* Resolved merge conflict

Co-authored-by: William Cheng <wing328hk@gmail.com>
This commit is contained in:
Abrhm7786
2022-03-06 15:20:04 +00:00
committed by GitHub
parent 7466bc2ed6
commit be8567f656
33 changed files with 1529 additions and 383 deletions

View File

@@ -81,7 +81,7 @@ The following generators are available:
* [cpp-pistache-server](generators/cpp-pistache-server.md)
* [cpp-qt-qhttpengine-server](generators/cpp-qt-qhttpengine-server.md)
* [cpp-restbed-server](generators/cpp-restbed-server.md)
* [csharp-netcore-functions (beta)](generators/csharp-netcore-functions.md)
* [csharp-netcore-functions](generators/csharp-netcore-functions.md)
* [erlang-server](generators/erlang-server.md)
* [fsharp-functions (beta)](generators/fsharp-functions.md)
* [fsharp-giraffe-server (beta)](generators/fsharp-giraffe-server.md)

View File

@@ -1,6 +1,8 @@
---
title: Documentation for the csharp-netcore-functions Generator
---
These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details.
=======
## METADATA
@@ -15,7 +17,6 @@ title: Documentation for the csharp-netcore-functions Generator
## CONFIG OPTIONS
These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details.
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false|

View File

@@ -16,90 +16,589 @@
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 io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.parameters.Parameter;
import java.io.File;
import java.util.*;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.meta.GeneratorMetadata;
import org.openapitools.codegen.meta.Stability;
import org.openapitools.codegen.meta.features.*;
import org.openapitools.codegen.utils.ModelUtils;
import org.openapitools.codegen.utils.URLPathUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CsharpNetcoreFunctionsServerCodegen extends CSharpNetCoreReducedClientCodegen {
public static final String PROJECT_NAME = "projectName";
import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
final Logger LOGGER = LoggerFactory.getLogger(CsharpNetcoreFunctionsServerCodegen.class);
import static java.util.UUID.randomUUID;
public CodegenType getTag() {
return CodegenType.SERVER;
}
public class CsharpNetcoreFunctionsServerCodegen extends AbstractCSharpCodegen {
public String getName() {
return "csharp-netcore-functions";
}
public static final String NET_CORE_VERSION = "netCoreVersion";
public static final String AZURE_FUNCTIONS_VERSION = "azureFunctionsVersion";
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 TARGET_FRAMEWORK= "targetFramework";
public static final String FUNCTIONS_SDK_VERSION = "functionsSDKVersion";
public String getHelp() {
return "Generates a csharp server.";
}
public static final String COMPATIBILITY_VERSION = "compatibilityVersion";
public static final String USE_NEWTONSOFT = "useNewtonsoft";
public static final String NEWTONSOFT_VERSION = "newtonsoftVersion";
private String packageGuid = "{" + randomUUID().toString().toUpperCase(Locale.ROOT) + "}";
private String userSecretsGuid = randomUUID().toString();
protected final Logger LOGGER = LoggerFactory.getLogger(AspNetCoreServerCodegen.class);
protected int serverPort = 8080;
protected String serverHost = "0.0.0.0";
protected CliOption netCoreVersion = new CliOption(NET_CORE_VERSION, ".NET Core version: 6.0, 5.0, 3.1, 3.0");
protected CliOption azureFunctionsVersion = new CliOption(AZURE_FUNCTIONS_VERSION, "Azure functions version: v4, v3");
private CliOption classModifier = new CliOption(CLASS_MODIFIER, "Class Modifier for function classes: Empty string or abstract.");
private CliOption operationModifier = new CliOption(OPERATION_MODIFIER, "Operation Modifier can be virtual or abstract");
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 = "Microsoft.NET.Sdk";
private boolean operationIsAsync = false;
private boolean operationResultTask = false;
private boolean isLibrary = false;
private boolean useFrameworkReference = false;
private boolean useNewtonsoft = true;
private String newtonsoftVersion = "3.0.0";
public CsharpNetcoreFunctionsServerCodegen() {
super();
generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
.stability(Stability.BETA)
.build();
// TODO: AspnetCore community review
modifyFeatureSet(features -> features
.includeDocumentationFeatures(DocumentationFeature.Readme)
.excludeWireFormatFeatures(WireFormatFeature.PROTOBUF)
.includeSecurityFeatures(
SecurityFeature.ApiKey,
SecurityFeature.BasicAuth,
SecurityFeature.BearerToken
)
.excludeSecurityFeatures(
SecurityFeature.OpenIDConnect,
SecurityFeature.OAuth2_Password,
SecurityFeature.OAuth2_AuthorizationCode,
SecurityFeature.OAuth2_ClientCredentials,
SecurityFeature.OAuth2_Implicit
)
.excludeGlobalFeatures(
GlobalFeature.XMLStructureDefinitions,
GlobalFeature.Callbacks,
GlobalFeature.LinkObjects,
GlobalFeature.ParameterStyling,
GlobalFeature.MultiServer
)
.includeSchemaSupportFeatures(
SchemaSupportFeature.Polymorphism
)
.includeParameterFeatures(
ParameterFeature.Cookie
)
);
outputFolder = "generated-code" + File.separator + getName();
outputFolder = "generated-code" + File.separator + "csharp";
modelTemplateFiles.put("model.mustache", ".cs");
apiTemplateFiles.put("functions.mustache", ".cs");
embeddedTemplateDir = templateDir = "csharp-netcore-functions";
apiPackage = "Apis";
modelPackage = "Models";
String clientPackageDir = "generatedSrc/Client";
supportingFiles.add(new SupportingFile("README.mustache", "generatedSrc", "README.md"));
supportingFiles.add(new SupportingFile("project.mustache", "generatedSrc", "project.json"));
apiTemplateFiles.put("function.mustache", ".cs");
supportingFiles.add(new SupportingFile("IApiAccessor.mustache",
clientPackageDir, "IApiAccessor.cs"));
supportingFiles.add(new SupportingFile("Configuration.mustache",
clientPackageDir, "Configuration.cs"));
supportingFiles.add(new SupportingFile("ApiClient.mustache",
clientPackageDir, "ApiClient.cs"));
supportingFiles.add(new SupportingFile("ApiException.mustache",
clientPackageDir, "ApiException.cs"));
supportingFiles.add(new SupportingFile("ApiResponse.mustache",
clientPackageDir, "ApiResponse.cs"));
supportingFiles.add(new SupportingFile("ExceptionFactory.mustache",
clientPackageDir, "ExceptionFactory.cs"));
supportingFiles.add(new SupportingFile("OpenAPIDateConverter.mustache",
clientPackageDir, "OpenAPIDateConverter.cs"));
embeddedTemplateDir = templateDir = "csharp-netcore-functions";
// contextually reserved words
// NOTE: C# uses camel cased reserved words, while models are title cased. We don't want lowercase comparisons.
reservedWords.addAll(
Arrays.asList("var", "async", "await", "dynamic", "yield")
);
cliOptions.clear();
typeMapping.put("boolean", "bool");
typeMapping.put("integer", "int");
typeMapping.put("float", "float");
typeMapping.put("long", "long");
typeMapping.put("double", "double");
typeMapping.put("number", "decimal");
typeMapping.put("DateTime", "DateTime");
typeMapping.put("date", "DateTime");
typeMapping.put("UUID", "Guid");
typeMapping.put("URI", "string");
setSupportNullable(Boolean.TRUE);
// CLI options
addOption(CodegenConstants.PACKAGE_DESCRIPTION,
CodegenConstants.PACKAGE_DESCRIPTION_DESC,
packageDescription);
addOption(CodegenConstants.LICENSE_URL,
CodegenConstants.LICENSE_URL_DESC,
licenseUrl);
addOption(CodegenConstants.LICENSE_NAME,
CodegenConstants.LICENSE_NAME_DESC,
licenseName);
addOption(CodegenConstants.PACKAGE_COPYRIGHT,
CodegenConstants.PACKAGE_COPYRIGHT_DESC,
packageCopyright);
addOption(CodegenConstants.PACKAGE_AUTHORS,
CodegenConstants.PACKAGE_AUTHORS_DESC,
packageAuthors);
addOption(CodegenConstants.PACKAGE_TITLE,
CodegenConstants.PACKAGE_TITLE_DESC,
packageTitle);
addOption(CodegenConstants.PACKAGE_NAME,
"C# package name (convention: Title.Case).",
packageName);
addOption(CodegenConstants.PACKAGE_VERSION,
"C# package version.",
packageVersion);
addOption(CodegenConstants.OPTIONAL_PROJECT_GUID,
CodegenConstants.OPTIONAL_PROJECT_GUID_DESC,
null);
addOption(CodegenConstants.SOURCE_FOLDER,
CodegenConstants.SOURCE_FOLDER_DESC,
sourceFolder);
netCoreVersion.addEnum("3.0", ".NET Core 3.0");
netCoreVersion.addEnum("3.1", ".NET Core 3.1");
netCoreVersion.addEnum("5.0", ".NET Core 5.0");
netCoreVersion.addEnum("6.0", ".NET Core 6.0");
netCoreVersion.setDefault("3.1");
netCoreVersion.setOptValue(netCoreVersion.getDefault());
cliOptions.add(netCoreVersion);
azureFunctionsVersion.addEnum("v4", "Azure Functions v4");
azureFunctionsVersion.addEnum("v3", "Azure Functions v3");
azureFunctionsVersion.setDefault("v4");
azureFunctionsVersion.setOptValue(azureFunctionsVersion.getDefault());
cliOptions.add(azureFunctionsVersion);
// CLI Switches
addSwitch(CodegenConstants.NULLABLE_REFERENCE_TYPES,
CodegenConstants.NULLABLE_REFERENCE_TYPES_DESC,
this.nullReferenceTypesFlag);
addSwitch(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC,
sortParamsByRequiredFlag);
addSwitch(CodegenConstants.USE_DATETIME_OFFSET,
CodegenConstants.USE_DATETIME_OFFSET_DESC,
useDateTimeOffsetFlag);
addSwitch(CodegenConstants.USE_COLLECTION,
CodegenConstants.USE_COLLECTION_DESC,
useCollection);
addSwitch(CodegenConstants.RETURN_ICOLLECTION,
CodegenConstants.RETURN_ICOLLECTION_DESC,
returnICollection);
addSwitch(USE_NEWTONSOFT,
"Uses the Newtonsoft JSON library.",
useNewtonsoft);
addOption(NEWTONSOFT_VERSION,
"Version for Newtonsoft.Json for .NET Core 3.0+",
newtonsoftVersion);
addOption(CodegenConstants.ENUM_NAME_SUFFIX,
CodegenConstants.ENUM_NAME_SUFFIX_DESC,
enumNameSuffix);
addOption(CodegenConstants.ENUM_VALUE_SUFFIX,
"Suffix that will be appended to all enum values.",
enumValueSuffix);
addSwitch(GENERATE_BODY,
"Generates method body.",
generateBody);
classModifier.addEnum("", "Keep class default with no modifier");
classModifier.addEnum("abstract", "Make class abstract");
classModifier.setDefault("");
classModifier.setOptValue(classModifier.getDefault());
addOption(classModifier.getOpt(), classModifier.getDescription(), classModifier.getOptValue());
operationModifier.addEnum("virtual", "Keep method virtual");
operationModifier.addEnum("abstract", "Make method abstract");
operationModifier.setDefault("virtual");
operationModifier.setOptValue(operationModifier.getDefault());
cliOptions.add(operationModifier);
buildTarget.addEnum("program", "Generate code for a standalone server");
buildTarget.addEnum("library", "Generate code for a server abstract class library");
buildTarget.setDefault("program");
buildTarget.setOptValue(buildTarget.getDefault());
cliOptions.add(buildTarget);
addSwitch(GENERATE_BODY,
"Generates method body.",
generateBody);
addSwitch(OPERATION_IS_ASYNC,
"Set methods to async or sync (default).",
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
public CodegenType getTag() {
return CodegenType.SERVER;
}
@Override
public String getName() {
return "csharp-netcore-functions";
}
@Override
public String getHelp() {
return "Generates an ASP.NET Core Web API server.";
}
@Override
public void preprocessOpenAPI(OpenAPI openAPI) {
super.preprocessOpenAPI(openAPI);
URL url = URLPathUtils.getServerURL(openAPI, serverVariableOverrides());
additionalProperties.put("serverHost", url.getHost());
additionalProperties.put("serverPort", URLPathUtils.getPort(url, 8080));
setApiBasePath();
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_GUID)) {
setPackageGuid((String) additionalProperties.get(CodegenConstants.OPTIONAL_PROJECT_GUID));
}
additionalProperties.put("packageGuid", packageGuid);
additionalProperties.put("userSecretsGuid", userSecretsGuid);
if (!additionalProperties.containsKey(NEWTONSOFT_VERSION)) {
additionalProperties.put(NEWTONSOFT_VERSION, newtonsoftVersion);
} else {
newtonsoftVersion = (String) additionalProperties.get(NEWTONSOFT_VERSION);
}
// Check for the modifiers etc.
// The order of the checks is important.
setClassModifier();
setOperationModifier();
setModelClassModifier();
setOperationIsAsync();
additionalProperties.put("dockerTag", packageName.toLowerCase(Locale.ROOT));
if (!additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) {
apiPackage = packageName + ".Functions";
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;
// determine the ASP.NET core version setting
setAzureFunctionsVersion();
setNetCoreVersion(packageFolder);
setUseNewtonsoft();
// Check for class modifier if not present set the default value.
supportingFiles.add(new SupportingFile("build.sh.mustache", "", "build.sh"));
supportingFiles.add(new SupportingFile("build.bat.mustache", "", "build.bat"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("Solution.mustache", "", packageName + ".sln"));
supportingFiles.add(new SupportingFile("gitignore", packageFolder, ".gitignore"));
supportingFiles.add(new SupportingFile("OpenApi" + File.separator + "TypeExtensions.mustache", packageFolder + File.separator + "OpenApi", "TypeExtensions.cs"));
supportingFiles.add(new SupportingFile("Project.csproj.mustache", packageFolder, packageName + ".csproj"));
supportingFiles.add(new SupportingFile("typeConverter.mustache", packageFolder + File.separator + "Converters", "CustomEnumConverter.cs"));
supportingFiles.add(new SupportingFile("host.json.mustache", packageFolder, "host.json"));
supportingFiles.add(new SupportingFile("local.settings.json.mustache", packageFolder, "local.settings.json"));
}
public void setPackageGuid(String packageGuid) {
this.packageGuid = packageGuid;
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + "generatedSrc" + File.separator + "Functions";
return outputFolder + File.separator + sourceFolder + File.separator + packageName + File.separator + "Functions";
}
@Override
public String modelFileFolder() {
return outputFolder + File.separator + "generatedSrc" + File.separator + "Models";
return outputFolder + File.separator + sourceFolder + File.separator + packageName + File.separator + "Models";
}
@Override
public String apiDocFileFolder() {
return (outputFolder + "/Docs").replace('/', File.separatorChar);
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
generateJSONSpecFile(objs);
return super.postProcessSupportingFileData(objs);
}
@Override
public String apiTestFileFolder() {
return outputFolder + File.separator + "Tests" + File.separator + "Tests" + File.separator + apiPackage();
protected void processOperation(CodegenOperation operation) {
super.processOperation(operation);
// HACK: Unlikely in the wild, but we need to clean operation paths for MVC Routing
if (operation.path != null) {
if (operation.path.startsWith("/"))
{
operation.path = operation.path.substring(1);
}
String original = operation.path;
operation.path = operation.path.replace("?", "/");
if (!original.equals(operation.path)) {
LOGGER.warn("Normalized {} to {}. Please verify generated source.", original, operation.path);
}
}
// Converts, for example, PUT to HttpPut for function attributes
operation.httpMethod = operation.httpMethod.charAt(0) + operation.httpMethod.substring(1).toLowerCase(Locale.ROOT);
}
@Override
public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> objs, List<Object> allModels) {
super.postProcessOperationsWithModels(objs, allModels);
// We need to postprocess the operations to add proper consumes tags and fix form file handling
if (objs != null) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation operation : ops) {
if (operation.consumes == null) {
continue;
}
if (operation.consumes.size() == 0) {
continue;
}
// Build a consumes string for the operation we cannot iterate in the template as we need a ','
// after each entry but the last
StringBuilder consumesString = new StringBuilder();
for (Map<String, String> consume : operation.consumes) {
if (!consume.containsKey("mediaType")) {
continue;
}
if(consumesString.toString().isEmpty()) {
consumesString = new StringBuilder("\"" + consume.get("mediaType") + "\"");
}
else {
consumesString.append(", \"").append(consume.get("mediaType")).append("\"");
}
// In a multipart/form-data consuming context binary data is best handled by an IFormFile
if (!consume.get("mediaType").equals("multipart/form-data")) {
continue;
}
// Change dataType of binary parameters to IFormFile for formParams in multipart/form-data
for (CodegenParameter param : operation.formParams) {
if (param.isBinary) {
param.dataType = "IFormFile";
param.baseType = "IFormFile";
}
}
for (CodegenParameter param : operation.allParams) {
if (param.isBinary && param.isFormParam) {
param.dataType = "IFormFile";
param.baseType = "IFormFile";
}
}
}
if(!consumesString.toString().isEmpty()) {
operation.vendorExtensions.put("x-aspnetcore-consumes", consumesString.toString());
}
}
}
}
return objs;
}
@Override
public Mustache.Compiler processCompiler(Mustache.Compiler compiler) {
// To avoid unexpected behaviors when options are passed programmatically such as { "useCollection": "" }
return super.processCompiler(compiler).emptyStringIsFalse(true);
}
@Override
public String toRegularExpression(String pattern) {
return escapeText(pattern);
}
@SuppressWarnings("rawtypes")
@Override
public String getNullableType(Schema p, String type) {
if (languageSpecificPrimitives.contains(type)) {
if (isSupportNullable() && ModelUtils.isNullable(p) && (nullableType.contains(type) || nullReferenceTypesFlag)) {
return type + "?";
} else {
return type;
}
} else {
return null;
}
}
private void setCliOption(CliOption cliOption) throws IllegalArgumentException {
if (additionalProperties.containsKey(cliOption.getOpt())) {
// 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() {
// CHeck for class modifier if not present set the default value.
setCliOption(classModifier);
// If class modifier is abstract then the methods need to be abstract too.
if ("abstract".equals(classModifier.getOptValue())) {
operationModifier.setOptValue(classModifier.getOptValue());
additionalProperties.put(OPERATION_MODIFIER, operationModifier.getOptValue());
LOGGER.warn("classModifier is {} so forcing operationModifier to {}", classModifier.getOptValue(), operationModifier.getOptValue());
}
}
private void setOperationModifier() {
setCliOption(operationModifier);
// If operation modifier is abstract then dont generate any body
if ("abstract".equals(operationModifier.getOptValue())) {
generateBody = false;
additionalProperties.put(GENERATE_BODY, generateBody);
LOGGER.warn("operationModifier is {} so forcing generateBody to {}", operationModifier.getOptValue(), generateBody);
} else if (additionalProperties.containsKey(GENERATE_BODY)) {
generateBody = convertPropertyToBooleanAndWriteBack(GENERATE_BODY);
} else {
additionalProperties.put(GENERATE_BODY, generateBody);
}
}
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 {} so removing any modelClassModifier ", buildTarget.getOptValue());
}
}
private void setNetCoreVersion(String packageFolder) {
setCliOption(netCoreVersion);
LOGGER.info("ASP.NET core version: {}", netCoreVersion.getOptValue());
}
private void setAzureFunctionsVersion() {
setCliOption(azureFunctionsVersion);
String functionsSDKVersion = "3.0.13";
if ("v4".equals(azureFunctionsVersion.getOptValue())) {
functionsSDKVersion = "4.0.1";
if (!netCoreVersion.getOptValue().startsWith("6.")) {
LOGGER.warn("ASP.NET core version: {} is not compatible with Azure functions v4. Using version 6.0.", netCoreVersion.getOptValue());
netCoreVersion.setOptValue("6.0");
}
}
additionalProperties.put(FUNCTIONS_SDK_VERSION, functionsSDKVersion);
//set .NET target version
String targetFrameworkVersion = "net" + netCoreVersion.getOptValue();
additionalProperties.put(TARGET_FRAMEWORK, targetFrameworkVersion);
}
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);
}
}
private void setUseNewtonsoft() {
if (additionalProperties.containsKey(USE_NEWTONSOFT)) {
useNewtonsoft = convertPropertyToBooleanAndWriteBack(USE_NEWTONSOFT);
} else {
additionalProperties.put(USE_NEWTONSOFT, useNewtonsoft);
}
}
private void setApiBasePath() {
URL url = URLPathUtils.getServerURL(openAPI, serverVariableOverrides());
String apiBasePath = encodePath(url.getPath()).replaceAll("/$", "");
// if a base path exists, remove leading '/' and append trailing '/'
if (apiBasePath != null && apiBasePath.length() > 0) {
if (apiBasePath.startsWith("/"))
apiBasePath = apiBasePath.substring(1);
if (apiBasePath.endsWith("/"))
apiBasePath = apiBasePath.substring(0, apiBasePath.lastIndexOf("/"));
}
additionalProperties.put("apiBasePath", apiBasePath);
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Linq;
using System.Text;
namespace {{packageName}}.OpenApi
{
/// <summary>
/// Replacement utilities from Swashbuckle.AspNetCore.SwaggerGen which are not in 5.x
/// </summary>
public static class TypeExtensions
{
/// <summary>
/// Produce a friendly name for the type which is unique.
/// </summary>
/// <param name="type"></param>
/// <param name="fullyQualified"></param>
public static string FriendlyId(this Type type, bool fullyQualified = false)
{
var typeName = fullyQualified
? type.FullNameSansTypeParameters().Replace("+", ".")
: type.Name;
if (type.IsGenericType)
{
var genericArgumentIds = type.GetGenericArguments()
.Select(t => t.FriendlyId(fullyQualified))
.ToArray();
return new StringBuilder(typeName)
.Replace($"`{genericArgumentIds.Count()}", string.Empty)
.Append($"[{string.Join(",", genericArgumentIds).TrimEnd(',')}]")
.ToString();
}
return typeName;
}
/// <summary>
/// Determine the fully qualified type name without type parameters.
/// </summary>
/// <param name="type"></param>
public static string FullNameSansTypeParameters(this Type type)
{
var fullName = type.FullName;
if (string.IsNullOrEmpty(fullName))
fullName = type.Name;
var chopIndex = fullName.IndexOf("[[", StringComparison.Ordinal);
return (chopIndex == -1) ? fullName : fullName.Substring(0, chopIndex);
}
}
}

View File

@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>{{packageDescription}}{{^packageDescription}}{{packageName}}{{/packageDescription}}</Description>
<Copyright>{{packageCopyright}}</Copyright>
<Authors>{{packageAuthors}}</Authors>
<TargetFramework>{{targetFramework}}</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PreserveCompilationContext>true</PreserveCompilationContext>
<Version>{{packageVersion}}</Version>
<AzureFunctionsVersion>{{azureFunctionsVersion}}</AzureFunctionsVersion>
{{#nullableReferenceTypes}}
<Nullable>annotations</Nullable>
{{/nullableReferenceTypes}}
{{#isLibrary}}
<OutputType>Library</OutputType>
{{/isLibrary}}
<AssemblyName>{{packageName}}</AssemblyName>
<PackageId>{{packageName}}</PackageId>
<UserSecretsId>{{userSecretsGuid}}</UserSecretsId>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<DockerfileContext>..\..</DockerfileContext>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions" Version="4.0.1" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.OpenApi.Core" Version="1.0.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="{{functionsSDKVersion}}" />
<PackageReference Include="Microsoft.OpenApi" Version="1.2.3" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.OpenApi" Version="0.7.2-preview" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>{{packageDescription}}{{^packageDescription}}{{packageName}}{{/packageDescription}}</Description>
<Copyright>{{packageCopyright}}</Copyright>
<Authors>{{packageAuthors}}</Authors>
<TargetFramework>{{targetFramework}}</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PreserveCompilationContext>true</PreserveCompilationContext>
<Version>{{packageVersion}}</Version>
<AzureFunctionsVersion>{{azureFunctionsVersion}}</AzureFunctionsVersion>
{{#nullableReferenceTypes}}
<Nullable>annotations</Nullable>
{{/nullableReferenceTypes}}
{{#isLibrary}}
<OutputType>Library</OutputType>
{{/isLibrary}}
<AssemblyName>{{packageName}}</AssemblyName>
<PackageId>{{packageName}}</PackageId>
<UserSecretsId>{{userSecretsGuid}}</UserSecretsId>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<DockerfileContext>..\..</DockerfileContext>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.OpenApi" Version="0.7.2-preview" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="{{functionsSDKVersion}}" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>$id$</id>
<version>{{packageVersion}}</version>
<title>{{packageTitle}}</title>
<authors>{{packageAuthors}}</authors>
<owners>{{packageAuthors}}</owners>
<licenseUrl>{{licenseUrl}}</licenseUrl>
<!--
<projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
<iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
-->
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>{{packageDescription}}{{^packageDescription}}{{packageName}}{{/packageDescription}}</description>
<releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
<copyright>{{packageCopyright}}</copyright>
<tags>{{packageName}}</tags>
</metadata>
</package>

View File

@@ -1,270 +1,28 @@
# {{packageName}} - the C# library for the {{appName}}
# {{packageName}} - Azure Functions {{azureFunctionsVersion}} Server
{{#appDescriptionWithNewLines}}
{{{appDescriptionWithNewLines}}}
{{{.}}}
{{/appDescriptionWithNewLines}}
This C# SDK is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
## Run
- API version: {{appVersion}}
- SDK version: {{packageVersion}}
{{^hideGenerationTimestamp}}
- Build date: {{generatedDate}}
{{/hideGenerationTimestamp}}
- Build package: {{generatorClass}}
{{#infoUrl}}
For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
{{/infoUrl}}
<a name="frameworks-supported"></a>
## Frameworks supported
{{#netStandard}}
- .NET Core >=1.0
- .NET Framework >=4.6
- Mono/Xamarin >=vNext
{{/netStandard}}
<a name="dependencies"></a>
## Dependencies
{{#useRestSharp}}
- [RestSharp](https://www.nuget.org/packages/RestSharp) - 106.11.7 or later
{{/useRestSharp}}
- [Json.NET](https://www.nuget.org/packages/Newtonsoft.Json/) - 12.0.3 or later
- [JsonSubTypes](https://www.nuget.org/packages/JsonSubTypes/) - 1.8.0 or later
{{#useCompareNetObjects}}
- [CompareNETObjects](https://www.nuget.org/packages/CompareNETObjects) - 4.61.0 or later
{{/useCompareNetObjects}}
{{#validatable}}
- [System.ComponentModel.Annotations](https://www.nuget.org/packages/System.ComponentModel.Annotations) - 5.0.0 or later
{{/validatable}}
The DLLs included in the package may not be the latest version. We recommend using [NuGet](https://docs.nuget.org/consume/installing-nuget) to obtain the latest version of the packages:
```
{{#useRestSharp}}
Install-Package RestSharp
{{/useRestSharp}}
Install-Package Newtonsoft.Json
Install-Package JsonSubTypes
{{#validatable}}
Install-Package System.ComponentModel.Annotations
{{/validatable}}
{{#useCompareNetObjects}}
Install-Package CompareNETObjects
{{/useCompareNetObjects}}
```
{{#useRestSharp}}
NOTE: RestSharp versions greater than 105.1.0 have a bug which causes file uploads to fail. See [RestSharp#742](https://github.com/restsharp/RestSharp/issues/742).
NOTE: RestSharp for .Net Core creates a new socket for each api call, which can lead to a socket exhaustion problem. See [RestSharp#1406](https://github.com/restsharp/RestSharp/issues/1406).
{{/useRestSharp}}
<a name="installation"></a>
## Installation
{{#netStandard}}
Generate the DLL using your preferred tool (e.g. `dotnet build`)
{{/netStandard}}
{{^netStandard}}
Run the following command to generate the DLL
- [Mac/Linux] `/bin/sh build.sh`
- [Windows] `build.bat`
{{/netStandard}}
Then include the DLL (under the `bin` folder) in the C# project, and use the namespaces:
```csharp
using {{packageName}}.{{apiPackage}};
using {{packageName}}.Client;
using {{packageName}}.{{modelPackage}};
```
{{^netStandard}}
<a name="packaging"></a>
## Packaging
A `.nuspec` is included with the project. You can follow the Nuget quickstart to [create](https://docs.microsoft.com/en-us/nuget/quickstart/create-and-publish-a-package#create-the-package) and [publish](https://docs.microsoft.com/en-us/nuget/quickstart/create-and-publish-a-package#publish-the-package) packages.
This `.nuspec` uses placeholders from the `.csproj`, so build the `.csproj` directly:
Linux/OS X:
```
nuget pack -Build -OutputDirectory out {{packageName}}.csproj
sh build.sh
```
Then, publish to a [local feed](https://docs.microsoft.com/en-us/nuget/hosting-packages/local-feeds) or [other host](https://docs.microsoft.com/en-us/nuget/hosting-packages/overview) and consume the new package via Nuget as usual.
Windows:
{{/netStandard}}
<a name="usage"></a>
## Usage
To use the API client with a HTTP proxy, setup a `System.Net.WebProxy`
```csharp
Configuration c = new Configuration();
System.Net.WebProxy webProxy = new System.Net.WebProxy("http://myProxyUrl:80/");
webProxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
c.Proxy = webProxy;
```
{{#useHttpClient}}
### Connections
Each ApiClass (properly the ApiClient inside it) will create an istance of HttpClient. It will use that for the entire lifecycle and dispose it when called the Dispose method.
To better manager the connections it's a common practice to reuse the HttpClient and HttpClientHander (see [here](https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests#issues-with-the-original-httpclient-class-available-in-net) for details). To use your own HttpClient instance just pass it to the ApiClass constructor.
```csharp
HttpClientHandler yourHandler = new HttpClientHandler();
HttpClient yourHttpClient = new HttpClient(yourHandler);
var api = new YourApiClass(yourHttpClient, yourHandler);
build.bat
```
{{^isLibrary}}
## Run in Docker
If you want to use an HttpClient and don't have access to the handler, for example in a DI context in Asp.net Core when using IHttpClientFactory.
```csharp
HttpClient yourHttpClient = new HttpClient();
var api = new YourApiClass(yourHttpClient);
```
You'll loose some configuration settings, the features affected are: Setting and Retrieving Cookies, Client Certificates, Proxy settings. You need to either manually handle those in your setup of the HttpClient or they won't be available.
Here an example of DI setup in a sample web project:
```csharp
services.AddHttpClient<YourApiClass>(httpClient =>
new PetApi(httpClient));
cd {{sourceFolder}}/{{packageName}}
docker build -t {{dockerTag}} .
docker run -p 5000:8080 {{dockerTag}}
```
{{/useHttpClient}}
<a name="getting-started"></a>
## Getting Started
```csharp
using System.Collections.Generic;
using System.Diagnostics;
{{#useHttpClient}}
using System.Net.Http;
{{/useHttpClient}}
using {{packageName}}.{{apiPackage}};
using {{packageName}}.Client;
using {{packageName}}.{{modelPackage}};
namespace Example
{
public class {{operationId}}Example
{
public static void Main()
{
{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}}
Configuration config = new Configuration();
config.BasePath = "{{{basePath}}}";
{{#hasAuthMethods}}
{{#authMethods}}
{{#isBasicBasic}}
// Configure HTTP basic authorization: {{{name}}}
config.Username = "YOUR_USERNAME";
config.Password = "YOUR_PASSWORD";
{{/isBasicBasic}}
{{#isBasicBearer}}
// Configure Bearer token for authorization: {{{name}}}
config.AccessToken = "YOUR_BEARER_TOKEN";
{{/isBasicBearer}}
{{#isApiKey}}
// Configure API key authorization: {{{name}}}
config.ApiKey.Add("{{{keyParamName}}}", "YOUR_API_KEY");
// Uncomment below to setup prefix (e.g. Bearer) for API key, if needed
// config.ApiKeyPrefix.Add("{{{keyParamName}}}", "Bearer");
{{/isApiKey}}
{{#isOAuth}}
// Configure OAuth2 access token for authorization: {{{name}}}
config.AccessToken = "YOUR_ACCESS_TOKEN";
{{/isOAuth}}
{{/authMethods}}
{{/hasAuthMethods}}
{{#useHttpClient}}
// create instances of HttpClient, HttpClientHandler to be reused later with different Api classes
HttpClient httpClient = new HttpClient();
HttpClientHandler httpClientHandler = new HttpClientHandler();
var apiInstance = new {{classname}}(httpClient, config, httpClientHandler);
{{/useHttpClient}}
{{^useHttpClient}}
var apiInstance = new {{classname}}(config);
{{/useHttpClient}}
{{#allParams}}
{{#isPrimitiveType}}
var {{paramName}} = {{{example}}}; // {{{dataType}}} | {{{description}}}{{^required}} (optional) {{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}
{{/isPrimitiveType}}
{{^isPrimitiveType}}
var {{paramName}} = new {{{dataType}}}(); // {{{dataType}}} | {{{description}}}{{^required}} (optional) {{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}
{{/isPrimitiveType}}
{{/allParams}}
try
{
{{#summary}}
// {{{.}}}
{{/summary}}
{{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}}
Debug.WriteLine(result);{{/returnType}}
}
catch (ApiException e)
{
Debug.Print("Exception when calling {{classname}}.{{operationId}}: " + e.Message );
Debug.Print("Status Code: "+ e.ErrorCode);
Debug.Print(e.StackTrace);
}
{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}}
}
}
}
```
<a name="documentation-for-api-endpoints"></a>
## Documentation for API Endpoints
All URIs are relative to *{{{basePath}}}*
Class | Method | HTTP request | Description
------------ | ------------- | ------------- | -------------
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{{summary}}}{{/summary}}
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
<a name="documentation-for-models"></a>
## Documentation for Models
{{#modelPackage}}
{{#models}}{{#model}} - [{{{modelPackage}}}.{{{classname}}}]({{modelDocPath}}{{{classname}}}.md)
{{/model}}{{/models}}
{{/modelPackage}}
{{^modelPackage}}
No model defined in this package
{{/modelPackage}}
<a name="documentation-for-authorization"></a>
## Documentation for Authorization
{{^authMethods}}
All endpoints do not require authorization.
{{/authMethods}}
{{#authMethods}}
{{#last}}
Authentication schemes defined for the API:
{{/last}}
{{/authMethods}}
{{#authMethods}}
<a name="{{name}}"></a>
### {{name}}
{{#isApiKey}}- **Type**: API key
- **API key parameter name**: {{keyParamName}}
- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}}
{{/isApiKey}}
{{#isBasicBasic}}- **Type**: HTTP basic authentication
{{/isBasicBasic}}
{{#isBasicBearer}}- **Type**: Bearer Authentication
{{/isBasicBearer}}
{{#isOAuth}}- **Type**: OAuth
- **Flow**: {{flow}}
- **Authorization URL**: {{authorizationUrl}}
- **Scopes**: {{^scopes}}N/A{{/scopes}}
{{#scopes}} - {{scope}}: {{description}}
{{/scopes}}
{{/isOAuth}}
{{/authMethods}}
{{/isLibrary}}

View File

@@ -1,27 +1,22 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio {{^netStandard}}2012{{/netStandard}}{{#netStandard}}14{{/netStandard}}
VisualStudioVersion = {{^netStandard}}12.0.0.0{{/netStandard}}{{#netStandard}}14.0.25420.1{{/netStandard}}
MinimumVisualStudioVersion = {{^netStandard}}10.0.0.1{{/netStandard}}{{#netStandard}}10.0.40219.1{{/netStandard}}
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "{{packageName}}", "src\{{packageName}}\{{packageName}}.csproj", "{{packageGuid}}"
# Visual Studio 15
VisualStudioVersion = 15.0.27428.2043
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "{{packageName}}", "{{sourceFolder}}\{{packageName}}\{{packageName}}.csproj", "{{packageGuid}}"
EndProject
{{^excludeTests}}Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "{{testPackageName}}", "src\{{testPackageName}}\{{testPackageName}}.csproj", "{19F1DEBC-DE5E-4517-8062-F000CD499087}"
EndProject
{{/excludeTests}}Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{{packageGuid}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{{packageGuid}}.Debug|Any CPU.Build.0 = Debug|Any CPU
{{packageGuid}}.Release|Any CPU.ActiveCfg = Release|Any CPU
{{packageGuid}}.Release|Any CPU.Build.0 = Release|Any CPU
{19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{{packageGuid}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{{packageGuid}}.Debug|Any CPU.Build.0 = Debug|Any CPU
{{packageGuid}}.Release|Any CPU.ActiveCfg = Release|Any CPU
{{packageGuid}}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@@ -0,0 +1 @@
{{#isBodyParam}}[FromBody]{{&dataType}} {{paramName}}{{/isBodyParam}}

View File

@@ -0,0 +1,9 @@
:: Generated by: https://openapi-generator.tech
::
@echo off
dotnet restore {{sourceFolder}}\{{packageName}}
dotnet build {{sourceFolder}}\{{packageName}}
echo Now, run the following to start the project: dotnet run -p {{sourceFolder}}\{{packageName}}\{{packageName}}.csproj --launch-profile web.
echo.

View File

@@ -0,0 +1,8 @@
#!/usr/bin/env bash
#
# Generated by: https://openapi-generator.tech
#
dotnet restore {{sourceFolder}}/{{packageName}}/ && \
dotnet build {{sourceFolder}}/{{packageName}}/ && \
echo "Now, run the following to start the project: func start"

View File

@@ -0,0 +1,88 @@
{{>partial_header}}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
{{#operationResultTask}}
using System.Threading.Tasks;
{{/operationResultTask}}
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
{{#useSwashbuckle}}
using Swashbuckle.AspNetCore.Annotations;
using Swashbuckle.AspNetCore.SwaggerGen;
{{/useSwashbuckle}}
{{^isLibrary}}
using Newtonsoft.Json;
{{/isLibrary}}
using {{packageName}}.Attributes;
using {{modelPackage}};
namespace {{apiPackage}}
{ {{#operations}}
/// <summary>
/// {{description}}
/// </summary>{{#description}}
[Description("{{.}}")]{{/description}}
[ApiController]
public {{#classModifier}}{{.}} {{/classModifier}}class {{classname}}Controller : ControllerBase
{ {{#operation}}
/// <summary>
/// {{summary}}
/// </summary>{{#notes}}
/// <remarks>{{.}}</remarks>{{/notes}}{{#allParams}}
/// <param name="{{paramName}}">{{description}}{{#isDeprecated}} (deprecated){{/isDeprecated}}</param>{{/allParams}}{{#responses}}
/// <response code="{{code}}">{{message}}</response>{{/responses}}
[{{httpMethod}}]
[Route("{{{basePathWithoutHost}}}{{{path}}}")]
{{#authMethods}}
{{#isApiKey}}
[Authorize(Policy = "{{name}}")]
{{/isApiKey}}
{{#isBasicBearer}}
[Authorize{{#scopes}}{{#-first}}(Roles = "{{/-first}}{{scope}}{{^-last}},{{/-last}}{{#-last}}"){{/-last}}{{/scopes}}]
{{/isBasicBearer}}
{{/authMethods}}
{{#vendorExtensions.x-aspnetcore-consumes}}
[Consumes({{&vendorExtensions.x-aspnetcore-consumes}})]
{{/vendorExtensions.x-aspnetcore-consumes}}
[ValidateModelState]{{#useSwashbuckle}}
[SwaggerOperation("{{operationId}}")]{{#responses}}{{#dataType}}
[SwaggerResponse(statusCode: {{code}}, type: typeof({{&dataType}}), description: "{{message}}")]{{/dataType}}{{/responses}}{{/useSwashbuckle}}{{^useSwashbuckle}}{{#responses}}{{#dataType}}
[ProducesResponseType(statusCode: {{code}}, type: typeof({{&dataType}}))]{{/dataType}}{{/responses}}{{/useSwashbuckle}}
{{#isDeprecated}}
[Obsolete]
{{/isDeprecated}}
public {{operationModifier}} {{#operationResultTask}}{{#operationIsAsync}}async {{/operationIsAsync}}Task<{{/operationResultTask}}IActionResult{{#operationResultTask}}>{{/operationResultTask}} {{operationId}}({{#allParams}}{{>pathParam}}{{>queryParam}}{{>bodyParam}}{{>formParam}}{{>headerParam}}{{^-last}}{{^isCookieParam}}, {{/isCookieParam}}{{/-last}}{{/allParams}}){{^generateBody}};{{/generateBody}}
{{#generateBody}}
{
{{#cookieParams}}
var {{paramName}} = Request.Cookies["{{paramName}}"];
{{/cookieParams}}
{{#responses}}
{{#dataType}}
//TODO: Uncomment the next line to return response {{code}} or use other options such as return this.NotFound(), return this.BadRequest(..), ...
// return StatusCode({{code}}, default({{&dataType}}));
{{/dataType}}
{{^dataType}}
//TODO: Uncomment the next line to return response {{code}} or use other options such as return this.NotFound(), return this.BadRequest(..), ...
// return StatusCode({{code}});
{{/dataType}}
{{/responses}}
{{#returnType}}
string exampleJson = null;
{{#examples}}
exampleJson = "{{{example}}}";
{{/examples}}
{{#isListCollection}}{{>listReturn}}{{/isListCollection}}{{^isListCollection}}{{#isMap}}{{>mapReturn}}{{/isMap}}{{^isMap}}{{>objectReturn}}{{/isMap}}{{/isListCollection}}
{{!TODO: defaultResponse, examples, auth, consumes, produces, nickname, externalDocs, imports, security}}
//TODO: Change the data returned
return {{#operationResultTask}}Task.FromResult<IActionResult>({{/operationResultTask}}new ObjectResult(example){{#operationResultTask}}){{/operationResultTask}};{{/returnType}}{{^returnType}}
throw new NotImplementedException();{{/returnType}}
}
{{/generateBody}}
{{/operation}}
}
{{/operations}}
}

View File

@@ -0,0 +1,19 @@
/// <summary>
/// {{^description}}Gets or Sets {{{name}}}{{/description}}{{{description}}}
/// </summary>
{{#description}}
/// <value>{{{.}}}</value>
{{/description}}
{{#allowableValues}}{{#enumVars}}{{#-first}}{{#isString}}[TypeConverter(typeof(CustomEnumConverter<{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}>))]
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]{{/isString}}{{/-first}}{{/enumVars}}{{/allowableValues}}
public enum {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}
{
{{#allowableValues}}{{#enumVars}}
/// <summary>
/// Enum {{name}} for {{{value}}}
/// </summary>
{{#isString}}[EnumMember(Value = "{{{value}}}")]{{/isString}}
{{name}}{{^isString}} = {{{value}}}{{/isString}}{{#isString}} = {{-index}}{{/isString}}{{^-last}},
{{/-last}}{{/enumVars}}{{/allowableValues}}
}

View File

@@ -0,0 +1 @@
{{#isFormParam}}{{^isBinary}}[FromForm{{^isModel}} (Name = "{{baseName}}"){{/isModel}}]{{/isBinary}}{{#required}}[Required()]{{/required}}{{#pattern}}[RegularExpression("{{{.}}}")]{{/pattern}}{{#minLength}}{{#maxLength}}[StringLength({{maxLength}}, MinimumLength={{minLength}})]{{/maxLength}}{{/minLength}}{{#minLength}}{{^maxLength}} [MinLength({{minLength}})]{{/maxLength}}{{/minLength}}{{^minLength}}{{#maxLength}} [MaxLength({{.}})]{{/maxLength}}{{/minLength}}{{#minimum}}{{#maximum}}[Range({{minimum}}, {{maximum}})]{{/maximum}}{{/minimum}}{{&dataType}} {{paramName}}{{/isFormParam}}

View File

@@ -0,0 +1,33 @@
using System.IO;
using System.Net;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json;
namespace {{apiPackage}}
{ {{#operations}}
public partial {{#classModifier}}{{classModifier}} {{/classModifier}}class {{classname}}
{ {{#operation}}
[FunctionName("{{classname}}_{{operationId}}")]
public async Task<IActionResult> _{{operationId}}([HttpTrigger(AuthorizationLevel.Anonymous, "{{httpMethod}}", Route = "{{{apiBasePath}}}{{{path}}}")]HttpRequest req, ExecutionContext context{{#allParams}}{{#isPathParam}}, {{>pathParam}}{{/isPathParam}}{{/allParams}}){{^generateBody}};{{/generateBody}}
{{#generateBody}}
{
var method = this.GetType().GetMethod("{{operationId}}");
return method != null
? (await ((Task<IActionResult>)method.Invoke(this, new object[] { req, context{{#allParams}}{{#isPathParam}}, {{>paramName}}{{/isPathParam}}{{/allParams}} })).ConfigureAwait(false))
: new StatusCodeResult((int)HttpStatusCode.NotImplemented);
}
{{/generateBody}}
{{/operation}}
}
{{/operations}}
}

View File

@@ -0,0 +1,33 @@
using System.IO;
using System.Net;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json;
namespace {{apiPackage}}
{ {{#operations}}
public partial {{#classModifier}}{{classModifier}} {{/classModifier}}class {{classname}}
{ {{#operation}}
[FunctionName("{{classname}}_{{operationId}}")]
public async Task<IActionResult> _{{operationId}}([HttpTrigger(AuthorizationLevel.Anonymous, "{{httpMethod}}", Route = "{{{path}}}")]HttpRequest req, ExecutionContext context{{#allParams}}{{#isPathParam}}, {{>pathParam}}{{/isPathParam}}{{/allParams}}){{^generateBody}};{{/generateBody}}
{{#generateBody}}
{
var method = this.GetType().GetMethod("{{operationId}}");
return method != null
? (await ((Task<IActionResult>)method.Invoke(this, new object[] { req, context{{#allParams}}{{#isPathParam}}, {{>paramName}}{{/isPathParam}}{{/allParams}} })).ConfigureAwait(false))
: new StatusCodeResult((int)HttpStatusCode.NotImplemented);
}
{{/generateBody}}
{{/operation}}
}
{{/operations}}
}

View File

@@ -0,0 +1,362 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd

View File

@@ -0,0 +1 @@
{{#isHeaderParam}}[FromHeader]{{#required}}[Required()]{{/required}}{{#pattern}}[RegularExpression("{{{.}}}")]{{/pattern}}{{#minLength}}{{#maxLength}}[StringLength({{maxLength}}, MinimumLength={{minLength}})]{{/maxLength}}{{/minLength}}{{#minLength}}{{^maxLength}} [MinLength({{minLength}})]{{/maxLength}}{{/minLength}}{{^minLength}}{{#maxLength}} [MaxLength({{.}})]{{/maxLength}}{{/minLength}}{{#minimum}}{{#maximum}}[Range({{minimum}}, {{maximum}})]{{/maximum}}{{/minimum}}{{&dataType}} {{paramName}}{{/isHeaderParam}}

View File

@@ -0,0 +1,11 @@
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
}
}

View File

@@ -0,0 +1,4 @@
var example = exampleJson != null
? JsonConvert.DeserializeObject<{{returnContainer}}<{{{returnType}}}>>(exampleJson)
: Enumerable.Empty<{{{returnType}}}>();

View File

@@ -0,0 +1,7 @@
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
}
}

View File

@@ -0,0 +1,4 @@
var example = exampleJson != null
? JsonConvert.DeserializeObject<Dictionary<{{{returnType}}}>>(exampleJson)
: new Dictionary<{{{returnType}}}>();

View File

@@ -1,47 +1,160 @@
{{>partial_header}}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using {{packageName}}.Converters;
{{#models}}
{{#model}}
{{#discriminator}}
using JsonSubTypes;
{{/discriminator}}
{{/model}}
{{/models}}
{{#validatable}}
using System.ComponentModel.DataAnnotations;
{{/validatable}}
using OpenAPIDateConverter = {{packageName}}.Client.OpenAPIDateConverter;
{{#useCompareNetObjects}}
using OpenAPIClientUtils = {{packageName}}.Client.ClientUtils;
{{/useCompareNetObjects}}
{{#models}}
{{#model}}
{{#oneOf}}
{{#-first}}
using System.Reflection;
{{/-first}}
{{/oneOf}}
{{#aneOf}}
{{#-first}}
using System.Reflection;
{{/-first}}
{{/aneOf}}
namespace {{modelPackage}}
{ {{#isEnum}}{{>enumClass}}{{/isEnum}}{{^isEnum}}
/// <summary>
/// {{description}}
/// </summary>
[DataContract]
public {{#modelClassModifier}}{{.}} {{/modelClassModifier}}class {{classname}} : {{#parent}}{{{.}}}, {{/parent}}IEquatable<{{classname}}>
{
{{#vars}}
{{#items.isEnum}}
{{#items}}
{{^complexType}}
{{>enumClass}}
{{/complexType}}
{{/items}}
{{/items.isEnum}}
{{^items.isEnum}}
{{#isEnum}}
{{^complexType}}
{{>enumClass}}
{{/complexType}}
{{/isEnum}}
{{/items.isEnum}}
/// <summary>
/// {{description}}{{^description}}Gets or Sets {{{name}}}{{/description}}
/// </summary>{{#description}}
/// <value>{{.}}</value>{{/description}}{{#required}}
[Required]{{/required}}{{#pattern}}
[RegularExpression("{{{.}}}")]{{/pattern}}{{#minLength}}{{#maxLength}}
[StringLength({{maxLength}}, MinimumLength={{minLength}})]{{/maxLength}}{{/minLength}}{{#minLength}}{{^maxLength}}
[MinLength({{minLength}})]{{/maxLength}}{{/minLength}}{{^minLength}}{{#maxLength}}
[MaxLength({{.}})]{{/maxLength}}{{/minLength}}{{#minimum}}{{#maximum}}
[Range({{minimum}}, {{maximum}})]{{/maximum}}{{/minimum}}
[DataMember(Name="{{baseName}}", EmitDefaultValue={{#isNullable}}true{{/isNullable}}{{^isNullable}}false{{/isNullable}})]
{{#isEnum}}
public {{{datatypeWithEnum}}}{{#isNullable}}?{{/isNullable}} {{name}} { get; set; }{{#defaultValue}} = {{{.}}};{{/defaultValue}}
{{/isEnum}}
{{^isEnum}}
public {{{dataType}}} {{name}} { get; {{#isReadOnly}}private {{/isReadOnly}}set; }{{#defaultValue}} = {{{.}}};{{/defaultValue}}
{{/isEnum}}
{{^-last}}
namespace {{packageName}}.{{modelPackage}}
{
{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#oneOf}}{{#-first}}{{>modelOneOf}}{{/-first}}{{/oneOf}}{{#anyOf}}{{#-first}}{{>modelAnyOf}}{{/-first}}{{/anyOf}}{{^oneOf}}{{^anyOf}}{{>modelGeneric}}{{/anyOf}}{{/oneOf}}{{/isEnum}}
{{/-last}}
{{/vars}}
/// <summary>
/// Returns the string presentation of the object
/// </summary>
/// <returns>String presentation of the object</returns>
public override string ToString()
{
var sb = new StringBuilder();
sb.Append("class {{classname}} {\n");
{{#vars}}
sb.Append(" {{name}}: ").Append({{name}}).Append("\n");
{{/vars}}
sb.Append("}\n");
return sb.ToString();
}
/// <summary>
/// Returns the JSON string presentation of the object
/// </summary>
/// <returns>JSON string presentation of the object</returns>
public {{#parent}}{{^isMap}}{{^isArray}}new {{/isArray}}{{/isMap}}{{/parent}}string ToJson()
{
return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented);
}
/// <summary>
/// Returns true if objects are equal
/// </summary>
/// <param name="obj">Object to be compared</param>
/// <returns>Boolean</returns>
public override bool Equals(object obj)
{
if (obj is null) return false;
if (ReferenceEquals(this, obj)) return true;
return obj.GetType() == GetType() && Equals(({{classname}})obj);
}
/// <summary>
/// Returns true if {{classname}} instances are equal
/// </summary>
/// <param name="other">Instance of {{classname}} to be compared</param>
/// <returns>Boolean</returns>
public bool Equals({{classname}} other)
{
if (other is null) return false;
if (ReferenceEquals(this, other)) return true;
return {{#vars}}{{^isContainer}}
(
{{name}} == other.{{name}} ||
{{^vendorExtensions.x-is-value-type}}{{name}} != null &&{{/vendorExtensions.x-is-value-type}}
{{name}}.Equals(other.{{name}})
){{^-last}} && {{/-last}}{{/isContainer}}{{#isContainer}}
(
{{name}} == other.{{name}} ||
{{^vendorExtensions.x-is-value-type}}{{name}} != null &&
other.{{name}} != null &&
{{/vendorExtensions.x-is-value-type}}{{name}}.SequenceEqual(other.{{name}})
){{^-last}} && {{/-last}}{{/isContainer}}{{/vars}}{{^vars}}false{{/vars}};
}
/// <summary>
/// Gets the hash code
/// </summary>
/// <returns>Hash code</returns>
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
var hashCode = 41;
// Suitable nullity checks etc, of course :)
{{#vars}}
{{^vendorExtensions.x-is-value-type}}if ({{name}} != null){{/vendorExtensions.x-is-value-type}}
hashCode = hashCode * 59 + {{name}}.GetHashCode();
{{/vars}}
return hashCode;
}
}
#region Operators
#pragma warning disable 1591
public static bool operator ==({{classname}} left, {{classname}} right)
{
return Equals(left, right);
}
public static bool operator !=({{classname}} left, {{classname}} right)
{
return !Equals(left, right);
}
#pragma warning restore 1591
#endregion Operators
}
{{/isEnum}}
{{/model}}
{{/models}}
}

View File

@@ -0,0 +1,4 @@
var example = exampleJson != null
? JsonConvert.DeserializeObject<{{{returnType}}}>(exampleJson)
: default({{{returnType}}});

View File

@@ -0,0 +1 @@
{{paramName}}

View File

@@ -1,17 +1,13 @@
/*
{{#appName}}
* {{{appName}}}
* {{{.}}}
*
{{/appName}}
{{#appDescription}}
* {{{appDescription}}}
* {{{.}}}
*
{{/appDescription}}
{{#version}}
* The version of the OpenAPI document: {{{version}}}
{{/version}}
{{#infoEmail}}
* Contact: {{{infoEmail}}}
{{/infoEmail}}
* Generated by: https://github.com/openapitools/openapi-generator.git
* {{#version}}The version of the OpenAPI document: {{{.}}}{{/version}}
* {{#infoEmail}}Contact: {{{.}}}{{/infoEmail}}
* Generated by: https://openapi-generator.tech
*/

View File

@@ -0,0 +1 @@
{{#isQueryParam}}[FromQuery]{{#required}}[Required()]{{/required}}{{#pattern}}[RegularExpression("{{{pattern}}}")]{{/pattern}}{{#minLength}}{{#maxLength}}[StringLength({{maxLength}}, MinimumLength={{minLength}})]{{/maxLength}}{{/minLength}}{{#minLength}}{{^maxLength}} [MinLength({{minLength}})]{{/maxLength}}{{/minLength}}{{^minLength}}{{#maxLength}} [MaxLength({{maxLength}})]{{/maxLength}}{{/minLength}}{{#minimum}}{{#maximum}}[Range({{minimum}}, {{maximum}})]{{/maximum}}{{/minimum}}{{&dataType}} {{paramName}}{{/isQueryParam}}

View File

@@ -0,0 +1 @@
{{!TODO: Need iterable tags object...}}{{#tags}}, Tags = new[] { {{/tags}}"{{#tags}}{{tag}} {{/tags}}"{{#tags}} }{{/tags}}

View File

@@ -0,0 +1,33 @@
using System;
using System.ComponentModel;
using System.Globalization;
using Newtonsoft.Json;
namespace {{packageName}}.Converters
{
/// <summary>
/// Custom string to enum converter
/// </summary>
public class CustomEnumConverter<T> : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var s = value as string;
if (string.IsNullOrEmpty(s))
{
return null;
}
return JsonConvert.DeserializeObject<T>(@"""" + value.ToString() + @"""");
}
}
}

View File

@@ -27,11 +27,11 @@ public class CsharpNetcoreFunctionsServerCodegenTest {
final CsharpNetcoreFunctionsServerCodegen codegen = new CsharpNetcoreFunctionsServerCodegen();
codegen.processOpts();
Assert.assertEquals(codegen.toEnumVarName("FooBar", "string"), "FooBar");
Assert.assertEquals(codegen.toEnumVarName("fooBar", "string"), "FooBar");
Assert.assertEquals(codegen.toEnumVarName("foo-bar", "string"), "FooBar");
Assert.assertEquals(codegen.toEnumVarName("foo_bar", "string"), "FooBar");
Assert.assertEquals(codegen.toEnumVarName("foo bar", "string"), "FooBar");
Assert.assertEquals(codegen.toEnumVarName("FooBar", "string"), "FooBarEnum");
Assert.assertEquals(codegen.toEnumVarName("fooBar", "string"), "FooBarEnum");
Assert.assertEquals(codegen.toEnumVarName("foo-bar", "string"), "FooBarEnum");
Assert.assertEquals(codegen.toEnumVarName("foo_bar", "string"), "FooBarEnum");
Assert.assertEquals(codegen.toEnumVarName("foo bar", "string"), "FooBarEnum");
// The below cases do not work currently, camelize doesn't support uppercase
// Assert.assertEquals(codegen.toEnumVarName("FOO-BAR", "string"), "FooBar");