[csharp] Add a server generator for FastEndpoints (#19690)

* Add of a first working generator for FastEndpoints framework

Generator that support the basics of a FastEndpoints project
https://fast-endpoints.com/

* Add respose code documentation support

* Add an option to enable use of problem details

* Clean enum and model

* Add an option to generate record for requests/models

* Update sample

* Add support of nullable types

* Add option to enable authentication

* Add option to generate validators

* Clean readme.md file

* Add option to enable response caching

* update readme template

* Add missing files references

* Update generated sample

* Add link to documentation

* Add generator documentation

* correctly support packageName

supportingFiles additions moved to processOpts()

* improve useAuthentication option handling

Avoid to copy an empty file

* processOpts, move call to parent at the end

* Update generated sample

* Refactor and fix super.processOpts(); call order

* Handle the case of multi-line description

* Rename field to match naming conventions

* Add useApiVersioning option

* Update generated sample

* Add generator documentation

* Fix record when model contains optional properties

* Add configuration files for each option

* Add sample project for each configuration

* Add GitHub Action workflow for sample projects

* Add FastEndpoints BindFrom attribute on path, query and form params

* Update sample generated projects

* Fix validator template

* fix alphabetical order

* Use fully qualified name for FastEndpoints

* Add options to set GUID to be used in sln file

* update sample projects

* Update generators.md

* Fix path in github workflow

* Put readme, gitignore and solution file at the root of generated project

* update sample projects

* Remove the projectGuid option

This Guid need to be constant, it is related to project type

* update sample projects
This commit is contained in:
Julien Tschäppät 2024-11-07 13:28:29 +01:00 committed by GitHub
parent e2553a4a91
commit 7deecdc569
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
196 changed files with 14406 additions and 0 deletions

View File

@ -0,0 +1,34 @@
name: Samples C# .Net 8 FastEndpoints Server
on:
push:
paths:
- samples/server/petstore/aspnet/fastendpoints/**
- samples/server/petstore/aspnet/fastendpoints-*/**
pull_request:
paths:
- samples/server/petstore/aspnet/fastendpoints/**
- samples/server/petstore/aspnet/fastendpoints-*/**
jobs:
build:
name: Build .Net 8 FastEndpoints servers
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
sample:
- samples/server/petstore/aspnet/fastendpoints
- samples/server/petstore/aspnet/fastendpoints-useApiVersioning
- samples/server/petstore/aspnet/fastendpoints-useAuthentication
- samples/server/petstore/aspnet/fastendpoints-useProblemDetails
- samples/server/petstore/aspnet/fastendpoints-useRecords
- samples/server/petstore/aspnet/fastendpoints-useResponseCaching
- samples/server/petstore/aspnet/fastendpoints-useValidators
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4.0.1
with:
dotnet-version: '8.0.x'
- name: Build
working-directory: ${{ matrix.sample }}
run: dotnet build Org.OpenAPITools.sln

View File

@ -0,0 +1,16 @@
generatorName: aspnet-fastendpoints
outputDir: samples/server/petstore/aspnet/fastendpoints-useApiVersioning
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/aspnet-fastendpoints
additionalProperties:
hideGenerationTimestamp: "true"
useProblemDetails: "false"
useRecords: "false"
useAuthentication: "false"
useValidators: "false"
useResponseCaching: "false"
useApiVersioning: "true"
routePrefix: "api"
versionPrefix: "v"
solutionGuid: "{1EC59EB0-DA5B-40C0-8E49-A3E0829DBBFC}"
projectConfigurationGuid: "{9685C490-9B77-4EE2-BE4D-811F52665E8F}"

View File

@ -0,0 +1,16 @@
generatorName: aspnet-fastendpoints
outputDir: samples/server/petstore/aspnet/fastendpoints-useAuthentication
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/aspnet-fastendpoints
additionalProperties:
hideGenerationTimestamp: "true"
useProblemDetails: "false"
useRecords: "false"
useAuthentication: "true"
useValidators: "false"
useResponseCaching: "false"
useApiVersioning: "false"
routePrefix: "api"
versionPrefix: "v"
solutionGuid: "{10D45F9B-F270-480C-9DA9-720AA62526A4}"
projectConfigurationGuid: "{3FA19D58-AE7C-45E5-B00E-7482026D1816}"

View File

@ -0,0 +1,16 @@
generatorName: aspnet-fastendpoints
outputDir: samples/server/petstore/aspnet/fastendpoints-useProblemDetails
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/aspnet-fastendpoints
additionalProperties:
hideGenerationTimestamp: "true"
useProblemDetails: "true"
useRecords: "false"
useAuthentication: "false"
useValidators: "false"
useResponseCaching: "false"
useApiVersioning: "false"
routePrefix: "api"
versionPrefix: "v"
solutionGuid: "{EA9B735E-72CA-44C4-BB28-358BDECE60C8}"
projectConfigurationGuid: "{74D68BAC-36F5-43FC-BE9A-F3E660EECF5D}"

View File

@ -0,0 +1,16 @@
generatorName: aspnet-fastendpoints
outputDir: samples/server/petstore/aspnet/fastendpoints-useRecords
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/aspnet-fastendpoints
additionalProperties:
hideGenerationTimestamp: "true"
useProblemDetails: "false"
useRecords: "true"
useAuthentication: "false"
useValidators: "false"
useResponseCaching: "false"
useApiVersioning: "false"
routePrefix: "api"
versionPrefix: "v"
solutionGuid: "{C5D2BEB0-AB74-433F-BC14-DA66CAC82C10}"
projectConfigurationGuid: "{D465FD3B-3146-4661-BB50-522608AA3967}"

View File

@ -0,0 +1,16 @@
generatorName: aspnet-fastendpoints
outputDir: samples/server/petstore/aspnet/fastendpoints-useResponseCaching
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/aspnet-fastendpoints
additionalProperties:
hideGenerationTimestamp: "true"
useProblemDetails: "false"
useRecords: "false"
useAuthentication: "false"
useValidators: "false"
useResponseCaching: "true"
useApiVersioning: "false"
routePrefix: "api"
versionPrefix: "v"
solutionGuid: "{BC56C2A3-ACC5-4ED0-AD8F-CD1831B8A467}"
projectConfigurationGuid: "{5D19ACAB-8830-47FD-BAFA-C0985DF9F5F3}"

View File

@ -0,0 +1,16 @@
generatorName: aspnet-fastendpoints
outputDir: samples/server/petstore/aspnet/fastendpoints-useValidators
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/aspnet-fastendpoints
additionalProperties:
hideGenerationTimestamp: "true"
useProblemDetails: "false"
useRecords: "false"
useAuthentication: "false"
useValidators: "true"
useResponseCaching: "false"
useApiVersioning: "false"
routePrefix: "api"
versionPrefix: "v"
solutionGuid: "{C7818EE1-09E2-4349-9696-8B1A9119974A}"
projectConfigurationGuid: "{39B801D8-74AA-465D-A637-4A2FFB905378}"

View File

@ -0,0 +1,16 @@
generatorName: aspnet-fastendpoints
outputDir: samples/server/petstore/aspnet/fastendpoints
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/aspnet-fastendpoints
additionalProperties:
hideGenerationTimestamp: "true"
useProblemDetails: "false"
useRecords: "false"
useAuthentication: "false"
useValidators: "false"
useResponseCaching: "false"
useApiVersioning: "false"
routePrefix: "api"
versionPrefix: "v"
solutionGuid: "{4BC03566-F5F9-4E45-A835-8FA3B2B524B9}"
projectConfigurationGuid: "{5F32A09C-5CB7-4917-83AB-CD7D1A04FF49}"

View File

@ -84,6 +84,7 @@ The following generators are available:
## SERVER generators
* [ada-server](generators/ada-server.md)
* [aspnet-fastendpoints](generators/aspnet-fastendpoints.md)
* [aspnetcore](generators/aspnetcore.md)
* [cpp-pistache-server](generators/cpp-pistache-server.md)
* [cpp-qt-qhttpengine-server](generators/cpp-qt-qhttpengine-server.md)

View File

@ -0,0 +1,321 @@
---
title: Documentation for the aspnet-fastendpoints Generator
---
## METADATA
| Property | Value | Notes |
| -------- | ----- | ----- |
| generator name | aspnet-fastendpoints | pass this to the generate command after -g |
| generator stability | STABLE | |
| generator type | SERVER | |
| generator language | C# | |
| generator default templating engine | mustache | |
| helpTxt | Generates a server for FastEndpoints (https://fast-endpoints.com/). | |
## 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|
|apiVersion|The version of the API. Used only if useApiVersioning is true| |1|
|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|<dl><dt>**false**</dt><dd>The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.</dd><dt>**true**</dt><dd>Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.</dd></dl>|true|
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response.With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|<dl><dt>**false**</dt><dd>No changes to the enum's are made, this is the default option.</dd><dt>**true**</dt><dd>With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case.</dd></dl>|false|
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|true|
|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|
|projectConfigurationGuid|The project configuration GUID to be used in the solution file (auto generated if not provided)| |null|
|routePrefix|The route prefix for the API. Used only if useApiVersioning is true| |api|
|solutionGuid|The solution GUID to be used in the solution file (auto generated if not provided)| |null|
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|useApiVersioning|Enable API versioning (https://fast-endpoints.com/docs/api-versioning).| |false|
|useAuthentication|Enable authentication (https://fast-endpoints.com/docs/security).| |false|
|useProblemDetails|Enable RFC compatible error responses (https://fast-endpoints.com/docs/configuration-settings#rfc7807-rfc9457-compatible-problem-details).| |false|
|useRecords|Use record instead of class for the requests and response.| |false|
|useResponseCaching|Enable response caching (https://fast-endpoints.com/docs/response-caching).| |false|
|useValidators|Enable request validators (https://fast-endpoints.com/docs/validation).| |false|
|versioningPrefix|The versioning prefix for the API. Used only if useApiVersioning is true| |v|
## IMPORT MAPPING
| Type/Alias | Imports |
| ---------- | ------- |
## INSTANTIATION TYPES
| Type/Alias | Instantiated By |
| ---------- | --------------- |
|array|List|
|list|List|
|map|Dictionary|
## LANGUAGE PRIMITIVES
<ul class="column-ul">
<li>Boolean</li>
<li>Collection</li>
<li>DateOnly</li>
<li>DateOnly?</li>
<li>DateTime</li>
<li>DateTime?</li>
<li>DateTimeOffset</li>
<li>DateTimeOffset?</li>
<li>Decimal</li>
<li>Dictionary</li>
<li>Double</li>
<li>Float</li>
<li>Guid</li>
<li>Guid?</li>
<li>ICollection</li>
<li>Int32</li>
<li>Int64</li>
<li>List</li>
<li>Object</li>
<li>String</li>
<li>System.IO.Stream</li>
<li>bool</li>
<li>bool?</li>
<li>byte[]</li>
<li>decimal</li>
<li>decimal?</li>
<li>double</li>
<li>double?</li>
<li>float</li>
<li>float?</li>
<li>int</li>
<li>int?</li>
<li>long</li>
<li>long?</li>
<li>string</li>
<li>uint</li>
<li>uint?</li>
<li>ulong</li>
<li>ulong?</li>
</ul>
## RESERVED WORDS
<ul class="column-ul">
<li>Client</li>
<li>Configuration</li>
<li>Environment</li>
<li>OperatingSystem</li>
<li>TimeZone</li>
<li>Version</li>
<li>abstract</li>
<li>as</li>
<li>base</li>
<li>bool</li>
<li>break</li>
<li>byte</li>
<li>case</li>
<li>catch</li>
<li>char</li>
<li>checked</li>
<li>class</li>
<li>client</li>
<li>const</li>
<li>continue</li>
<li>decimal</li>
<li>default</li>
<li>delegate</li>
<li>do</li>
<li>double</li>
<li>else</li>
<li>enum</li>
<li>event</li>
<li>explicit</li>
<li>extern</li>
<li>false</li>
<li>finally</li>
<li>fixed</li>
<li>float</li>
<li>for</li>
<li>foreach</li>
<li>goto</li>
<li>if</li>
<li>implicit</li>
<li>in</li>
<li>int</li>
<li>interface</li>
<li>internal</li>
<li>is</li>
<li>localVarFileParams</li>
<li>localVarFormParams</li>
<li>localVarHeaderParams</li>
<li>localVarHttpContentType</li>
<li>localVarHttpContentTypes</li>
<li>localVarHttpHeaderAccept</li>
<li>localVarHttpHeaderAccepts</li>
<li>localVarPath</li>
<li>localVarPathParams</li>
<li>localVarPostBody</li>
<li>localVarQueryParams</li>
<li>localVarResponse</li>
<li>localVarStatusCode</li>
<li>lock</li>
<li>long</li>
<li>namespace</li>
<li>new</li>
<li>null</li>
<li>object</li>
<li>operator</li>
<li>out</li>
<li>override</li>
<li>parameter</li>
<li>params</li>
<li>private</li>
<li>protected</li>
<li>public</li>
<li>readonly</li>
<li>ref</li>
<li>return</li>
<li>sbyte</li>
<li>sealed</li>
<li>short</li>
<li>sizeof</li>
<li>stackalloc</li>
<li>static</li>
<li>string</li>
<li>struct</li>
<li>switch</li>
<li>system</li>
<li>this</li>
<li>throw</li>
<li>true</li>
<li>try</li>
<li>typeof</li>
<li>uint</li>
<li>ulong</li>
<li>unchecked</li>
<li>unsafe</li>
<li>ushort</li>
<li>using</li>
<li>virtual</li>
<li>void</li>
<li>volatile</li>
<li>while</li>
</ul>
## FEATURE SET
### Client Modification Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|BasePath|✗|ToolingExtension
|Authorizations|✗|ToolingExtension
|UserAgent|✗|ToolingExtension
|MockServer|✗|ToolingExtension
### Data Type Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Custom|✗|OAS2,OAS3
|Int32|✓|OAS2,OAS3
|Int64|✓|OAS2,OAS3
|Float|✓|OAS2,OAS3
|Double|✓|OAS2,OAS3
|Decimal|✓|ToolingExtension
|String|✓|OAS2,OAS3
|Byte|✓|OAS2,OAS3
|Binary|✓|OAS2,OAS3
|Boolean|✓|OAS2,OAS3
|Date|✓|OAS2,OAS3
|DateTime|✓|OAS2,OAS3
|Password|✓|OAS2,OAS3
|File|✓|OAS2
|Uuid|✗|
|Array|✓|OAS2,OAS3
|Null|✗|OAS3
|AnyType|✗|OAS2,OAS3
|Object|✓|OAS2,OAS3
|Maps|✓|ToolingExtension
|CollectionFormat|✓|OAS2
|CollectionFormatMulti|✓|OAS2
|Enum|✓|OAS2,OAS3
|ArrayOfEnum|✓|ToolingExtension
|ArrayOfModel|✓|ToolingExtension
|ArrayOfCollectionOfPrimitives|✓|ToolingExtension
|ArrayOfCollectionOfModel|✓|ToolingExtension
|ArrayOfCollectionOfEnum|✓|ToolingExtension
|MapOfEnum|✓|ToolingExtension
|MapOfModel|✓|ToolingExtension
|MapOfCollectionOfPrimitives|✓|ToolingExtension
|MapOfCollectionOfModel|✓|ToolingExtension
|MapOfCollectionOfEnum|✓|ToolingExtension
### Documentation Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Readme|✗|ToolingExtension
|Model|✓|ToolingExtension
|Api|✓|ToolingExtension
### Global Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Host|✓|OAS2,OAS3
|BasePath|✓|OAS2,OAS3
|Info|✓|OAS2,OAS3
|Schemes|✗|OAS2,OAS3
|PartialSchemes|✓|OAS2,OAS3
|Consumes|✓|OAS2
|Produces|✓|OAS2
|ExternalDocumentation|✓|OAS2,OAS3
|Examples|✓|OAS2,OAS3
|XMLStructureDefinitions|✗|OAS2,OAS3
|MultiServer|✗|OAS3
|ParameterizedServer|✗|OAS3
|ParameterStyling|✗|OAS3
|Callbacks|✓|OAS3
|LinkObjects|✗|OAS3
### Parameter Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Path|✓|OAS2,OAS3
|Query|✓|OAS2,OAS3
|Header|✓|OAS2,OAS3
|Body|✓|OAS2
|FormUnencoded|✓|OAS2
|FormMultipart|✓|OAS2
|Cookie|✓|OAS3
### Schema Support Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Simple|✓|OAS2,OAS3
|Composite|✓|OAS2,OAS3
|Polymorphism|✓|OAS2,OAS3
|Union|✗|OAS3
|allOf|✗|OAS2,OAS3
|anyOf|✗|OAS3
|oneOf|✗|OAS3
|not|✗|OAS3
### Security Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect|✗|OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3
|OAuth2_ClientCredentials|✓|OAS2,OAS3
|OAuth2_AuthorizationCode|✓|OAS2,OAS3
|SignatureAuth|✗|OAS3
|AWSV4Signature|✗|ToolingExtension
### Wire Format Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|JSON|✓|OAS2,OAS3
|XML|✓|OAS2,OAS3
|PROTOBUF|✗|ToolingExtension
|Custom|✗|OAS2,OAS3

View File

@ -0,0 +1,220 @@
package org.openapitools.codegen.languages;
import org.openapitools.codegen.*;
import java.io.File;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static java.util.UUID.randomUUID;
public class AspnetFastendpointsServerCodegen extends AbstractCSharpCodegen implements CodegenConfig {
public static final String PROJECT_NAME = "projectName";
public static final String USE_PROBLEM_DETAILS = "useProblemDetails";
public static final String USE_RECORDS = "useRecords";
public static final String USE_AUTHENTICATION = "useAuthentication";
public static final String USE_VALIDATORS = "useValidators";
public static final String USE_RESPONSE_CACHING = "useResponseCaching";
public static final String USE_API_VERSIONING = "useApiVersioning";
public static final String ROUTE_PREFIX = "routePrefix";
public static final String VERSIONING_PREFIX = "versioningPrefix";
public static final String API_VERSION = "apiVersion";
public static final String SOLUTION_GUID = "solutionGuid";
public static final String PROJECT_CONFIGURATION_GUID = "projectConfigurationGuid";
private final Logger LOGGER = LoggerFactory.getLogger(AspnetFastendpointsServerCodegen.class);
private boolean useProblemDetails = false;
private boolean useRecords = false;
private boolean useAuthentication = false;
private boolean useValidators = false;
private boolean useResponseCaching = false;
private boolean useApiVersioning = false;
private String routePrefix = "api";
private String versioningPrefix = "v";
private String apiVersion = "1";
private String solutionGuid = null;
private String projectConfigurationGuid = null;
public CodegenType getTag() {
return CodegenType.SERVER;
}
public String getName() {
return "aspnet-fastendpoints";
}
public String getHelp() {
return "Generates a server for FastEndpoints (https://fast-endpoints.com/).";
}
public AspnetFastendpointsServerCodegen() {
super();
outputFolder = "generated-code" + File.separator + "aspnet-fastendpoints";
embeddedTemplateDir = templateDir = "aspnet-fastendpoints";
modelTemplateFiles.put("model.mustache", ".cs");
apiTemplateFiles.put("endpoint.mustache", "Endpoint.cs");
apiTemplateFiles.put("request.mustache", "Request.cs");
addSwitch(USE_PROBLEM_DETAILS, "Enable RFC compatible error responses (https://fast-endpoints.com/docs/configuration-settings#rfc7807-rfc9457-compatible-problem-details).", useProblemDetails);
addSwitch(USE_RECORDS, "Use record instead of class for the requests and response.", useRecords);
addSwitch(USE_AUTHENTICATION, "Enable authentication (https://fast-endpoints.com/docs/security).", useAuthentication);
addSwitch(USE_VALIDATORS, "Enable request validators (https://fast-endpoints.com/docs/validation).", useValidators);
addSwitch(USE_RESPONSE_CACHING, "Enable response caching (https://fast-endpoints.com/docs/response-caching).", useResponseCaching);
addSwitch(USE_API_VERSIONING, "Enable API versioning (https://fast-endpoints.com/docs/api-versioning).", useApiVersioning);
addOption(ROUTE_PREFIX, "The route prefix for the API. Used only if useApiVersioning is true", routePrefix);
addOption(VERSIONING_PREFIX, "The versioning prefix for the API. Used only if useApiVersioning is true", versioningPrefix);
addOption(API_VERSION, "The version of the API. Used only if useApiVersioning is true", apiVersion);
addOption(SOLUTION_GUID, "The solution GUID to be used in the solution file (auto generated if not provided)", solutionGuid);
addOption(PROJECT_CONFIGURATION_GUID, "The project configuration GUID to be used in the solution file (auto generated if not provided)", projectConfigurationGuid);
}
@Override
public void processOpts() {
setPackageDescription(openAPI.getInfo().getDescription());
setUseProblemDetails();
setUseRecordForRequest();
setUseAuthentication();
setUseValidators();
setUseResponseCaching();
setUseApiVersioning();
setRoutePrefix();
setVersioningPrefix();
setApiVersion();
setSolutionGuid();
setProjectConfigurationGuid();
super.processOpts();
addSupportingFiles();
}
private void addSupportingFiles() {
apiPackage = "Features";
modelPackage = "Models";
String packageFolder = sourceFolder + File.separator + packageName;
if(useAuthentication) {
supportingFiles.add(new SupportingFile("loginRequest.mustache", packageFolder + File.separator + apiPackage, "LoginRequest.cs"));
supportingFiles.add(new SupportingFile("userLoginEndpoint.mustache", packageFolder + File.separator + apiPackage, "UserLoginEndpoint.cs"));
}
supportingFiles.add(new SupportingFile("readme.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("gitignore", "", ".gitignore"));
supportingFiles.add(new SupportingFile("solution.mustache", "", packageName + ".sln"));
supportingFiles.add(new SupportingFile("project.csproj.mustache", packageFolder, packageName + ".csproj"));
supportingFiles.add(new SupportingFile("Properties" + File.separator + "launchSettings.json", packageFolder + File.separator + "Properties", "launchSettings.json"));
supportingFiles.add(new SupportingFile("appsettings.json", packageFolder, "appsettings.json"));
supportingFiles.add(new SupportingFile("appsettings.Development.json", packageFolder, "appsettings.Development.json"));
supportingFiles.add(new SupportingFile("program.mustache", packageFolder, "Program.cs"));
}
@Override
protected void processOperation(CodegenOperation operation) {
super.processOperation(operation);
// Converts, for example, PUT to Put for endpoint configuration
operation.httpMethod = operation.httpMethod.charAt(0) + operation.httpMethod.substring(1).toLowerCase(Locale.ROOT);
}
private void setUseProblemDetails() {
if (additionalProperties.containsKey(USE_PROBLEM_DETAILS)) {
useProblemDetails = convertPropertyToBooleanAndWriteBack(USE_PROBLEM_DETAILS);
} else {
additionalProperties.put(USE_PROBLEM_DETAILS, useProblemDetails);
}
}
private void setUseRecordForRequest() {
if (additionalProperties.containsKey(USE_RECORDS)) {
useRecords = convertPropertyToBooleanAndWriteBack(USE_RECORDS);
} else {
additionalProperties.put(USE_RECORDS, useRecords);
}
}
private void setUseAuthentication() {
if (additionalProperties.containsKey(USE_AUTHENTICATION)) {
useAuthentication = convertPropertyToBooleanAndWriteBack(USE_AUTHENTICATION);
} else {
additionalProperties.put(USE_AUTHENTICATION, useAuthentication);
}
}
private void setUseValidators() {
if (additionalProperties.containsKey(USE_VALIDATORS)) {
useValidators = convertPropertyToBooleanAndWriteBack(USE_VALIDATORS);
} else {
additionalProperties.put(USE_VALIDATORS, useValidators);
}
}
private void setUseResponseCaching() {
if (additionalProperties.containsKey(USE_RESPONSE_CACHING)) {
useResponseCaching = convertPropertyToBooleanAndWriteBack(USE_RESPONSE_CACHING);
} else {
additionalProperties.put(USE_RESPONSE_CACHING, useResponseCaching);
}
}
private void setUseApiVersioning() {
if (additionalProperties.containsKey(USE_API_VERSIONING)) {
useApiVersioning = convertPropertyToBooleanAndWriteBack(USE_API_VERSIONING);
} else {
additionalProperties.put(USE_API_VERSIONING, useApiVersioning);
}
}
private void setRoutePrefix() {
if (additionalProperties.containsKey(ROUTE_PREFIX)) {
routePrefix = (String) additionalProperties.get(ROUTE_PREFIX);
} else {
additionalProperties.put(ROUTE_PREFIX, routePrefix);
}
}
private void setVersioningPrefix() {
if (additionalProperties.containsKey(VERSIONING_PREFIX)) {
versioningPrefix = (String) additionalProperties.get(VERSIONING_PREFIX);
} else {
additionalProperties.put(VERSIONING_PREFIX, versioningPrefix);
}
}
private void setApiVersion() {
if (additionalProperties.containsKey(API_VERSION)) {
apiVersion = (String) additionalProperties.get(API_VERSION);
} else {
additionalProperties.put(API_VERSION, apiVersion);
}
}
private void setSolutionGuid() {
if (additionalProperties.containsKey(SOLUTION_GUID)) {
solutionGuid = (String) additionalProperties.get(SOLUTION_GUID);
} else {
solutionGuid = "{" + randomUUID().toString().toUpperCase(Locale.ROOT) + "}";
additionalProperties.put(SOLUTION_GUID, solutionGuid);
}
}
private void setProjectConfigurationGuid() {
if (additionalProperties.containsKey(PROJECT_CONFIGURATION_GUID)) {
projectConfigurationGuid = (String) additionalProperties.get(PROJECT_CONFIGURATION_GUID);
} else {
projectConfigurationGuid = "{" + randomUUID().toString().toUpperCase(Locale.ROOT) + "}";
additionalProperties.put(PROJECT_CONFIGURATION_GUID, projectConfigurationGuid);
}
}
}

View File

@ -4,6 +4,7 @@ org.openapitools.codegen.languages.AndroidClientCodegen
org.openapitools.codegen.languages.Apache2ConfigCodegen
org.openapitools.codegen.languages.ApexClientCodegen
org.openapitools.codegen.languages.AsciidocDocumentationCodegen
org.openapitools.codegen.languages.AspnetFastendpointsServerCodegen
org.openapitools.codegen.languages.AspNetServerCodegen
org.openapitools.codegen.languages.AvroSchemaCodegen
org.openapitools.codegen.languages.BashClientCodegen

View File

@ -0,0 +1,41 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:52621",
"sslPort": 44314
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5198",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7047;http://localhost:5198",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@ -0,0 +1,50 @@
using {{packageName}}.Models;
namespace {{packageName}}.{{apiPackage}};
{{#operations}}
{{#operation}}
/// <summary>
/// {{summary}}
/// </summary>
{{#isDeprecated}}[Obsolete]{{/isDeprecated}}
public class {{operationId}}Endpoint : {{>endpointType}}{{>endpointRequestType}}{{>endpointResponseType}}
{
public override void Configure()
{
{{httpMethod}}("{{{basePathWithoutHost}}}{{{path}}}");
{{#useApiVersioning}}Version({{apiVersion}});{{/useApiVersioning}}
{{#useResponseCaching}}ResponseCache(60);{{/useResponseCaching}}
{{^useAuthentication}}AllowAnonymous();{{/useAuthentication}}{{#useAuthentication}}//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization{{/useAuthentication}}
{{#allParams}}{{#isFile}}AllowFileUploads();{{/isFile}}{{/allParams}}
Description(x =>
{
x.WithTags("{{#tags}}{{name}}{{/tags}}");{{#responses}}{{^is2xx}}
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblem{{#useProblemDetails}}Details{{/useProblemDetails}}{{^useProblemDetails}}FE{{/useProblemDetails}}(x, {{code}});{{/is2xx}}{{/responses}}
});
Summary(s => {
s.Summary = "{{summary}}";
{{#allParams}}
s.RequestParam(r => r.{{#isBodyParam}}{{paramName}}{{/isBodyParam}}{{^isBodyParam}}{{nameInPascalCase}}{{/isBodyParam}}, "{{description}}");
{{/allParams}}
{{#responses}}
s.Responses[{{code}}] = "{{message}}";
{{/responses}}
});
}
public override async Task HandleAsync({{#allParams}}{{#-first}}{{operationId}}Request req, {{/-first}}{{/allParams}}CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
{{/operation}}
{{/operations}}

View File

@ -0,0 +1 @@
{{#allParams}}{{#-first}}<{{operationId}}Request{{#returnType}}, {{/returnType}}{{^returnType}}>{{/returnType}}{{/-first}}{{/allParams}}

View File

@ -0,0 +1 @@
{{#returnType}}{{#allParams}}{{/allParams}}{{^allParams}}<{{/allParams}}{{#returnTypeIsPrimitive}}{{&returnType}}{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}{{#generateModelDocs}}{{&returnType}}{{/generateModelDocs}}{{^generateModelDocs}}{{&returnType}}{{/generateModelDocs}}{{/returnTypeIsPrimitive}}>{{/returnType}}{{^returnType}}{{/returnType}}

View File

@ -0,0 +1 @@
{{#allParams}}{{#-first}}FastEndpoints.Endpoint{{/-first}}{{/allParams}}{{^allParams}}FastEndpoints.EndpointWithoutRequest{{/allParams}}

View File

@ -0,0 +1,16 @@
/// <summary>
/// {{^description}}Gets or Sets {{{name}}}{{/description}}{{{description}}}
/// </summary>
{{#description}}
/// <value>{{{.}}}</value>
{{/description}}
public enum {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}
{
{{#allowableValues}}{{#enumVars}}
/// <summary>
/// Enum {{name}} for {{{value}}}
/// </summary>
{{name}}{{^isString}} = {{{value}}}{{/isString}}{{#isString}} = {{-index}}{{/isString}}{{^-last}},
{{/-last}}{{/enumVars}}{{/allowableValues}}
}

View File

@ -0,0 +1,484 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from `dotnet new gitignore`
# dotenv files
.env
# 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
project.lock.json
project.fragment.lock.json
artifacts/
# Tye
.tye/
# 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
*.tlog
*.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 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# 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/
# Visual Studio History (VSHistory) files
.vshistory/
# 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
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml
.idea
##
## Visual studio for Mac
##
# globs
Makefile.in
*.userprefs
*.usertasks
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.tar.gz
tarballs/
test-results/
# Mac bundle stuff
*.dmg
*.app
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# Vim temporary swap files
*.swp

View File

@ -0,0 +1,15 @@
{{#useAuthentication}}
namespace {{packageName}}.{{apiPackage}};
{{#useRecords}}
public record LoginRequest(string Username, string Password);
{{/useRecords}}
{{^useRecords}}
public class LoginRequest
{
public string Username { get; set; }
public string Password { get; set; }
}
{{/useRecords}}
{{/useAuthentication}}

View File

@ -0,0 +1,10 @@
{{#models}}
{{#model}}
namespace {{packageName}}.{{modelPackage}};
{{#isEnum}}{{>enumClass}}{{/isEnum}}{{^isEnum}}
{{#useRecords}}{{>modelRecord}}{{/useRecords}}
{{^useRecords}}{{>modelClass}}{{/useRecords}}
{{/isEnum}}
{{/model}}
{{/models}}

View File

@ -0,0 +1,16 @@
/// <summary>
/// {{description}}
/// </summary>
public class {{classname}} {{#parent}}: {{{.}}}{{/parent}}
{
{{#vars}}
{{#isEnum}}{{^complexType}}{{>enumClass}}{{/complexType}}
{{/isEnum}}
{{#isEnum}}
public {{{datatypeWithEnum}}}{{#isNullable}}?{{/isNullable}} {{name}} { get; set; }{{#defaultValue}} = {{{.}}};{{/defaultValue}}
{{/isEnum}}
{{^isEnum}}
public {{{dataType}}}{{#nullableReferenceTypes}}{{^isContainer}}{{^required}}{{^isNullable}}?{{/isNullable}}{{/required}}{{/isContainer}}{{/nullableReferenceTypes}} {{name}} { get; set; }{{#defaultValue}} = {{{.}}};{{/defaultValue}}
{{/isEnum}}
{{/vars}}
}

View File

@ -0,0 +1,13 @@
/// <summary>
/// {{description}}
/// </summary>
public record {{classname}}({{#requiredVars}}{{#isEnum}}{{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isEnum}}{{^isEnum}}{{{dataType}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isEnum}}{{^-last}},{{/-last}}{{/requiredVars}}) {{#parent}}: {{{.}}}{{/parent}}
{
{{#optionalVars}}
public {{#isEnum}}{{{datatypeWithEnum}}}{{#isNullable}}?{{/isNullable}} {{name}} {get; init; }{{#defaultValue}} = {{{.}}};{{/defaultValue}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{#isNullable}}?{{/isNullable}} {{name}} {get; init; }{{#defaultValue}} = {{{.}}};{{/defaultValue}}{{/isEnum}}
{{/optionalVars}}
{{#vars}}
{{#isEnum}}{{^complexType}}{{>enumClass}}{{/complexType}}
{{/isEnum}}
{{/vars}}
}

View File

@ -0,0 +1,45 @@
using FastEndpoints;{{#useAuthentication}}
using FastEndpoints.Security;{{/useAuthentication}}
using FastEndpoints.Swagger;
var builder = WebApplication.CreateBuilder(args);
builder.Services
{{#useAuthentication}}.AddAuthenticationJwtBearer(s => s.SigningKey = "The secret used to sign tokens") //TODO set the signing key
.AddAuthorization(){{/useAuthentication}}
.AddFastEndpoints()
.SwaggerDocument(o =>
{
o.DocumentSettings = s =>
{
s.DocumentName = "{{{appName}}}{{^appName}}{{packageName}}{{/appName}}";
s.Title = "{{{appName}}}{{^appName}}{{packageName}}{{/appName}}";
s.Description = """
{{{packageDescription}}}
""";
s.Version = "{{{version}}}{{^version}}v1{{/version}}";
};
o.AutoTagPathSegmentIndex = 0;
})
{{#useResponseCaching}}.AddResponseCaching(){{/useResponseCaching}}
;
var app = builder.Build();
app
{{#useAuthentication}}.UseAuthentication()
.UseAuthorization(){{/useAuthentication}}{{#useResponseCaching}}
.UseResponseCaching(){{/useResponseCaching}}
.UseFastEndpoints(x =>
{
{{#useProblemDetails}}x.Errors.UseProblemDetails();{{/useProblemDetails}}
{{#useApiVersioning}}
x.Endpoints.RoutePrefix = "{{routePrefix}}";
x.Versioning.Prefix = "{{versioningPrefix}}";
{{/useApiVersioning}}
})
.UseSwaggerGen();
app.UseHttpsRedirection();
app.Run();

View File

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FastEndpoints" Version="5.29.0" />{{#useAuthentication}}
<PackageReference Include="FastEndpoints.Security" Version="5.29.0" />{{/useAuthentication}}
<PackageReference Include="FastEndpoints.Swagger" Version="5.29.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,18 @@
# {{packageName}} - FastEndpoints ASP.NET Server
{{#appDescriptionWithNewLines}}
{{{.}}}
{{/appDescriptionWithNewLines}}
## Documentation
This generated project include basic configuration for FastEndpoints ASP.NET Server.
For more information regarding FastEndpoints, please visit the [FastEndpoints website](https://fast-endpoints.com).
## Enabled Features
The following feature have been enabled in this project :
{{^useProblemDetails}}{{^useAuthentication}}{{^useValidators}}{{^useResponseCaching}}- No additional features enabled{{/useResponseCaching}}{{/useValidators}}{{/useAuthentication}}{{/useProblemDetails}}
{{#useProblemDetails}}- [Problem Details](https://fast-endpoints.com/docs/configuration-settings#rfc7807-rfc9457-compatible-problem-details){{/useProblemDetails}}
{{#useAuthentication}}- [Authentication](https://fast-endpoints.com/docs/security){{/useAuthentication}}
{{#useValidators}}- [Validation](https://fast-endpoints.com/docs/validation){{/useValidators}}
{{#useResponseCaching}}- [Response Caching](https://fast-endpoints.com/docs/response-caching){{/useResponseCaching}}

View File

@ -0,0 +1,22 @@
{{#useValidators}}using FluentValidation;{{/useValidators}}
using {{packageName}}.Models;
namespace {{packageName}}.{{apiPackage}};
{{#useRecords}}{{>requestRecord}}{{/useRecords}}
{{^useRecords}}{{>requestClass}}{{/useRecords}}
{{#useValidators}}
{{#operations}}{{#operation}}
public class {{operationId}}RequestValidator : FastEndpoints.Validator<{{operationId}}Request>
{
public {{operationId}}RequestValidator()
{
{{#requiredParams}}
RuleFor(x => x.{{#isBodyParam}}{{paramName}}{{/isBodyParam}}{{^isBodyParam}}{{nameInPascalCase}}{{/isBodyParam}}).NotEmpty();
{{/requiredParams}}
}
}
{{/operation}}{{/operations}}
{{/useValidators}}

View File

@ -0,0 +1,42 @@
{{#operations}}
{{#operation}}
public class {{operationId}}Request
{
{{#pathParams}}
/// <summary>
/// {{description}}
/// </summary>
[FastEndpoints.BindFrom("{{baseName}}")]
public {{&dataType}}{{^required}}{{#isNullable}}?{{/isNullable}}{{/required}} {{nameInPascalCase}} { get; set; }
{{/pathParams}}
{{#queryParams}}
/// <summary>
/// {{description}}
/// </summary>
[FastEndpoints.QueryParam, FastEndpoints.BindFrom("{{baseName}}")]
public {{&dataType}}{{^required}}{{#isNullable}}?{{/isNullable}}{{/required}} {{nameInPascalCase}} { get; set; }
{{/queryParams}}
{{#bodyParams}}
/// <summary>
/// {{description}}
/// </summary>
[FastEndpoints.FromBody]
public {{&dataType}}{{^required}}{{#isNullable}}?{{/isNullable}}{{/required}} {{paramName}} { get; set; }
{{/bodyParams}}
{{#formParams}}
/// <summary>
/// {{description}}
/// </summary>
[FastEndpoints.BindFrom("{{baseName}}")]
public {{&dataType}}{{^required}}{{#isNullable}}?{{/isNullable}}{{/required}} {{nameInPascalCase}} { get; set; }
{{/formParams}}
{{#headerParams}}
/// <summary>
/// {{description}}
/// </summary>
[FastEndpoints.FromHeader]
public {{&dataType}}{{^required}}{{#isNullable}}?{{/isNullable}}{{/required}} {{nameInPascalCase}} { get; set; }
{{/headerParams}}
}
{{/operation}}
{{/operations}}

View File

@ -0,0 +1,11 @@
{{#operations}}
{{#operation}}
public record {{operationId}}Request({{#requiredParams}}{{#isPathParam}}[property: FastEndpoints.BindFrom("{{baseName}}")] {{&dataType}} {{nameInPascalCase}}{{/isPathParam}}{{#isQueryParam}}[property: FastEndpoints.QueryParam, FastEndpoints.BindFrom("{{baseName}}")] {{&dataType}} {{nameInPascalCase}}{{/isQueryParam}}{{#isBodyParam}}[property: FastEndpoints.FromBody] {{&dataType}} {{paramName}}{{/isBodyParam}}{{#isFormParam}}[property: FastEndpoints.BindFrom("{{baseName}}")]{{&dataType}} {{nameInPascalCase}}{{/isFormParam}}{{#isHeaderParam}}[property: FastEndpoints.FromHeader] {{&dataType}} {{nameInPascalCase}}{{/isHeaderParam}}{{^-last}}{{^isCookieParam}}, {{/isCookieParam}}{{/-last}}{{/requiredParams}})
{
{{#optionalParams}}
{{#isPathParam}}[FastEndpoints.BindFrom("{{baseName}}")] public {{&dataType}}{{#isNullable}}?{{/isNullable}} {{nameInPascalCase}} {get; init; }{{/isPathParam}}{{#isQueryParam}}[property: FastEndpoints.QueryParam, FastEndpoints.BindFrom("{{baseName}}")] public {{&dataType}}{{#isNullable}}?{{/isNullable}} {{nameInPascalCase}} {get; init; }{{/isQueryParam}}{{#isBodyParam}}[property: FastEndpoints.FromBody] public {{&dataType}}{{#isNullable}}?{{/isNullable}} {{paramName}} {get; init; }{{/isBodyParam}}{{#isFormParam}}[FastEndpoints.BindFrom("{{baseName}}")] public {{&dataType}}{{#isNullable}}?{{/isNullable}} {{nameInPascalCase}} {get; init; }{{/isFormParam}}{{#isHeaderParam}}[property: FastEndpoints.FromHeader] public {{&dataType}}{{#isNullable}}?{{/isNullable}} {{nameInPascalCase}} {get; init; }{{/isHeaderParam}}
{{/optionalParams}}
}
{{/operation}}
{{/operations}}

View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.10.35122.118
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "{{packageName}}", "src\{{packageName}}\{{packageName}}.csproj", "{{projectConfigurationGuid}}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{{projectConfigurationGuid}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{{projectConfigurationGuid}}.Debug|Any CPU.Build.0 = Debug|Any CPU
{{projectConfigurationGuid}}.Release|Any CPU.ActiveCfg = Release|Any CPU
{{projectConfigurationGuid}}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {{solutionGuid}}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,46 @@
{{#useAuthentication}}
using FastEndpoints;
using FastEndpoints.Security;
namespace {{packageName}}.{{apiPackage}};
//TODO: This is a placeholder for the actual login request endpoint
// For more information : https://fast-endpoints.com/docs/security
public class UserLoginEndpoint : Endpoint<LoginRequest>
{
public override void Configure()
{
Post("/api/login");
AllowAnonymous();
}
public override async Task HandleAsync(LoginRequest req, CancellationToken ct)
{
bool credentialsAreValid = true; //TODO call your authentication service
if (credentialsAreValid)
{
var jwtToken = JwtBearer.CreateToken(
o =>
{
o.SigningKey = "A secret token signing key";
o.ExpireAt = DateTime.UtcNow.AddDays(1);
o.User.Roles.Add("Manager", "Auditor");
o.User.Claims.Add(("UserName", req.Username));
o.User["UserId"] = "001"; //indexer based claim setting
});
await SendAsync(
new
{
req.Username,
Token = jwtToken
});
}
else
{
ThrowError("The supplied credentials are invalid!");
}
}
}
{{/useAuthentication}}

View File

@ -0,0 +1,484 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from `dotnet new gitignore`
# dotenv files
.env
# 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
project.lock.json
project.fragment.lock.json
artifacts/
# Tye
.tye/
# 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
*.tlog
*.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 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# 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/
# Visual Studio History (VSHistory) files
.vshistory/
# 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
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml
.idea
##
## Visual studio for Mac
##
# globs
Makefile.in
*.userprefs
*.usertasks
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.tar.gz
tarballs/
test-results/
# Mac bundle stuff
*.dmg
*.app
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# Vim temporary swap files
*.swp

View File

@ -0,0 +1,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.
# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

View File

@ -0,0 +1,21 @@
.gitignore
.openapi-generator-ignore
Org.OpenAPITools.sln
README.md
src/Org.OpenAPITools/Features/PetApiEndpoint.cs
src/Org.OpenAPITools/Features/PetApiRequest.cs
src/Org.OpenAPITools/Features/StoreApiEndpoint.cs
src/Org.OpenAPITools/Features/StoreApiRequest.cs
src/Org.OpenAPITools/Features/UserApiEndpoint.cs
src/Org.OpenAPITools/Features/UserApiRequest.cs
src/Org.OpenAPITools/Models/ApiResponse.cs
src/Org.OpenAPITools/Models/Category.cs
src/Org.OpenAPITools/Models/Order.cs
src/Org.OpenAPITools/Models/Pet.cs
src/Org.OpenAPITools/Models/Tag.cs
src/Org.OpenAPITools/Models/User.cs
src/Org.OpenAPITools/Org.OpenAPITools.csproj
src/Org.OpenAPITools/Program.cs
src/Org.OpenAPITools/Properties/launchSettings.json
src/Org.OpenAPITools/appsettings.Development.json
src/Org.OpenAPITools/appsettings.json

View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.10.35122.118
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Org.OpenAPITools", "src\Org.OpenAPITools\Org.OpenAPITools.csproj", "{9685C490-9B77-4EE2-BE4D-811F52665E8F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9685C490-9B77-4EE2-BE4D-811F52665E8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9685C490-9B77-4EE2-BE4D-811F52665E8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9685C490-9B77-4EE2-BE4D-811F52665E8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9685C490-9B77-4EE2-BE4D-811F52665E8F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1EC59EB0-DA5B-40C0-8E49-A3E0829DBBFC}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,16 @@
# Org.OpenAPITools - FastEndpoints ASP.NET Server
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
## Documentation
This generated project include basic configuration for FastEndpoints ASP.NET Server.
For more information regarding FastEndpoints, please visit the [FastEndpoints website](https://fast-endpoints.com).
## Enabled Features
The following feature have been enabled in this project :
- No additional features enabled

View File

@ -0,0 +1,316 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
/// <summary>
/// Add a new pet to the store
/// </summary>
public class AddPetEndpoint : FastEndpoints.Endpoint<AddPetRequest, Pet>
{
public override void Configure()
{
Post("/v2/pet");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 405);
});
Summary(s => {
s.Summary = "Add a new pet to the store";
s.RequestParam(r => r.pet, "Pet object that needs to be added to the store");
s.Responses[200] = "successful operation";
s.Responses[405] = "Invalid input";
});
}
public override async Task HandleAsync(AddPetRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Deletes a pet
/// </summary>
public class DeletePetEndpoint : FastEndpoints.Endpoint<DeletePetRequest>
{
public override void Configure()
{
Delete("/v2/pet/{petId}");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
});
Summary(s => {
s.Summary = "Deletes a pet";
s.RequestParam(r => r.PetId, "Pet id to delete");
s.RequestParam(r => r.ApiKey, "");
s.Responses[400] = "Invalid pet value";
});
}
public override async Task HandleAsync(DeletePetRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Finds Pets by status
/// </summary>
public class FindPetsByStatusEndpoint : FastEndpoints.Endpoint<FindPetsByStatusRequest, List<Pet>>
{
public override void Configure()
{
Get("/v2/pet/findByStatus");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
});
Summary(s => {
s.Summary = "Finds Pets by status";
s.RequestParam(r => r.Status, "Status values that need to be considered for filter");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid status value";
});
}
public override async Task HandleAsync(FindPetsByStatusRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Finds Pets by tags
/// </summary>
[Obsolete]
public class FindPetsByTagsEndpoint : FastEndpoints.Endpoint<FindPetsByTagsRequest, List<Pet>>
{
public override void Configure()
{
Get("/v2/pet/findByTags");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
});
Summary(s => {
s.Summary = "Finds Pets by tags";
s.RequestParam(r => r.Tags, "Tags to filter by");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid tag value";
});
}
public override async Task HandleAsync(FindPetsByTagsRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Find pet by ID
/// </summary>
public class GetPetByIdEndpoint : FastEndpoints.Endpoint<GetPetByIdRequest, Pet>
{
public override void Configure()
{
Get("/v2/pet/{petId}");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 404);
});
Summary(s => {
s.Summary = "Find pet by ID";
s.RequestParam(r => r.PetId, "ID of pet to return");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid ID supplied";
s.Responses[404] = "Pet not found";
});
}
public override async Task HandleAsync(GetPetByIdRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Update an existing pet
/// </summary>
public class UpdatePetEndpoint : FastEndpoints.Endpoint<UpdatePetRequest, Pet>
{
public override void Configure()
{
Put("/v2/pet");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 404);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 405);
});
Summary(s => {
s.Summary = "Update an existing pet";
s.RequestParam(r => r.pet, "Pet object that needs to be added to the store");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid ID supplied";
s.Responses[404] = "Pet not found";
s.Responses[405] = "Validation exception";
});
}
public override async Task HandleAsync(UpdatePetRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Updates a pet in the store with form data
/// </summary>
public class UpdatePetWithFormEndpoint : FastEndpoints.Endpoint<UpdatePetWithFormRequest>
{
public override void Configure()
{
Post("/v2/pet/{petId}");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 405);
});
Summary(s => {
s.Summary = "Updates a pet in the store with form data";
s.RequestParam(r => r.PetId, "ID of pet that needs to be updated");
s.RequestParam(r => r.Name, "Updated name of the pet");
s.RequestParam(r => r.Status, "Updated status of the pet");
s.Responses[405] = "Invalid input";
});
}
public override async Task HandleAsync(UpdatePetWithFormRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// uploads an image
/// </summary>
public class UploadFileEndpoint : FastEndpoints.Endpoint<UploadFileRequest, ApiResponse>
{
public override void Configure()
{
Post("/v2/pet/{petId}/uploadImage");
Version(1);
AllowAnonymous();
AllowFileUploads();
Description(x =>
{
x.WithTags("pet");
});
Summary(s => {
s.Summary = "uploads an image";
s.RequestParam(r => r.PetId, "ID of pet to update");
s.RequestParam(r => r.AdditionalMetadata, "Additional data to pass to server");
s.RequestParam(r => r.File, "file to upload");
s.Responses[200] = "successful operation";
});
}
public override async Task HandleAsync(UploadFileRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}

View File

@ -0,0 +1,97 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
public class AddPetRequest
{
/// <summary>
/// Pet object that needs to be added to the store
/// </summary>
[FastEndpoints.FromBody]
public Pet pet { get; set; }
}
public class DeletePetRequest
{
/// <summary>
/// Pet id to delete
/// </summary>
[FastEndpoints.BindFrom("petId")]
public long PetId { get; set; }
/// <summary>
///
/// </summary>
[FastEndpoints.FromHeader]
public string? ApiKey { get; set; }
}
public class FindPetsByStatusRequest
{
/// <summary>
/// Status values that need to be considered for filter
/// </summary>
[FastEndpoints.QueryParam, FastEndpoints.BindFrom("status")]
public List<string> Status { get; set; }
}
public class FindPetsByTagsRequest
{
/// <summary>
/// Tags to filter by
/// </summary>
[FastEndpoints.QueryParam, FastEndpoints.BindFrom("tags")]
public List<string> Tags { get; set; }
}
public class GetPetByIdRequest
{
/// <summary>
/// ID of pet to return
/// </summary>
[FastEndpoints.BindFrom("petId")]
public long PetId { get; set; }
}
public class UpdatePetRequest
{
/// <summary>
/// Pet object that needs to be added to the store
/// </summary>
[FastEndpoints.FromBody]
public Pet pet { get; set; }
}
public class UpdatePetWithFormRequest
{
/// <summary>
/// ID of pet that needs to be updated
/// </summary>
[FastEndpoints.BindFrom("petId")]
public long PetId { get; set; }
/// <summary>
/// Updated name of the pet
/// </summary>
[FastEndpoints.BindFrom("name")]
public string? Name { get; set; }
/// <summary>
/// Updated status of the pet
/// </summary>
[FastEndpoints.BindFrom("status")]
public string? Status { get; set; }
}
public class UploadFileRequest
{
/// <summary>
/// ID of pet to update
/// </summary>
[FastEndpoints.BindFrom("petId")]
public long PetId { get; set; }
/// <summary>
/// Additional data to pass to server
/// </summary>
[FastEndpoints.BindFrom("additionalMetadata")]
public string? AdditionalMetadata { get; set; }
/// <summary>
/// file to upload
/// </summary>
[FastEndpoints.BindFrom("file")]
public System.IO.Stream? File { get; set; }
}

View File

@ -0,0 +1,157 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
/// <summary>
/// Delete purchase order by ID
/// </summary>
public class DeleteOrderEndpoint : FastEndpoints.Endpoint<DeleteOrderRequest>
{
public override void Configure()
{
Delete("/v2/store/order/{orderId}");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("store");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 404);
});
Summary(s => {
s.Summary = "Delete purchase order by ID";
s.RequestParam(r => r.OrderId, "ID of the order that needs to be deleted");
s.Responses[400] = "Invalid ID supplied";
s.Responses[404] = "Order not found";
});
}
public override async Task HandleAsync(DeleteOrderRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Returns pet inventories by status
/// </summary>
public class GetInventoryEndpoint : FastEndpoints.EndpointWithoutRequest<Dictionary<string, int>>
{
public override void Configure()
{
Get("/v2/store/inventory");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("store");
});
Summary(s => {
s.Summary = "Returns pet inventories by status";
s.Responses[200] = "successful operation";
});
}
public override async Task HandleAsync(CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Find purchase order by ID
/// </summary>
public class GetOrderByIdEndpoint : FastEndpoints.Endpoint<GetOrderByIdRequest, Order>
{
public override void Configure()
{
Get("/v2/store/order/{orderId}");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("store");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 404);
});
Summary(s => {
s.Summary = "Find purchase order by ID";
s.RequestParam(r => r.OrderId, "ID of pet that needs to be fetched");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid ID supplied";
s.Responses[404] = "Order not found";
});
}
public override async Task HandleAsync(GetOrderByIdRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Place an order for a pet
/// </summary>
public class PlaceOrderEndpoint : FastEndpoints.Endpoint<PlaceOrderRequest, Order>
{
public override void Configure()
{
Post("/v2/store/order");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("store");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
});
Summary(s => {
s.Summary = "Place an order for a pet";
s.RequestParam(r => r.order, "order placed for purchasing the pet");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid Order";
});
}
public override async Task HandleAsync(PlaceOrderRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}

View File

@ -0,0 +1,35 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
public class DeleteOrderRequest
{
/// <summary>
/// ID of the order that needs to be deleted
/// </summary>
[FastEndpoints.BindFrom("orderId")]
public string OrderId { get; set; }
}
public class GetInventoryRequest
{
}
public class GetOrderByIdRequest
{
/// <summary>
/// ID of pet that needs to be fetched
/// </summary>
[FastEndpoints.BindFrom("orderId")]
public long OrderId { get; set; }
}
public class PlaceOrderRequest
{
/// <summary>
/// order placed for purchasing the pet
/// </summary>
[FastEndpoints.FromBody]
public Order order { get; set; }
}

View File

@ -0,0 +1,310 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
/// <summary>
/// Create user
/// </summary>
public class CreateUserEndpoint : FastEndpoints.Endpoint<CreateUserRequest>
{
public override void Configure()
{
Post("/v2/user");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 0);
});
Summary(s => {
s.Summary = "Create user";
s.RequestParam(r => r.user, "Created user object");
s.Responses[0] = "successful operation";
});
}
public override async Task HandleAsync(CreateUserRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Creates list of users with given input array
/// </summary>
public class CreateUsersWithArrayInputEndpoint : FastEndpoints.Endpoint<CreateUsersWithArrayInputRequest>
{
public override void Configure()
{
Post("/v2/user/createWithArray");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 0);
});
Summary(s => {
s.Summary = "Creates list of users with given input array";
s.RequestParam(r => r.user, "List of user object");
s.Responses[0] = "successful operation";
});
}
public override async Task HandleAsync(CreateUsersWithArrayInputRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Creates list of users with given input array
/// </summary>
public class CreateUsersWithListInputEndpoint : FastEndpoints.Endpoint<CreateUsersWithListInputRequest>
{
public override void Configure()
{
Post("/v2/user/createWithList");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 0);
});
Summary(s => {
s.Summary = "Creates list of users with given input array";
s.RequestParam(r => r.user, "List of user object");
s.Responses[0] = "successful operation";
});
}
public override async Task HandleAsync(CreateUsersWithListInputRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Delete user
/// </summary>
public class DeleteUserEndpoint : FastEndpoints.Endpoint<DeleteUserRequest>
{
public override void Configure()
{
Delete("/v2/user/{username}");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 404);
});
Summary(s => {
s.Summary = "Delete user";
s.RequestParam(r => r.Username, "The name that needs to be deleted");
s.Responses[400] = "Invalid username supplied";
s.Responses[404] = "User not found";
});
}
public override async Task HandleAsync(DeleteUserRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Get user by user name
/// </summary>
public class GetUserByNameEndpoint : FastEndpoints.Endpoint<GetUserByNameRequest, User>
{
public override void Configure()
{
Get("/v2/user/{username}");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 404);
});
Summary(s => {
s.Summary = "Get user by user name";
s.RequestParam(r => r.Username, "The name that needs to be fetched. Use user1 for testing.");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid username supplied";
s.Responses[404] = "User not found";
});
}
public override async Task HandleAsync(GetUserByNameRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Logs user into the system
/// </summary>
public class LoginUserEndpoint : FastEndpoints.Endpoint<LoginUserRequest, string>
{
public override void Configure()
{
Get("/v2/user/login");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
});
Summary(s => {
s.Summary = "Logs user into the system";
s.RequestParam(r => r.Username, "The user name for login");
s.RequestParam(r => r.Password, "The password for login in clear text");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid username/password supplied";
});
}
public override async Task HandleAsync(LoginUserRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Logs out current logged in user session
/// </summary>
public class LogoutUserEndpoint : FastEndpoints.EndpointWithoutRequest
{
public override void Configure()
{
Get("/v2/user/logout");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 0);
});
Summary(s => {
s.Summary = "Logs out current logged in user session";
s.Responses[0] = "successful operation";
});
}
public override async Task HandleAsync(CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Updated user
/// </summary>
public class UpdateUserEndpoint : FastEndpoints.Endpoint<UpdateUserRequest>
{
public override void Configure()
{
Put("/v2/user/{username}");
Version(1);
AllowAnonymous();
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 404);
});
Summary(s => {
s.Summary = "Updated user";
s.RequestParam(r => r.Username, "name that need to be deleted");
s.RequestParam(r => r.user, "Updated user object");
s.Responses[400] = "Invalid user supplied";
s.Responses[404] = "User not found";
});
}
public override async Task HandleAsync(UpdateUserRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}

View File

@ -0,0 +1,77 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
public class CreateUserRequest
{
/// <summary>
/// Created user object
/// </summary>
[FastEndpoints.FromBody]
public User user { get; set; }
}
public class CreateUsersWithArrayInputRequest
{
/// <summary>
/// List of user object
/// </summary>
[FastEndpoints.FromBody]
public List<User> user { get; set; }
}
public class CreateUsersWithListInputRequest
{
/// <summary>
/// List of user object
/// </summary>
[FastEndpoints.FromBody]
public List<User> user { get; set; }
}
public class DeleteUserRequest
{
/// <summary>
/// The name that needs to be deleted
/// </summary>
[FastEndpoints.BindFrom("username")]
public string Username { get; set; }
}
public class GetUserByNameRequest
{
/// <summary>
/// The name that needs to be fetched. Use user1 for testing.
/// </summary>
[FastEndpoints.BindFrom("username")]
public string Username { get; set; }
}
public class LoginUserRequest
{
/// <summary>
/// The user name for login
/// </summary>
[FastEndpoints.QueryParam, FastEndpoints.BindFrom("username")]
public string Username { get; set; }
/// <summary>
/// The password for login in clear text
/// </summary>
[FastEndpoints.QueryParam, FastEndpoints.BindFrom("password")]
public string Password { get; set; }
}
public class LogoutUserRequest
{
}
public class UpdateUserRequest
{
/// <summary>
/// name that need to be deleted
/// </summary>
[FastEndpoints.BindFrom("username")]
public string Username { get; set; }
/// <summary>
/// Updated user object
/// </summary>
[FastEndpoints.FromBody]
public User user { get; set; }
}

View File

@ -0,0 +1,14 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// Describes the result of uploading an image resource
/// </summary>
public class ApiResponse
{
public int Code { get; set; }
public string Type { get; set; }
public string Message { get; set; }
}

View File

@ -0,0 +1,13 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// A category for a pet
/// </summary>
public class Category
{
public long Id { get; set; }
public string Name { get; set; }
}

View File

@ -0,0 +1,41 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// An order for a pets from the pet store
/// </summary>
public class Order
{
public long Id { get; set; }
public long PetId { get; set; }
public int Quantity { get; set; }
public DateTime ShipDate { get; set; }
/// <summary>
/// Order Status
/// </summary>
/// <value>Order Status</value>
public enum StatusEnum
{
/// <summary>
/// Enum PlacedEnum for placed
/// </summary>
PlacedEnum = 1,
/// <summary>
/// Enum ApprovedEnum for approved
/// </summary>
ApprovedEnum = 2,
/// <summary>
/// Enum DeliveredEnum for delivered
/// </summary>
DeliveredEnum = 3
}
public StatusEnum Status { get; set; }
public bool Complete { get; set; } = false;
}

View File

@ -0,0 +1,41 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// A pet for sale in the pet store
/// </summary>
public class Pet
{
public long Id { get; set; }
public Category Category { get; set; }
public string Name { get; set; }
public List<string> PhotoUrls { get; set; }
public List<Tag> Tags { get; set; }
/// <summary>
/// pet status in the store
/// </summary>
/// <value>pet status in the store</value>
public enum StatusEnum
{
/// <summary>
/// Enum AvailableEnum for available
/// </summary>
AvailableEnum = 1,
/// <summary>
/// Enum PendingEnum for pending
/// </summary>
PendingEnum = 2,
/// <summary>
/// Enum SoldEnum for sold
/// </summary>
SoldEnum = 3
}
public StatusEnum Status { get; set; }
}

View File

@ -0,0 +1,13 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// A tag for a pet
/// </summary>
public class Tag
{
public long Id { get; set; }
public string Name { get; set; }
}

View File

@ -0,0 +1,19 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// A User who is purchasing from the pet store
/// </summary>
public class User
{
public long Id { get; set; }
public string Username { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string Phone { get; set; }
public int UserStatus { get; set; }
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FastEndpoints" Version="5.29.0" />
<PackageReference Include="FastEndpoints.Swagger" Version="5.29.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,39 @@
using FastEndpoints;
using FastEndpoints.Swagger;
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddFastEndpoints()
.SwaggerDocument(o =>
{
o.DocumentSettings = s =>
{
s.DocumentName = "OpenAPI Petstore";
s.Title = "OpenAPI Petstore";
s.Description = """
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
""";
s.Version = "1.0.0";
};
o.AutoTagPathSegmentIndex = 0;
})
;
var app = builder.Build();
app
.UseFastEndpoints(x =>
{
x.Endpoints.RoutePrefix = "api";
x.Versioning.Prefix = "v";
})
.UseSwaggerGen();
app.UseHttpsRedirection();
app.Run();

View File

@ -0,0 +1,41 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:52621",
"sslPort": 44314
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5198",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7047;http://localhost:5198",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@ -0,0 +1,484 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from `dotnet new gitignore`
# dotenv files
.env
# 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
project.lock.json
project.fragment.lock.json
artifacts/
# Tye
.tye/
# 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
*.tlog
*.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 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# 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/
# Visual Studio History (VSHistory) files
.vshistory/
# 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
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml
.idea
##
## Visual studio for Mac
##
# globs
Makefile.in
*.userprefs
*.usertasks
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.tar.gz
tarballs/
test-results/
# Mac bundle stuff
*.dmg
*.app
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# Vim temporary swap files
*.swp

View File

@ -0,0 +1,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.
# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

View File

@ -0,0 +1,23 @@
.gitignore
.openapi-generator-ignore
Org.OpenAPITools.sln
README.md
src/Org.OpenAPITools/Features/LoginRequest.cs
src/Org.OpenAPITools/Features/PetApiEndpoint.cs
src/Org.OpenAPITools/Features/PetApiRequest.cs
src/Org.OpenAPITools/Features/StoreApiEndpoint.cs
src/Org.OpenAPITools/Features/StoreApiRequest.cs
src/Org.OpenAPITools/Features/UserApiEndpoint.cs
src/Org.OpenAPITools/Features/UserApiRequest.cs
src/Org.OpenAPITools/Features/UserLoginEndpoint.cs
src/Org.OpenAPITools/Models/ApiResponse.cs
src/Org.OpenAPITools/Models/Category.cs
src/Org.OpenAPITools/Models/Order.cs
src/Org.OpenAPITools/Models/Pet.cs
src/Org.OpenAPITools/Models/Tag.cs
src/Org.OpenAPITools/Models/User.cs
src/Org.OpenAPITools/Org.OpenAPITools.csproj
src/Org.OpenAPITools/Program.cs
src/Org.OpenAPITools/Properties/launchSettings.json
src/Org.OpenAPITools/appsettings.Development.json
src/Org.OpenAPITools/appsettings.json

View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.10.35122.118
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Org.OpenAPITools", "src\Org.OpenAPITools\Org.OpenAPITools.csproj", "{3FA19D58-AE7C-45E5-B00E-7482026D1816}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3FA19D58-AE7C-45E5-B00E-7482026D1816}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3FA19D58-AE7C-45E5-B00E-7482026D1816}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3FA19D58-AE7C-45E5-B00E-7482026D1816}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3FA19D58-AE7C-45E5-B00E-7482026D1816}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {10D45F9B-F270-480C-9DA9-720AA62526A4}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,16 @@
# Org.OpenAPITools - FastEndpoints ASP.NET Server
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
## Documentation
This generated project include basic configuration for FastEndpoints ASP.NET Server.
For more information regarding FastEndpoints, please visit the [FastEndpoints website](https://fast-endpoints.com).
## Enabled Features
The following feature have been enabled in this project :
- [Authentication](https://fast-endpoints.com/docs/security)

View File

@ -0,0 +1,9 @@

namespace Org.OpenAPITools.Features;
public class LoginRequest
{
public string Username { get; set; }
public string Password { get; set; }
}

View File

@ -0,0 +1,316 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
/// <summary>
/// Add a new pet to the store
/// </summary>
public class AddPetEndpoint : FastEndpoints.Endpoint<AddPetRequest, Pet>
{
public override void Configure()
{
Post("/v2/pet");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 405);
});
Summary(s => {
s.Summary = "Add a new pet to the store";
s.RequestParam(r => r.pet, "Pet object that needs to be added to the store");
s.Responses[200] = "successful operation";
s.Responses[405] = "Invalid input";
});
}
public override async Task HandleAsync(AddPetRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Deletes a pet
/// </summary>
public class DeletePetEndpoint : FastEndpoints.Endpoint<DeletePetRequest>
{
public override void Configure()
{
Delete("/v2/pet/{petId}");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
});
Summary(s => {
s.Summary = "Deletes a pet";
s.RequestParam(r => r.PetId, "Pet id to delete");
s.RequestParam(r => r.ApiKey, "");
s.Responses[400] = "Invalid pet value";
});
}
public override async Task HandleAsync(DeletePetRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Finds Pets by status
/// </summary>
public class FindPetsByStatusEndpoint : FastEndpoints.Endpoint<FindPetsByStatusRequest, List<Pet>>
{
public override void Configure()
{
Get("/v2/pet/findByStatus");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
});
Summary(s => {
s.Summary = "Finds Pets by status";
s.RequestParam(r => r.Status, "Status values that need to be considered for filter");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid status value";
});
}
public override async Task HandleAsync(FindPetsByStatusRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Finds Pets by tags
/// </summary>
[Obsolete]
public class FindPetsByTagsEndpoint : FastEndpoints.Endpoint<FindPetsByTagsRequest, List<Pet>>
{
public override void Configure()
{
Get("/v2/pet/findByTags");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
});
Summary(s => {
s.Summary = "Finds Pets by tags";
s.RequestParam(r => r.Tags, "Tags to filter by");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid tag value";
});
}
public override async Task HandleAsync(FindPetsByTagsRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Find pet by ID
/// </summary>
public class GetPetByIdEndpoint : FastEndpoints.Endpoint<GetPetByIdRequest, Pet>
{
public override void Configure()
{
Get("/v2/pet/{petId}");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 404);
});
Summary(s => {
s.Summary = "Find pet by ID";
s.RequestParam(r => r.PetId, "ID of pet to return");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid ID supplied";
s.Responses[404] = "Pet not found";
});
}
public override async Task HandleAsync(GetPetByIdRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Update an existing pet
/// </summary>
public class UpdatePetEndpoint : FastEndpoints.Endpoint<UpdatePetRequest, Pet>
{
public override void Configure()
{
Put("/v2/pet");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 404);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 405);
});
Summary(s => {
s.Summary = "Update an existing pet";
s.RequestParam(r => r.pet, "Pet object that needs to be added to the store");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid ID supplied";
s.Responses[404] = "Pet not found";
s.Responses[405] = "Validation exception";
});
}
public override async Task HandleAsync(UpdatePetRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Updates a pet in the store with form data
/// </summary>
public class UpdatePetWithFormEndpoint : FastEndpoints.Endpoint<UpdatePetWithFormRequest>
{
public override void Configure()
{
Post("/v2/pet/{petId}");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 405);
});
Summary(s => {
s.Summary = "Updates a pet in the store with form data";
s.RequestParam(r => r.PetId, "ID of pet that needs to be updated");
s.RequestParam(r => r.Name, "Updated name of the pet");
s.RequestParam(r => r.Status, "Updated status of the pet");
s.Responses[405] = "Invalid input";
});
}
public override async Task HandleAsync(UpdatePetWithFormRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// uploads an image
/// </summary>
public class UploadFileEndpoint : FastEndpoints.Endpoint<UploadFileRequest, ApiResponse>
{
public override void Configure()
{
Post("/v2/pet/{petId}/uploadImage");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
AllowFileUploads();
Description(x =>
{
x.WithTags("pet");
});
Summary(s => {
s.Summary = "uploads an image";
s.RequestParam(r => r.PetId, "ID of pet to update");
s.RequestParam(r => r.AdditionalMetadata, "Additional data to pass to server");
s.RequestParam(r => r.File, "file to upload");
s.Responses[200] = "successful operation";
});
}
public override async Task HandleAsync(UploadFileRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}

View File

@ -0,0 +1,97 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
public class AddPetRequest
{
/// <summary>
/// Pet object that needs to be added to the store
/// </summary>
[FastEndpoints.FromBody]
public Pet pet { get; set; }
}
public class DeletePetRequest
{
/// <summary>
/// Pet id to delete
/// </summary>
[FastEndpoints.BindFrom("petId")]
public long PetId { get; set; }
/// <summary>
///
/// </summary>
[FastEndpoints.FromHeader]
public string? ApiKey { get; set; }
}
public class FindPetsByStatusRequest
{
/// <summary>
/// Status values that need to be considered for filter
/// </summary>
[FastEndpoints.QueryParam, FastEndpoints.BindFrom("status")]
public List<string> Status { get; set; }
}
public class FindPetsByTagsRequest
{
/// <summary>
/// Tags to filter by
/// </summary>
[FastEndpoints.QueryParam, FastEndpoints.BindFrom("tags")]
public List<string> Tags { get; set; }
}
public class GetPetByIdRequest
{
/// <summary>
/// ID of pet to return
/// </summary>
[FastEndpoints.BindFrom("petId")]
public long PetId { get; set; }
}
public class UpdatePetRequest
{
/// <summary>
/// Pet object that needs to be added to the store
/// </summary>
[FastEndpoints.FromBody]
public Pet pet { get; set; }
}
public class UpdatePetWithFormRequest
{
/// <summary>
/// ID of pet that needs to be updated
/// </summary>
[FastEndpoints.BindFrom("petId")]
public long PetId { get; set; }
/// <summary>
/// Updated name of the pet
/// </summary>
[FastEndpoints.BindFrom("name")]
public string? Name { get; set; }
/// <summary>
/// Updated status of the pet
/// </summary>
[FastEndpoints.BindFrom("status")]
public string? Status { get; set; }
}
public class UploadFileRequest
{
/// <summary>
/// ID of pet to update
/// </summary>
[FastEndpoints.BindFrom("petId")]
public long PetId { get; set; }
/// <summary>
/// Additional data to pass to server
/// </summary>
[FastEndpoints.BindFrom("additionalMetadata")]
public string? AdditionalMetadata { get; set; }
/// <summary>
/// file to upload
/// </summary>
[FastEndpoints.BindFrom("file")]
public System.IO.Stream? File { get; set; }
}

View File

@ -0,0 +1,157 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
/// <summary>
/// Delete purchase order by ID
/// </summary>
public class DeleteOrderEndpoint : FastEndpoints.Endpoint<DeleteOrderRequest>
{
public override void Configure()
{
Delete("/v2/store/order/{orderId}");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("store");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 404);
});
Summary(s => {
s.Summary = "Delete purchase order by ID";
s.RequestParam(r => r.OrderId, "ID of the order that needs to be deleted");
s.Responses[400] = "Invalid ID supplied";
s.Responses[404] = "Order not found";
});
}
public override async Task HandleAsync(DeleteOrderRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Returns pet inventories by status
/// </summary>
public class GetInventoryEndpoint : FastEndpoints.EndpointWithoutRequest<Dictionary<string, int>>
{
public override void Configure()
{
Get("/v2/store/inventory");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("store");
});
Summary(s => {
s.Summary = "Returns pet inventories by status";
s.Responses[200] = "successful operation";
});
}
public override async Task HandleAsync(CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Find purchase order by ID
/// </summary>
public class GetOrderByIdEndpoint : FastEndpoints.Endpoint<GetOrderByIdRequest, Order>
{
public override void Configure()
{
Get("/v2/store/order/{orderId}");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("store");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 404);
});
Summary(s => {
s.Summary = "Find purchase order by ID";
s.RequestParam(r => r.OrderId, "ID of pet that needs to be fetched");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid ID supplied";
s.Responses[404] = "Order not found";
});
}
public override async Task HandleAsync(GetOrderByIdRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Place an order for a pet
/// </summary>
public class PlaceOrderEndpoint : FastEndpoints.Endpoint<PlaceOrderRequest, Order>
{
public override void Configure()
{
Post("/v2/store/order");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("store");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
});
Summary(s => {
s.Summary = "Place an order for a pet";
s.RequestParam(r => r.order, "order placed for purchasing the pet");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid Order";
});
}
public override async Task HandleAsync(PlaceOrderRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}

View File

@ -0,0 +1,35 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
public class DeleteOrderRequest
{
/// <summary>
/// ID of the order that needs to be deleted
/// </summary>
[FastEndpoints.BindFrom("orderId")]
public string OrderId { get; set; }
}
public class GetInventoryRequest
{
}
public class GetOrderByIdRequest
{
/// <summary>
/// ID of pet that needs to be fetched
/// </summary>
[FastEndpoints.BindFrom("orderId")]
public long OrderId { get; set; }
}
public class PlaceOrderRequest
{
/// <summary>
/// order placed for purchasing the pet
/// </summary>
[FastEndpoints.FromBody]
public Order order { get; set; }
}

View File

@ -0,0 +1,310 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
/// <summary>
/// Create user
/// </summary>
public class CreateUserEndpoint : FastEndpoints.Endpoint<CreateUserRequest>
{
public override void Configure()
{
Post("/v2/user");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 0);
});
Summary(s => {
s.Summary = "Create user";
s.RequestParam(r => r.user, "Created user object");
s.Responses[0] = "successful operation";
});
}
public override async Task HandleAsync(CreateUserRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Creates list of users with given input array
/// </summary>
public class CreateUsersWithArrayInputEndpoint : FastEndpoints.Endpoint<CreateUsersWithArrayInputRequest>
{
public override void Configure()
{
Post("/v2/user/createWithArray");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 0);
});
Summary(s => {
s.Summary = "Creates list of users with given input array";
s.RequestParam(r => r.user, "List of user object");
s.Responses[0] = "successful operation";
});
}
public override async Task HandleAsync(CreateUsersWithArrayInputRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Creates list of users with given input array
/// </summary>
public class CreateUsersWithListInputEndpoint : FastEndpoints.Endpoint<CreateUsersWithListInputRequest>
{
public override void Configure()
{
Post("/v2/user/createWithList");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 0);
});
Summary(s => {
s.Summary = "Creates list of users with given input array";
s.RequestParam(r => r.user, "List of user object");
s.Responses[0] = "successful operation";
});
}
public override async Task HandleAsync(CreateUsersWithListInputRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Delete user
/// </summary>
public class DeleteUserEndpoint : FastEndpoints.Endpoint<DeleteUserRequest>
{
public override void Configure()
{
Delete("/v2/user/{username}");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 404);
});
Summary(s => {
s.Summary = "Delete user";
s.RequestParam(r => r.Username, "The name that needs to be deleted");
s.Responses[400] = "Invalid username supplied";
s.Responses[404] = "User not found";
});
}
public override async Task HandleAsync(DeleteUserRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Get user by user name
/// </summary>
public class GetUserByNameEndpoint : FastEndpoints.Endpoint<GetUserByNameRequest, User>
{
public override void Configure()
{
Get("/v2/user/{username}");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 404);
});
Summary(s => {
s.Summary = "Get user by user name";
s.RequestParam(r => r.Username, "The name that needs to be fetched. Use user1 for testing.");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid username supplied";
s.Responses[404] = "User not found";
});
}
public override async Task HandleAsync(GetUserByNameRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Logs user into the system
/// </summary>
public class LoginUserEndpoint : FastEndpoints.Endpoint<LoginUserRequest, string>
{
public override void Configure()
{
Get("/v2/user/login");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
});
Summary(s => {
s.Summary = "Logs user into the system";
s.RequestParam(r => r.Username, "The user name for login");
s.RequestParam(r => r.Password, "The password for login in clear text");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid username/password supplied";
});
}
public override async Task HandleAsync(LoginUserRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Logs out current logged in user session
/// </summary>
public class LogoutUserEndpoint : FastEndpoints.EndpointWithoutRequest
{
public override void Configure()
{
Get("/v2/user/logout");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 0);
});
Summary(s => {
s.Summary = "Logs out current logged in user session";
s.Responses[0] = "successful operation";
});
}
public override async Task HandleAsync(CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Updated user
/// </summary>
public class UpdateUserEndpoint : FastEndpoints.Endpoint<UpdateUserRequest>
{
public override void Configure()
{
Put("/v2/user/{username}");
//TODO : authentication is enabled, you need to configure the authorizations : https://fast-endpoints.com/docs/security#endpoint-authorization
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemFE(x, 404);
});
Summary(s => {
s.Summary = "Updated user";
s.RequestParam(r => r.Username, "name that need to be deleted");
s.RequestParam(r => r.user, "Updated user object");
s.Responses[400] = "Invalid user supplied";
s.Responses[404] = "User not found";
});
}
public override async Task HandleAsync(UpdateUserRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}

View File

@ -0,0 +1,77 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
public class CreateUserRequest
{
/// <summary>
/// Created user object
/// </summary>
[FastEndpoints.FromBody]
public User user { get; set; }
}
public class CreateUsersWithArrayInputRequest
{
/// <summary>
/// List of user object
/// </summary>
[FastEndpoints.FromBody]
public List<User> user { get; set; }
}
public class CreateUsersWithListInputRequest
{
/// <summary>
/// List of user object
/// </summary>
[FastEndpoints.FromBody]
public List<User> user { get; set; }
}
public class DeleteUserRequest
{
/// <summary>
/// The name that needs to be deleted
/// </summary>
[FastEndpoints.BindFrom("username")]
public string Username { get; set; }
}
public class GetUserByNameRequest
{
/// <summary>
/// The name that needs to be fetched. Use user1 for testing.
/// </summary>
[FastEndpoints.BindFrom("username")]
public string Username { get; set; }
}
public class LoginUserRequest
{
/// <summary>
/// The user name for login
/// </summary>
[FastEndpoints.QueryParam, FastEndpoints.BindFrom("username")]
public string Username { get; set; }
/// <summary>
/// The password for login in clear text
/// </summary>
[FastEndpoints.QueryParam, FastEndpoints.BindFrom("password")]
public string Password { get; set; }
}
public class LogoutUserRequest
{
}
public class UpdateUserRequest
{
/// <summary>
/// name that need to be deleted
/// </summary>
[FastEndpoints.BindFrom("username")]
public string Username { get; set; }
/// <summary>
/// Updated user object
/// </summary>
[FastEndpoints.FromBody]
public User user { get; set; }
}

View File

@ -0,0 +1,45 @@

using FastEndpoints;
using FastEndpoints.Security;
namespace Org.OpenAPITools.Features;
//TODO: This is a placeholder for the actual login request endpoint
// For more information : https://fast-endpoints.com/docs/security
public class UserLoginEndpoint : Endpoint<LoginRequest>
{
public override void Configure()
{
Post("/api/login");
AllowAnonymous();
}
public override async Task HandleAsync(LoginRequest req, CancellationToken ct)
{
bool credentialsAreValid = true; //TODO call your authentication service
if (credentialsAreValid)
{
var jwtToken = JwtBearer.CreateToken(
o =>
{
o.SigningKey = "A secret token signing key";
o.ExpireAt = DateTime.UtcNow.AddDays(1);
o.User.Roles.Add("Manager", "Auditor");
o.User.Claims.Add(("UserName", req.Username));
o.User["UserId"] = "001"; //indexer based claim setting
});
await SendAsync(
new
{
req.Username,
Token = jwtToken
});
}
else
{
ThrowError("The supplied credentials are invalid!");
}
}
}

View File

@ -0,0 +1,14 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// Describes the result of uploading an image resource
/// </summary>
public class ApiResponse
{
public int Code { get; set; }
public string Type { get; set; }
public string Message { get; set; }
}

View File

@ -0,0 +1,13 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// A category for a pet
/// </summary>
public class Category
{
public long Id { get; set; }
public string Name { get; set; }
}

View File

@ -0,0 +1,41 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// An order for a pets from the pet store
/// </summary>
public class Order
{
public long Id { get; set; }
public long PetId { get; set; }
public int Quantity { get; set; }
public DateTime ShipDate { get; set; }
/// <summary>
/// Order Status
/// </summary>
/// <value>Order Status</value>
public enum StatusEnum
{
/// <summary>
/// Enum PlacedEnum for placed
/// </summary>
PlacedEnum = 1,
/// <summary>
/// Enum ApprovedEnum for approved
/// </summary>
ApprovedEnum = 2,
/// <summary>
/// Enum DeliveredEnum for delivered
/// </summary>
DeliveredEnum = 3
}
public StatusEnum Status { get; set; }
public bool Complete { get; set; } = false;
}

View File

@ -0,0 +1,41 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// A pet for sale in the pet store
/// </summary>
public class Pet
{
public long Id { get; set; }
public Category Category { get; set; }
public string Name { get; set; }
public List<string> PhotoUrls { get; set; }
public List<Tag> Tags { get; set; }
/// <summary>
/// pet status in the store
/// </summary>
/// <value>pet status in the store</value>
public enum StatusEnum
{
/// <summary>
/// Enum AvailableEnum for available
/// </summary>
AvailableEnum = 1,
/// <summary>
/// Enum PendingEnum for pending
/// </summary>
PendingEnum = 2,
/// <summary>
/// Enum SoldEnum for sold
/// </summary>
SoldEnum = 3
}
public StatusEnum Status { get; set; }
}

View File

@ -0,0 +1,13 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// A tag for a pet
/// </summary>
public class Tag
{
public long Id { get; set; }
public string Name { get; set; }
}

View File

@ -0,0 +1,19 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// A User who is purchasing from the pet store
/// </summary>
public class User
{
public long Id { get; set; }
public string Username { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string Phone { get; set; }
public int UserStatus { get; set; }
}

View File

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FastEndpoints" Version="5.29.0" />
<PackageReference Include="FastEndpoints.Security" Version="5.29.0" />
<PackageReference Include="FastEndpoints.Swagger" Version="5.29.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,40 @@
using FastEndpoints;
using FastEndpoints.Security;
using FastEndpoints.Swagger;
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddAuthenticationJwtBearer(s => s.SigningKey = "The secret used to sign tokens") //TODO set the signing key
.AddAuthorization()
.AddFastEndpoints()
.SwaggerDocument(o =>
{
o.DocumentSettings = s =>
{
s.DocumentName = "OpenAPI Petstore";
s.Title = "OpenAPI Petstore";
s.Description = """
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
""";
s.Version = "1.0.0";
};
o.AutoTagPathSegmentIndex = 0;
})
;
var app = builder.Build();
app
.UseAuthentication()
.UseAuthorization()
.UseFastEndpoints(x =>
{
})
.UseSwaggerGen();
app.UseHttpsRedirection();
app.Run();

View File

@ -0,0 +1,41 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:52621",
"sslPort": 44314
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5198",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7047;http://localhost:5198",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@ -0,0 +1,484 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from `dotnet new gitignore`
# dotenv files
.env
# 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
project.lock.json
project.fragment.lock.json
artifacts/
# Tye
.tye/
# 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
*.tlog
*.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 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# 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/
# Visual Studio History (VSHistory) files
.vshistory/
# 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
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml
.idea
##
## Visual studio for Mac
##
# globs
Makefile.in
*.userprefs
*.usertasks
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.tar.gz
tarballs/
test-results/
# Mac bundle stuff
*.dmg
*.app
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# Vim temporary swap files
*.swp

View File

@ -0,0 +1,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.
# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

View File

@ -0,0 +1,21 @@
.gitignore
.openapi-generator-ignore
Org.OpenAPITools.sln
README.md
src/Org.OpenAPITools/Features/PetApiEndpoint.cs
src/Org.OpenAPITools/Features/PetApiRequest.cs
src/Org.OpenAPITools/Features/StoreApiEndpoint.cs
src/Org.OpenAPITools/Features/StoreApiRequest.cs
src/Org.OpenAPITools/Features/UserApiEndpoint.cs
src/Org.OpenAPITools/Features/UserApiRequest.cs
src/Org.OpenAPITools/Models/ApiResponse.cs
src/Org.OpenAPITools/Models/Category.cs
src/Org.OpenAPITools/Models/Order.cs
src/Org.OpenAPITools/Models/Pet.cs
src/Org.OpenAPITools/Models/Tag.cs
src/Org.OpenAPITools/Models/User.cs
src/Org.OpenAPITools/Org.OpenAPITools.csproj
src/Org.OpenAPITools/Program.cs
src/Org.OpenAPITools/Properties/launchSettings.json
src/Org.OpenAPITools/appsettings.Development.json
src/Org.OpenAPITools/appsettings.json

View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.10.35122.118
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Org.OpenAPITools", "src\Org.OpenAPITools\Org.OpenAPITools.csproj", "{74D68BAC-36F5-43FC-BE9A-F3E660EECF5D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{74D68BAC-36F5-43FC-BE9A-F3E660EECF5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{74D68BAC-36F5-43FC-BE9A-F3E660EECF5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{74D68BAC-36F5-43FC-BE9A-F3E660EECF5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{74D68BAC-36F5-43FC-BE9A-F3E660EECF5D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EA9B735E-72CA-44C4-BB28-358BDECE60C8}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,16 @@
# Org.OpenAPITools - FastEndpoints ASP.NET Server
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
## Documentation
This generated project include basic configuration for FastEndpoints ASP.NET Server.
For more information regarding FastEndpoints, please visit the [FastEndpoints website](https://fast-endpoints.com).
## Enabled Features
The following feature have been enabled in this project :
- [Problem Details](https://fast-endpoints.com/docs/configuration-settings#rfc7807-rfc9457-compatible-problem-details)

View File

@ -0,0 +1,316 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
/// <summary>
/// Add a new pet to the store
/// </summary>
public class AddPetEndpoint : FastEndpoints.Endpoint<AddPetRequest, Pet>
{
public override void Configure()
{
Post("/v2/pet");
AllowAnonymous();
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 405);
});
Summary(s => {
s.Summary = "Add a new pet to the store";
s.RequestParam(r => r.pet, "Pet object that needs to be added to the store");
s.Responses[200] = "successful operation";
s.Responses[405] = "Invalid input";
});
}
public override async Task HandleAsync(AddPetRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Deletes a pet
/// </summary>
public class DeletePetEndpoint : FastEndpoints.Endpoint<DeletePetRequest>
{
public override void Configure()
{
Delete("/v2/pet/{petId}");
AllowAnonymous();
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 400);
});
Summary(s => {
s.Summary = "Deletes a pet";
s.RequestParam(r => r.PetId, "Pet id to delete");
s.RequestParam(r => r.ApiKey, "");
s.Responses[400] = "Invalid pet value";
});
}
public override async Task HandleAsync(DeletePetRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Finds Pets by status
/// </summary>
public class FindPetsByStatusEndpoint : FastEndpoints.Endpoint<FindPetsByStatusRequest, List<Pet>>
{
public override void Configure()
{
Get("/v2/pet/findByStatus");
AllowAnonymous();
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 400);
});
Summary(s => {
s.Summary = "Finds Pets by status";
s.RequestParam(r => r.Status, "Status values that need to be considered for filter");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid status value";
});
}
public override async Task HandleAsync(FindPetsByStatusRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Finds Pets by tags
/// </summary>
[Obsolete]
public class FindPetsByTagsEndpoint : FastEndpoints.Endpoint<FindPetsByTagsRequest, List<Pet>>
{
public override void Configure()
{
Get("/v2/pet/findByTags");
AllowAnonymous();
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 400);
});
Summary(s => {
s.Summary = "Finds Pets by tags";
s.RequestParam(r => r.Tags, "Tags to filter by");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid tag value";
});
}
public override async Task HandleAsync(FindPetsByTagsRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Find pet by ID
/// </summary>
public class GetPetByIdEndpoint : FastEndpoints.Endpoint<GetPetByIdRequest, Pet>
{
public override void Configure()
{
Get("/v2/pet/{petId}");
AllowAnonymous();
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 404);
});
Summary(s => {
s.Summary = "Find pet by ID";
s.RequestParam(r => r.PetId, "ID of pet to return");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid ID supplied";
s.Responses[404] = "Pet not found";
});
}
public override async Task HandleAsync(GetPetByIdRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Update an existing pet
/// </summary>
public class UpdatePetEndpoint : FastEndpoints.Endpoint<UpdatePetRequest, Pet>
{
public override void Configure()
{
Put("/v2/pet");
AllowAnonymous();
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 404);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 405);
});
Summary(s => {
s.Summary = "Update an existing pet";
s.RequestParam(r => r.pet, "Pet object that needs to be added to the store");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid ID supplied";
s.Responses[404] = "Pet not found";
s.Responses[405] = "Validation exception";
});
}
public override async Task HandleAsync(UpdatePetRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Updates a pet in the store with form data
/// </summary>
public class UpdatePetWithFormEndpoint : FastEndpoints.Endpoint<UpdatePetWithFormRequest>
{
public override void Configure()
{
Post("/v2/pet/{petId}");
AllowAnonymous();
Description(x =>
{
x.WithTags("pet");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 405);
});
Summary(s => {
s.Summary = "Updates a pet in the store with form data";
s.RequestParam(r => r.PetId, "ID of pet that needs to be updated");
s.RequestParam(r => r.Name, "Updated name of the pet");
s.RequestParam(r => r.Status, "Updated status of the pet");
s.Responses[405] = "Invalid input";
});
}
public override async Task HandleAsync(UpdatePetWithFormRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// uploads an image
/// </summary>
public class UploadFileEndpoint : FastEndpoints.Endpoint<UploadFileRequest, ApiResponse>
{
public override void Configure()
{
Post("/v2/pet/{petId}/uploadImage");
AllowAnonymous();
AllowFileUploads();
Description(x =>
{
x.WithTags("pet");
});
Summary(s => {
s.Summary = "uploads an image";
s.RequestParam(r => r.PetId, "ID of pet to update");
s.RequestParam(r => r.AdditionalMetadata, "Additional data to pass to server");
s.RequestParam(r => r.File, "file to upload");
s.Responses[200] = "successful operation";
});
}
public override async Task HandleAsync(UploadFileRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}

View File

@ -0,0 +1,97 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
public class AddPetRequest
{
/// <summary>
/// Pet object that needs to be added to the store
/// </summary>
[FastEndpoints.FromBody]
public Pet pet { get; set; }
}
public class DeletePetRequest
{
/// <summary>
/// Pet id to delete
/// </summary>
[FastEndpoints.BindFrom("petId")]
public long PetId { get; set; }
/// <summary>
///
/// </summary>
[FastEndpoints.FromHeader]
public string? ApiKey { get; set; }
}
public class FindPetsByStatusRequest
{
/// <summary>
/// Status values that need to be considered for filter
/// </summary>
[FastEndpoints.QueryParam, FastEndpoints.BindFrom("status")]
public List<string> Status { get; set; }
}
public class FindPetsByTagsRequest
{
/// <summary>
/// Tags to filter by
/// </summary>
[FastEndpoints.QueryParam, FastEndpoints.BindFrom("tags")]
public List<string> Tags { get; set; }
}
public class GetPetByIdRequest
{
/// <summary>
/// ID of pet to return
/// </summary>
[FastEndpoints.BindFrom("petId")]
public long PetId { get; set; }
}
public class UpdatePetRequest
{
/// <summary>
/// Pet object that needs to be added to the store
/// </summary>
[FastEndpoints.FromBody]
public Pet pet { get; set; }
}
public class UpdatePetWithFormRequest
{
/// <summary>
/// ID of pet that needs to be updated
/// </summary>
[FastEndpoints.BindFrom("petId")]
public long PetId { get; set; }
/// <summary>
/// Updated name of the pet
/// </summary>
[FastEndpoints.BindFrom("name")]
public string? Name { get; set; }
/// <summary>
/// Updated status of the pet
/// </summary>
[FastEndpoints.BindFrom("status")]
public string? Status { get; set; }
}
public class UploadFileRequest
{
/// <summary>
/// ID of pet to update
/// </summary>
[FastEndpoints.BindFrom("petId")]
public long PetId { get; set; }
/// <summary>
/// Additional data to pass to server
/// </summary>
[FastEndpoints.BindFrom("additionalMetadata")]
public string? AdditionalMetadata { get; set; }
/// <summary>
/// file to upload
/// </summary>
[FastEndpoints.BindFrom("file")]
public System.IO.Stream? File { get; set; }
}

View File

@ -0,0 +1,157 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
/// <summary>
/// Delete purchase order by ID
/// </summary>
public class DeleteOrderEndpoint : FastEndpoints.Endpoint<DeleteOrderRequest>
{
public override void Configure()
{
Delete("/v2/store/order/{orderId}");
AllowAnonymous();
Description(x =>
{
x.WithTags("store");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 404);
});
Summary(s => {
s.Summary = "Delete purchase order by ID";
s.RequestParam(r => r.OrderId, "ID of the order that needs to be deleted");
s.Responses[400] = "Invalid ID supplied";
s.Responses[404] = "Order not found";
});
}
public override async Task HandleAsync(DeleteOrderRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Returns pet inventories by status
/// </summary>
public class GetInventoryEndpoint : FastEndpoints.EndpointWithoutRequest<Dictionary<string, int>>
{
public override void Configure()
{
Get("/v2/store/inventory");
AllowAnonymous();
Description(x =>
{
x.WithTags("store");
});
Summary(s => {
s.Summary = "Returns pet inventories by status";
s.Responses[200] = "successful operation";
});
}
public override async Task HandleAsync(CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Find purchase order by ID
/// </summary>
public class GetOrderByIdEndpoint : FastEndpoints.Endpoint<GetOrderByIdRequest, Order>
{
public override void Configure()
{
Get("/v2/store/order/{orderId}");
AllowAnonymous();
Description(x =>
{
x.WithTags("store");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 404);
});
Summary(s => {
s.Summary = "Find purchase order by ID";
s.RequestParam(r => r.OrderId, "ID of pet that needs to be fetched");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid ID supplied";
s.Responses[404] = "Order not found";
});
}
public override async Task HandleAsync(GetOrderByIdRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Place an order for a pet
/// </summary>
public class PlaceOrderEndpoint : FastEndpoints.Endpoint<PlaceOrderRequest, Order>
{
public override void Configure()
{
Post("/v2/store/order");
AllowAnonymous();
Description(x =>
{
x.WithTags("store");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 400);
});
Summary(s => {
s.Summary = "Place an order for a pet";
s.RequestParam(r => r.order, "order placed for purchasing the pet");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid Order";
});
}
public override async Task HandleAsync(PlaceOrderRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}

View File

@ -0,0 +1,35 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
public class DeleteOrderRequest
{
/// <summary>
/// ID of the order that needs to be deleted
/// </summary>
[FastEndpoints.BindFrom("orderId")]
public string OrderId { get; set; }
}
public class GetInventoryRequest
{
}
public class GetOrderByIdRequest
{
/// <summary>
/// ID of pet that needs to be fetched
/// </summary>
[FastEndpoints.BindFrom("orderId")]
public long OrderId { get; set; }
}
public class PlaceOrderRequest
{
/// <summary>
/// order placed for purchasing the pet
/// </summary>
[FastEndpoints.FromBody]
public Order order { get; set; }
}

View File

@ -0,0 +1,310 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
/// <summary>
/// Create user
/// </summary>
public class CreateUserEndpoint : FastEndpoints.Endpoint<CreateUserRequest>
{
public override void Configure()
{
Post("/v2/user");
AllowAnonymous();
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 0);
});
Summary(s => {
s.Summary = "Create user";
s.RequestParam(r => r.user, "Created user object");
s.Responses[0] = "successful operation";
});
}
public override async Task HandleAsync(CreateUserRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Creates list of users with given input array
/// </summary>
public class CreateUsersWithArrayInputEndpoint : FastEndpoints.Endpoint<CreateUsersWithArrayInputRequest>
{
public override void Configure()
{
Post("/v2/user/createWithArray");
AllowAnonymous();
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 0);
});
Summary(s => {
s.Summary = "Creates list of users with given input array";
s.RequestParam(r => r.user, "List of user object");
s.Responses[0] = "successful operation";
});
}
public override async Task HandleAsync(CreateUsersWithArrayInputRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Creates list of users with given input array
/// </summary>
public class CreateUsersWithListInputEndpoint : FastEndpoints.Endpoint<CreateUsersWithListInputRequest>
{
public override void Configure()
{
Post("/v2/user/createWithList");
AllowAnonymous();
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 0);
});
Summary(s => {
s.Summary = "Creates list of users with given input array";
s.RequestParam(r => r.user, "List of user object");
s.Responses[0] = "successful operation";
});
}
public override async Task HandleAsync(CreateUsersWithListInputRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Delete user
/// </summary>
public class DeleteUserEndpoint : FastEndpoints.Endpoint<DeleteUserRequest>
{
public override void Configure()
{
Delete("/v2/user/{username}");
AllowAnonymous();
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 404);
});
Summary(s => {
s.Summary = "Delete user";
s.RequestParam(r => r.Username, "The name that needs to be deleted");
s.Responses[400] = "Invalid username supplied";
s.Responses[404] = "User not found";
});
}
public override async Task HandleAsync(DeleteUserRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Get user by user name
/// </summary>
public class GetUserByNameEndpoint : FastEndpoints.Endpoint<GetUserByNameRequest, User>
{
public override void Configure()
{
Get("/v2/user/{username}");
AllowAnonymous();
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 404);
});
Summary(s => {
s.Summary = "Get user by user name";
s.RequestParam(r => r.Username, "The name that needs to be fetched. Use user1 for testing.");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid username supplied";
s.Responses[404] = "User not found";
});
}
public override async Task HandleAsync(GetUserByNameRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Logs user into the system
/// </summary>
public class LoginUserEndpoint : FastEndpoints.Endpoint<LoginUserRequest, string>
{
public override void Configure()
{
Get("/v2/user/login");
AllowAnonymous();
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 400);
});
Summary(s => {
s.Summary = "Logs user into the system";
s.RequestParam(r => r.Username, "The user name for login");
s.RequestParam(r => r.Password, "The password for login in clear text");
s.Responses[200] = "successful operation";
s.Responses[400] = "Invalid username/password supplied";
});
}
public override async Task HandleAsync(LoginUserRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Logs out current logged in user session
/// </summary>
public class LogoutUserEndpoint : FastEndpoints.EndpointWithoutRequest
{
public override void Configure()
{
Get("/v2/user/logout");
AllowAnonymous();
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 0);
});
Summary(s => {
s.Summary = "Logs out current logged in user session";
s.Responses[0] = "successful operation";
});
}
public override async Task HandleAsync(CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}
/// <summary>
/// Updated user
/// </summary>
public class UpdateUserEndpoint : FastEndpoints.Endpoint<UpdateUserRequest>
{
public override void Configure()
{
Put("/v2/user/{username}");
AllowAnonymous();
Description(x =>
{
x.WithTags("user");
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 400);
FastEndpoints.RouteHandlerBuilderExtensions.ProducesProblemDetails(x, 404);
});
Summary(s => {
s.Summary = "Updated user";
s.RequestParam(r => r.Username, "name that need to be deleted");
s.RequestParam(r => r.user, "Updated user object");
s.Responses[400] = "Invalid user supplied";
s.Responses[404] = "User not found";
});
}
public override async Task HandleAsync(UpdateUserRequest req, CancellationToken ct)
{
//Response = new()
//{
//...
//};
//return Task.CompletedTask;
}
}

View File

@ -0,0 +1,77 @@
using Org.OpenAPITools.Models;
namespace Org.OpenAPITools.Features;
public class CreateUserRequest
{
/// <summary>
/// Created user object
/// </summary>
[FastEndpoints.FromBody]
public User user { get; set; }
}
public class CreateUsersWithArrayInputRequest
{
/// <summary>
/// List of user object
/// </summary>
[FastEndpoints.FromBody]
public List<User> user { get; set; }
}
public class CreateUsersWithListInputRequest
{
/// <summary>
/// List of user object
/// </summary>
[FastEndpoints.FromBody]
public List<User> user { get; set; }
}
public class DeleteUserRequest
{
/// <summary>
/// The name that needs to be deleted
/// </summary>
[FastEndpoints.BindFrom("username")]
public string Username { get; set; }
}
public class GetUserByNameRequest
{
/// <summary>
/// The name that needs to be fetched. Use user1 for testing.
/// </summary>
[FastEndpoints.BindFrom("username")]
public string Username { get; set; }
}
public class LoginUserRequest
{
/// <summary>
/// The user name for login
/// </summary>
[FastEndpoints.QueryParam, FastEndpoints.BindFrom("username")]
public string Username { get; set; }
/// <summary>
/// The password for login in clear text
/// </summary>
[FastEndpoints.QueryParam, FastEndpoints.BindFrom("password")]
public string Password { get; set; }
}
public class LogoutUserRequest
{
}
public class UpdateUserRequest
{
/// <summary>
/// name that need to be deleted
/// </summary>
[FastEndpoints.BindFrom("username")]
public string Username { get; set; }
/// <summary>
/// Updated user object
/// </summary>
[FastEndpoints.FromBody]
public User user { get; set; }
}

View File

@ -0,0 +1,14 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// Describes the result of uploading an image resource
/// </summary>
public class ApiResponse
{
public int Code { get; set; }
public string Type { get; set; }
public string Message { get; set; }
}

View File

@ -0,0 +1,13 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// A category for a pet
/// </summary>
public class Category
{
public long Id { get; set; }
public string Name { get; set; }
}

View File

@ -0,0 +1,41 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// An order for a pets from the pet store
/// </summary>
public class Order
{
public long Id { get; set; }
public long PetId { get; set; }
public int Quantity { get; set; }
public DateTime ShipDate { get; set; }
/// <summary>
/// Order Status
/// </summary>
/// <value>Order Status</value>
public enum StatusEnum
{
/// <summary>
/// Enum PlacedEnum for placed
/// </summary>
PlacedEnum = 1,
/// <summary>
/// Enum ApprovedEnum for approved
/// </summary>
ApprovedEnum = 2,
/// <summary>
/// Enum DeliveredEnum for delivered
/// </summary>
DeliveredEnum = 3
}
public StatusEnum Status { get; set; }
public bool Complete { get; set; } = false;
}

View File

@ -0,0 +1,41 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// A pet for sale in the pet store
/// </summary>
public class Pet
{
public long Id { get; set; }
public Category Category { get; set; }
public string Name { get; set; }
public List<string> PhotoUrls { get; set; }
public List<Tag> Tags { get; set; }
/// <summary>
/// pet status in the store
/// </summary>
/// <value>pet status in the store</value>
public enum StatusEnum
{
/// <summary>
/// Enum AvailableEnum for available
/// </summary>
AvailableEnum = 1,
/// <summary>
/// Enum PendingEnum for pending
/// </summary>
PendingEnum = 2,
/// <summary>
/// Enum SoldEnum for sold
/// </summary>
SoldEnum = 3
}
public StatusEnum Status { get; set; }
}

View File

@ -0,0 +1,13 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// A tag for a pet
/// </summary>
public class Tag
{
public long Id { get; set; }
public string Name { get; set; }
}

View File

@ -0,0 +1,19 @@
namespace Org.OpenAPITools.Models;
/// <summary>
/// A User who is purchasing from the pet store
/// </summary>
public class User
{
public long Id { get; set; }
public string Username { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string Phone { get; set; }
public int UserStatus { get; set; }
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FastEndpoints" Version="5.29.0" />
<PackageReference Include="FastEndpoints.Swagger" Version="5.29.0" />
</ItemGroup>
</Project>

Some files were not shown because too many files have changed in this diff Show More