diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AspNetCoreServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AspNetCoreServerCodegen.java index f669ffb6a59..235c6ccdbac 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AspNetCoreServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AspNetCoreServerCodegen.java @@ -23,7 +23,7 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen { private String packageGuid = "{" + randomUUID().toString().toUpperCase() + "}"; - private final String DEFAULT_ASP_NET_CORE_VERSION = "2.2"; + private final String DEFAULT_ASP_NET_CORE_VERSION = "3.0"; private String aspNetCoreVersion; @SuppressWarnings("hiding") @@ -64,7 +64,7 @@ public AspNetCoreServerCodegen() { sourceFolder); addOption(CodegenConstants.ASP_NET_CORE_VERSION, - "aspnetcore version to use, current options are: 2.0, 2.1 and 2.2 (default)", + "aspnetcore version to use, current options are: 2.0, 2.1, 2.2 and 3.0 (default)", this.aspNetCoreVersion); addOption(CodegenConstants.INTERFACE_ONLY, @@ -133,16 +133,35 @@ public void processOpts() { apiTemplateFiles.put("controller.mustache", ".cs"); addInterfaceControllerTemplate(interfaceOnly, interfaceController); + supportingFiles.add(new SupportingFile("Filters" + File.separator + "BasePathFilter.mustache", packageFolder + File.separator + "Filters", "BasePathFilter.cs")); + supportingFiles.add(new SupportingFile("Filters" + File.separator + "GeneratePathParamsValidationFilter.mustache", packageFolder + File.separator + "Filters", "GeneratePathParamsValidationFilter.cs")); + + supportingFiles.add(new SupportingFile("Startup.mustache", packageFolder, "Startup.cs")); supportingFiles.add(new SupportingFile("Program.mustache", packageFolder, "Program.cs")); supportingFiles.add(new SupportingFile("Project.csproj.mustache", packageFolder, this.packageName + ".csproj")); supportingFiles.add(new SupportingFile("Dockerfile.mustache", packageFolder, "Dockerfile")); - } else { + } else if (this.aspNetCoreVersion.equals("2.1")) { apiTemplateFiles.put("2.1/controller.mustache", ".cs"); addInterfaceControllerTemplate(interfaceOnly, interfaceController); + supportingFiles.add(new SupportingFile("Filters" + File.separator + "BasePathFilter.mustache", packageFolder + File.separator + "Filters", "BasePathFilter.cs")); + supportingFiles.add(new SupportingFile("Filters" + File.separator + "GeneratePathParamsValidationFilter.mustache", packageFolder + File.separator + "Filters", "GeneratePathParamsValidationFilter.cs")); + + supportingFiles.add(new SupportingFile("Startup.mustache", packageFolder, "Startup.cs")); supportingFiles.add(new SupportingFile("2.1/Program.mustache", packageFolder, "Program.cs")); supportingFiles.add(new SupportingFile("2.1/Project.csproj.mustache", packageFolder, this.packageName + ".csproj")); supportingFiles.add(new SupportingFile("2.1/Dockerfile.mustache", packageFolder, "Dockerfile")); + } else { + apiTemplateFiles.put("3.0/controller.mustache", ".cs"); + addInterfaceControllerTemplate(interfaceOnly, interfaceController); + + supportingFiles.add(new SupportingFile("3.0" + File.separator + "Filters" + File.separator + "BasePathFilter.mustache", packageFolder + File.separator + "Filters", "BasePathFilter.cs")); + supportingFiles.add(new SupportingFile("3.0" + File.separator + "Filters" + File.separator + "GeneratePathParamsValidationFilter.mustache", packageFolder + File.separator + "Filters", "GeneratePathParamsValidationFilter.cs")); + + supportingFiles.add(new SupportingFile("3.0/Startup.mustache", packageFolder, "Startup.cs")); + supportingFiles.add(new SupportingFile("3.0/Program.mustache", packageFolder, "Program.cs")); + supportingFiles.add(new SupportingFile("3.0/Project.csproj.mustache", packageFolder, this.packageName + ".csproj")); + supportingFiles.add(new SupportingFile("3.0/Dockerfile.mustache", packageFolder, "Dockerfile")); } additionalProperties.put("aspNetCoreVersion", aspNetCoreVersion); @@ -159,20 +178,14 @@ public void processOpts() { supportingFiles.add(new SupportingFile("build.bat.mustache", "", "build.bat")); supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); supportingFiles.add(new SupportingFile("Solution.mustache", "", this.packageName + ".sln")); - supportingFiles.add(new SupportingFile("Dockerfile.mustache", packageFolder, "Dockerfile")); supportingFiles.add(new SupportingFile("gitignore", packageFolder, ".gitignore")); supportingFiles.add(new SupportingFile("appsettings.json", packageFolder, "appsettings.json")); - supportingFiles.add(new SupportingFile("Startup.mustache", packageFolder, "Startup.cs")); supportingFiles.add(new SupportingFile("validateModel.mustache", packageFolder + File.separator + "Attributes", "ValidateModelStateAttribute.cs")); supportingFiles.add(new SupportingFile("web.config", packageFolder, "web.config")); supportingFiles.add(new SupportingFile("Properties" + File.separator + "launchSettings.json", packageFolder + File.separator + "Properties", "launchSettings.json")); - supportingFiles.add(new SupportingFile("Filters" + File.separator + "BasePathFilter.mustache", packageFolder + File.separator + "Filters", "BasePathFilter.cs")); - supportingFiles.add(new SupportingFile("Filters" + File.separator + "GeneratePathParamsValidationFilter.mustache", packageFolder + File.separator + "Filters", "GeneratePathParamsValidationFilter.cs")); - - supportingFiles.add(new SupportingFile("wwwroot" + File.separator + "README.md", packageFolder + File.separator + "wwwroot", "README.md")); supportingFiles.add(new SupportingFile("wwwroot" + File.separator + "index.html", packageFolder + File.separator + "wwwroot", "index.html")); supportingFiles.add(new SupportingFile("wwwroot" + File.separator + "web.config", packageFolder + File.separator + "wwwroot", "web.config")); @@ -301,7 +314,7 @@ private void setAspNetCoreVersion(String optionValue) { return; } this.aspNetCoreVersion = optionValue; - if (!this.aspNetCoreVersion.equals("2.0") && !this.aspNetCoreVersion.equals("2.1") && !this.aspNetCoreVersion.equals("2.2")) { + if (!this.aspNetCoreVersion.equals("2.0") && !this.aspNetCoreVersion.equals("2.1") && !this.aspNetCoreVersion.equals("2.2") && !this.aspNetCoreVersion.equals("3.0")) { LOGGER.error("version '" + this.aspNetCoreVersion + "' is not supported, switching to default version: '" + DEFAULT_ASP_NET_CORE_VERSION + "'"); this.aspNetCoreVersion = DEFAULT_ASP_NET_CORE_VERSION; } diff --git a/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Dockerfile.mustache b/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Dockerfile.mustache new file mode 100644 index 00000000000..aaee7ee659a --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Dockerfile.mustache @@ -0,0 +1,18 @@ +FROM mcr.microsoft.com/dotnet/core/sdk:{{aspNetCoreVersion}} AS build-env +WORKDIR /app + +ENV DOTNET_CLI_TELEMETRY_OPTOUT 1 + +# copy csproj and restore as distinct layers +COPY *.csproj ./ +RUN dotnet restore + +# copy everything else and build +COPY . ./ +RUN dotnet publish -c Release -o out + +# build runtime image +FROM mcr.microsoft.com/dotnet/core/aspnet:{{aspNetCoreVersion}} +WORKDIR /app +COPY --from=build-env /app/out . +ENTRYPOINT ["dotnet", "{{packageName}}.dll"] diff --git a/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Filters/BasePathFilter.mustache b/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Filters/BasePathFilter.mustache new file mode 100644 index 00000000000..3d2c3b67c74 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Filters/BasePathFilter.mustache @@ -0,0 +1,51 @@ +using System.Linq; +using System.Text.RegularExpressions; +using Swashbuckle.AspNetCore.Swagger; +using Swashbuckle.AspNetCore.SwaggerGen; +using Microsoft.OpenApi.Models; + +namespace {{packageName}}.Filters +{ + /// + /// BasePath Document Filter sets BasePath property of Swagger and removes it from the individual URL paths + /// + public class BasePathFilter : IDocumentFilter + { + /// + /// Constructor + /// + /// BasePath to remove from Operations + public BasePathFilter(string basePath) + { + BasePath = basePath; + } + + /// + /// Gets the BasePath of the Swagger Doc + /// + /// The BasePath of the Swagger Doc + public string BasePath { get; } + + /// + /// Apply the filter + /// + /// OpenApiDocument + /// FilterContext + public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) + { + swaggerDoc.Servers.Add(new OpenApiServer() { Url = this.BasePath }); + + var pathsToModify = swaggerDoc.Paths.Where(p => p.Key.StartsWith(this.BasePath)).ToList(); + + foreach (var path in pathsToModify) + { + if (path.Key.StartsWith(this.BasePath)) + { + string newKey = Regex.Replace(path.Key, $"^{this.BasePath}", string.Empty); + swaggerDoc.Paths.Remove(path.Key); + swaggerDoc.Paths.Add(newKey, path.Value); + } + } + } + } +} diff --git a/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Filters/GeneratePathParamsValidationFilter.mustache b/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Filters/GeneratePathParamsValidationFilter.mustache new file mode 100644 index 00000000000..2343bcfdc37 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Filters/GeneratePathParamsValidationFilter.mustache @@ -0,0 +1,98 @@ +using System.ComponentModel.DataAnnotations; +using System.Linq; +using Microsoft.AspNetCore.Mvc.Controllers; +using Swashbuckle.AspNetCore.Swagger; +using Swashbuckle.AspNetCore.SwaggerGen; +using Microsoft.OpenApi.Models; + +namespace {{packageName}}.Filters +{ + /// + /// Path Parameter Validation Rules Filter + /// + public class GeneratePathParamsValidationFilter : IOperationFilter + { + /// + /// Constructor + /// + /// Operation + /// OperationFilterContext + public void Apply(OpenApiOperation operation, OperationFilterContext context) + { + var pars = context.ApiDescription.ParameterDescriptions; + + foreach (var par in pars) + { + var swaggerParam = operation.Parameters.SingleOrDefault(p => p.Name == par.Name); + + var attributes = ((ControllerParameterDescriptor)par.ParameterDescriptor).ParameterInfo.CustomAttributes; + + if (attributes != null && attributes.Count() > 0 && swaggerParam != null) + { + // Required - [Required] + var requiredAttr = attributes.FirstOrDefault(p => p.AttributeType == typeof(RequiredAttribute)); + if (requiredAttr != null) + { + swaggerParam.Required = true; + } + + // Regex Pattern [RegularExpression] + var regexAttr = attributes.FirstOrDefault(p => p.AttributeType == typeof(RegularExpressionAttribute)); + if (regexAttr != null) + { + string regex = (string)regexAttr.ConstructorArguments[0].Value; + if (swaggerParam is OpenApiParameter) + { + ((OpenApiParameter)swaggerParam).Schema.Pattern = regex; + } + } + + // String Length [StringLength] + int? minLenght = null, maxLength = null; + var stringLengthAttr = attributes.FirstOrDefault(p => p.AttributeType == typeof(StringLengthAttribute)); + if (stringLengthAttr != null) + { + if (stringLengthAttr.NamedArguments.Count == 1) + { + minLenght = (int)stringLengthAttr.NamedArguments.Single(p => p.MemberName == "MinimumLength").TypedValue.Value; + } + maxLength = (int)stringLengthAttr.ConstructorArguments[0].Value; + } + + var minLengthAttr = attributes.FirstOrDefault(p => p.AttributeType == typeof(MinLengthAttribute)); + if (minLengthAttr != null) + { + minLenght = (int)minLengthAttr.ConstructorArguments[0].Value; + } + + var maxLengthAttr = attributes.FirstOrDefault(p => p.AttributeType == typeof(MaxLengthAttribute)); + if (maxLengthAttr != null) + { + maxLength = (int)maxLengthAttr.ConstructorArguments[0].Value; + } + + if (swaggerParam is OpenApiParameter) + { + ((OpenApiParameter)swaggerParam).Schema.MinLength = minLenght; + ((OpenApiParameter)swaggerParam).Schema.MaxLength = maxLength; + } + + // Range [Range] + var rangeAttr = attributes.FirstOrDefault(p => p.AttributeType == typeof(RangeAttribute)); + if (rangeAttr != null) + { + int rangeMin = (int)rangeAttr.ConstructorArguments[0].Value; + int rangeMax = (int)rangeAttr.ConstructorArguments[1].Value; + + if (swaggerParam is OpenApiParameter) + { + ((OpenApiParameter)swaggerParam).Schema.Minimum = rangeMin; + ((OpenApiParameter)swaggerParam).Schema.Maximum = rangeMax; + } + } + } + } + } + } +} + diff --git a/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Program.mustache b/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Program.mustache new file mode 100644 index 00000000000..49b1837ce6c --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Program.mustache @@ -0,0 +1,29 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore; + +namespace {{packageName}} +{ + /// + /// Program + /// + public class Program + { + /// + /// Main + /// + /// + public static void Main(string[] args) + { + CreateWebHostBuilder(args).Build().Run(); + } + + /// + /// Create the web host builder. + /// + /// + /// IWebHostBuilder + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseStartup(); + } +} diff --git a/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Project.csproj.mustache b/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Project.csproj.mustache new file mode 100644 index 00000000000..82f6e1a838b --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Project.csproj.mustache @@ -0,0 +1,20 @@ + + + {{packageName}} + {{packageName}} + netcoreapp{{aspNetCoreVersion}} + true + true + {{packageName}} + {{packageName}} + + + + + + + + + + + diff --git a/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Startup.mustache b/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Startup.mustache new file mode 100644 index 00000000000..bcfdea4eec4 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/Startup.mustache @@ -0,0 +1,154 @@ +{{>partial_header}} +using System; +using System.IO; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.OpenApi.Models; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Serialization; +using Swashbuckle.AspNetCore.Swagger; +using Swashbuckle.AspNetCore.SwaggerGen; +using {{packageName}}.Filters; +using {{packageName}}.Security; + +namespace {{packageName}} +{ + /// + /// Startup + /// + public class Startup + { + private readonly IWebHostEnvironment _hostingEnv; + + private IConfiguration Configuration { get; } + + /// + /// Constructor + /// + /// + /// + public Startup(IWebHostEnvironment env, IConfiguration configuration) + { + _hostingEnv = env; + Configuration = configuration; + } + + /// + /// This method gets called by the runtime. Use this method to add services to the container. + /// + /// + public void ConfigureServices(IServiceCollection services) + { + // Add framework services. + services + .AddMvc(options => + { + options.InputFormatters.RemoveType(); + options.OutputFormatters.RemoveType(); + }) + .AddNewtonsoftJson(opts => + { + opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); + opts.SerializerSettings.Converters.Add(new StringEnumConverter(new CamelCaseNamingStrategy())); + }) + .AddXmlSerializerFormatters(); + + {{#authMethods}} + {{#isBasic}} + services.AddAuthentication(BasicAuthenticationHandler.SchemeName) + .AddScheme(BasicAuthenticationHandler.SchemeName, null); + + {{/isBasic}} + {{#isBearer}} + services.AddAuthentication(BearerAuthenticationHandler.SchemeName) + .AddScheme(BearerAuthenticationHandler.SchemeName, null); + + {{/isBearer}} + {{#isApiKey}} + services.AddAuthentication(ApiKeyAuthenticationHandler.SchemeName) + .AddScheme(ApiKeyAuthenticationHandler.SchemeName, null); + + {{/isApiKey}} + {{/authMethods}} + + services + .AddSwaggerGen(c => + { + c.SwaggerDoc("{{#version}}{{{version}}}{{/version}}{{^version}}v1{{/version}}", new OpenApiInfo + { + Version = "{{#version}}{{{version}}}{{/version}}{{^version}}v1{{/version}}", + Title = "{{#appName}}{{{appName}}}{{/appName}}{{^appName}}{{packageName}}{{/appName}}", + Description = "{{#appName}}{{{appName}}}{{/appName}}{{^appName}}{{packageName}}{{/appName}} (ASP.NET Core {{aspNetCoreVersion}})", + Contact = new OpenApiContact() + { + Name = "{{#infoName}}{{{infoName}}}{{/infoName}}{{^infoName}}Swagger Codegen Contributors{{/infoName}}", + Url = new Uri("{{#infoUrl}}{{{infoUrl}}}{{/infoUrl}}{{^infoUrl}}https://github.com/swagger-api/swagger-codegen{{/infoUrl}}"), + Email = "{{#infoEmail}}{{{infoEmail}}}{{/infoEmail}}" + }, + TermsOfService = new Uri("{{#termsOfService}}{{{termsOfService}}}{{/termsOfService}}") + }); + c.CustomSchemaIds(type => type.FullName); + c.IncludeXmlComments($"{AppContext.BaseDirectory}{Path.DirectorySeparatorChar}{_hostingEnv.ApplicationName}.xml"); + {{#basePathWithoutHost}} + // Sets the basePath property in the Swagger document generated + c.DocumentFilter("{{{basePathWithoutHost}}}"); + {{/basePathWithoutHost}} + + // Include DataAnnotation attributes on Controller Action parameters as Swagger validation rules (e.g required, pattern, ..) + // Use [ValidateModelState] on Actions to actually validate it in C# as well! + c.OperationFilter(); + }); + } + + /// + /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + /// + /// + /// + /// + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) + { + app.UseRouting(); + + //TODO: Uncomment this if you need wwwroot folder + // app.UseStaticFiles(); + + app.UseAuthorization(); + + app.UseSwagger(); + app.UseSwaggerUI(c => + { + //TODO: Either use the SwaggerGen generated Swagger contract (generated from C# classes) + c.SwaggerEndpoint("/swagger/{{#version}}{{{version}}}{{/version}}{{^version}}v1{{/version}}/swagger.json", "{{#appName}}{{{appName}}}{{/appName}}{{^appName}}{{packageName}}{{/appName}}"); + + //TODO: Or alternatively use the original Swagger contract that's included in the static files + // c.SwaggerEndpoint("/swagger-original.json", "{{#appName}}{{{appName}}}{{/appName}}{{^appName}}{{packageName}}{{/appName}} Original"); + }); + + //TODO: Use Https Redirection + // app.UseHttpsRedirection(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else + { + //TODO: Enable production exception handling (https://docs.microsoft.com/en-us/aspnet/core/fundamentals/error-handling) + app.UseExceptionHandler("/Error"); + + app.UseHsts(); + } + } + } +} diff --git a/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/controller.mustache b/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/controller.mustache new file mode 100644 index 00000000000..f6804005399 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/aspnetcore/3.0/controller.mustache @@ -0,0 +1,71 @@ +{{>partial_header}} +using System; +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc; +using Swashbuckle.AspNetCore.Annotations; +using Swashbuckle.AspNetCore.SwaggerGen; +using Newtonsoft.Json; +using System.ComponentModel.DataAnnotations; +using {{packageName}}.Attributes; +using {{packageName}}.Security; +using Microsoft.AspNetCore.Authorization; +using {{modelPackage}}; + +namespace {{packageName}}.Controllers +{ {{#operations}} + /// + /// {{description}} + /// {{#description}} + [Description("{{description}}")]{{/description}} + [ApiController] + public class {{classname}}Controller : ControllerBase{{#interfaceController}}, I{{classname}}Controller{{/interfaceController}} + { {{#operation}} + /// + /// {{#summary}}{{summary}}{{/summary}} + /// + {{#notes}}/// {{notes}}{{/notes}}{{#allParams}} + /// {{description}}{{/allParams}}{{#responses}} + /// {{message}}{{/responses}} + [{{httpMethod}}] + [Route("{{{basePathWithoutHost}}}{{{path}}}")] + {{#authMethods}} + {{#-first}} + {{#isBasic}} + [Authorize(AuthenticationSchemes = BasicAuthenticationHandler.SchemeName)] + {{/isBasic}} + {{#isBearer}} + [Authorize(AuthenticationSchemes = BearerAuthenticationHandler.SchemeName)] + {{/isBearer}} + {{#isApiKey}} + [Authorize(AuthenticationSchemes = ApiKeyAuthenticationHandler.SchemeName)] + {{/isApiKey}} + {{/-first}} + {{/authMethods}} + [ValidateModelState] + [SwaggerOperation("{{operationId}}")]{{#responses}}{{#dataType}} + [SwaggerResponse(statusCode: {{code}}, type: typeof({{&dataType}}), description: "{{message}}")]{{/dataType}}{{^dataType}}{{/dataType}}{{/responses}} + public virtual IActionResult {{operationId}}({{#allParams}}{{>pathParam}}{{>queryParam}}{{>bodyParam}}{{>formParam}}{{>headerParam}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) + { {{#responses}} +{{#dataType}} + //TODO: Uncomment the next line to return response {{code}} or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode({{code}}, default({{&dataType}})); +{{/dataType}} +{{^dataType}} + //TODO: Uncomment the next line to return response {{code}} or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode({{code}}); +{{/dataType}}{{/responses}} +{{#returnType}} + string exampleJson = null; + {{#examples}} + exampleJson = "{{{example}}}"; + {{/examples}} + {{#isListCollection}}{{>listReturn}}{{/isListCollection}}{{^isListCollection}}{{#isMapContainer}}{{>mapReturn}}{{/isMapContainer}}{{^isMapContainer}}{{>objectReturn}}{{/isMapContainer}}{{/isListCollection}} + {{!TODO: defaultResponse, examples, auth, consumes, produces, nickname, externalDocs, imports, security}} + //TODO: Change the data returned + return new ObjectResult(example);{{/returnType}}{{^returnType}} + throw new NotImplementedException();{{/returnType}} + } + {{/operation}} + } +{{/operations}} +} diff --git a/modules/swagger-codegen/src/main/resources/aspnetcore/README.mustache b/modules/swagger-codegen/src/main/resources/aspnetcore/README.mustache index 03f23c1916a..425e0b5ae33 100644 --- a/modules/swagger-codegen/src/main/resources/aspnetcore/README.mustache +++ b/modules/swagger-codegen/src/main/resources/aspnetcore/README.mustache @@ -1,4 +1,4 @@ -# {{packageName}} - ASP.NET Core 2.0 Server +# {{packageName}} - ASP.NET Core {{aspNetCoreVersion}} Server {{#appDescription}} {{{appDescription}}} diff --git a/modules/swagger-codegen/src/main/resources/aspnetcore/wwwroot/README.md b/modules/swagger-codegen/src/main/resources/aspnetcore/wwwroot/README.md deleted file mode 100644 index 6a0b78471a3..00000000000 --- a/modules/swagger-codegen/src/main/resources/aspnetcore/wwwroot/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# Welcome to ASP.NET 5 Preview - -We've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new. - -ASP.NET 5 has been rearchitected to make it **lean** and **composable**. It's fully **open source** and available on [GitHub](http://go.microsoft.com/fwlink/?LinkID=517854). -Your new project automatically takes advantage of modern client-side utilities like [Bower](http://go.microsoft.com/fwlink/?LinkId=518004) and [npm](http://go.microsoft.com/fwlink/?LinkId=518005) (to add client-side libraries) and [Gulp](http://go.microsoft.com/fwlink/?LinkId=518007) (for client-side build and automation tasks). - -We hope you enjoy the new capabilities in ASP.NET 5 and Visual Studio 2015. -The ASP.NET Team - -### You've created a new ASP.NET 5 project. [Learn what's new](http://go.microsoft.com/fwlink/?LinkId=518016) - -### This application consists of: -* Sample pages using ASP.NET MVC 6 -* [Gulp](http://go.microsoft.com/fwlink/?LinkId=518007) and [Bower](http://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side resources -* Theming using [Bootstrap](http://go.microsoft.com/fwlink/?LinkID=398939) - -#### NEW CONCEPTS -* [The 'wwwroot' explained](http://go.microsoft.com/fwlink/?LinkId=518008) -* [Configuration in ASP.NET 5](http://go.microsoft.com/fwlink/?LinkId=518012) -* [Dependency Injection](http://go.microsoft.com/fwlink/?LinkId=518013) -* [Razor TagHelpers](http://go.microsoft.com/fwlink/?LinkId=518014) -* [Manage client packages using Gulp](http://go.microsoft.com/fwlink/?LinkID=517849) -* [Develop on different platforms](http://go.microsoft.com/fwlink/?LinkID=517850) - -#### CUSTOMIZE APP -* [Add Controllers and Views](http://go.microsoft.com/fwlink/?LinkID=398600) -* [Add Data using EntityFramework](http://go.microsoft.com/fwlink/?LinkID=398602) -* [Add Authentication using Identity](http://go.microsoft.com/fwlink/?LinkID=398603) -* [Add real time support using SignalR](http://go.microsoft.com/fwlink/?LinkID=398606) -* [Add Class library](http://go.microsoft.com/fwlink/?LinkID=398604) -* [Add Web APIs with MVC 6](http://go.microsoft.com/fwlink/?LinkId=518009) -* [Add client packages using Bower](http://go.microsoft.com/fwlink/?LinkID=517848) - -#### DEPLOY -* [Run your app locally](http://go.microsoft.com/fwlink/?LinkID=517851) -* [Run your app on ASP.NET Core 5](http://go.microsoft.com/fwlink/?LinkID=517852) -* [Run commands in your 'project.json'](http://go.microsoft.com/fwlink/?LinkID=517853) -* [Publish to Microsoft Azure Web Sites](http://go.microsoft.com/fwlink/?LinkID=398609) -* [Publish to the file system](http://go.microsoft.com/fwlink/?LinkId=518019) - -We would love to hear your [feedback](http://go.microsoft.com/fwlink/?LinkId=518015) diff --git a/samples/server/petstore/aspnetcore/.swagger-codegen/VERSION b/samples/server/petstore/aspnetcore/.swagger-codegen/VERSION index 6cecc1a68f3..158349812d2 100644 --- a/samples/server/petstore/aspnetcore/.swagger-codegen/VERSION +++ b/samples/server/petstore/aspnetcore/.swagger-codegen/VERSION @@ -1 +1 @@ -2.4.6-SNAPSHOT \ No newline at end of file +2.4.9 \ No newline at end of file diff --git a/samples/server/petstore/aspnetcore/IO.Swagger.sln b/samples/server/petstore/aspnetcore/IO.Swagger.sln index 045f3a11a74..218e3396343 100644 --- a/samples/server/petstore/aspnetcore/IO.Swagger.sln +++ b/samples/server/petstore/aspnetcore/IO.Swagger.sln @@ -2,7 +2,7 @@ # Visual Studio 15 VisualStudioVersion = 15.0.26114.2 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "IO.Swagger", "src\IO.Swagger\IO.Swagger.csproj", "{3C799344-F285-4669-8FD5-7ED9B795D5C5}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "IO.Swagger", "src\IO.Swagger\IO.Swagger.csproj", "{FBAB814D-29AC-42A0-8273-808F84F6E75C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -10,10 +10,10 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {3C799344-F285-4669-8FD5-7ED9B795D5C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3C799344-F285-4669-8FD5-7ED9B795D5C5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3C799344-F285-4669-8FD5-7ED9B795D5C5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3C799344-F285-4669-8FD5-7ED9B795D5C5}.Release|Any CPU.Build.0 = Release|Any CPU + {FBAB814D-29AC-42A0-8273-808F84F6E75C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FBAB814D-29AC-42A0-8273-808F84F6E75C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FBAB814D-29AC-42A0-8273-808F84F6E75C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FBAB814D-29AC-42A0-8273-808F84F6E75C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/samples/server/petstore/aspnetcore/README.md b/samples/server/petstore/aspnetcore/README.md index 07aa834ff03..eb0d56deed5 100644 --- a/samples/server/petstore/aspnetcore/README.md +++ b/samples/server/petstore/aspnetcore/README.md @@ -1,4 +1,4 @@ -# IO.Swagger - ASP.NET Core 2.0 Server +# IO.Swagger - ASP.NET Core 3.0 Server This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters. diff --git a/samples/server/petstore/aspnetcore/src/IO.Swagger/Controllers/PetApi.cs b/samples/server/petstore/aspnetcore/src/IO.Swagger/Controllers/PetApi.cs index e490fccc50b..54897f9bb06 100644 --- a/samples/server/petstore/aspnetcore/src/IO.Swagger/Controllers/PetApi.cs +++ b/samples/server/petstore/aspnetcore/src/IO.Swagger/Controllers/PetApi.cs @@ -89,7 +89,7 @@ public virtual IActionResult FindPetsByStatus([FromQuery][Required()]List>(exampleJson) @@ -120,7 +120,7 @@ public virtual IActionResult FindPetsByTags([FromQuery][Required()]List string exampleJson = null; exampleJson = "\n 123456789\n doggie\n \n aeiou\n \n \n \n aeiou\n"; - exampleJson = "[ {\n \"photoUrls\" : [ \"photoUrls\", \"photoUrls\" ],\n \"name\" : \"doggie\",\n \"id\" : 0,\n \"category\" : {\n \"name\" : \"name\",\n \"id\" : 6\n },\n \"tags\" : [ {\n \"name\" : \"name\",\n \"id\" : 1\n }, {\n \"name\" : \"name\",\n \"id\" : 1\n } ],\n \"status\" : \"available\"\n}, {\n \"photoUrls\" : [ \"photoUrls\", \"photoUrls\" ],\n \"name\" : \"doggie\",\n \"id\" : 0,\n \"category\" : {\n \"name\" : \"name\",\n \"id\" : 6\n },\n \"tags\" : [ {\n \"name\" : \"name\",\n \"id\" : 1\n }, {\n \"name\" : \"name\",\n \"id\" : 1\n } ],\n \"status\" : \"available\"\n} ]"; + exampleJson = "[ {\n \"tags\" : [ {\n \"id\" : 1,\n \"name\" : \"name\"\n }, {\n \"id\" : 1,\n \"name\" : \"name\"\n } ],\n \"id\" : 0,\n \"category\" : {\n \"id\" : 6,\n \"name\" : \"name\"\n },\n \"status\" : \"available\",\n \"name\" : \"doggie\",\n \"photoUrls\" : [ \"photoUrls\", \"photoUrls\" ]\n}, {\n \"tags\" : [ {\n \"id\" : 1,\n \"name\" : \"name\"\n }, {\n \"id\" : 1,\n \"name\" : \"name\"\n } ],\n \"id\" : 0,\n \"category\" : {\n \"id\" : 6,\n \"name\" : \"name\"\n },\n \"status\" : \"available\",\n \"name\" : \"doggie\",\n \"photoUrls\" : [ \"photoUrls\", \"photoUrls\" ]\n} ]"; var example = exampleJson != null ? JsonConvert.DeserializeObject>(exampleJson) @@ -156,7 +156,7 @@ public virtual IActionResult GetPetById([FromRoute][Required]long? petId) string exampleJson = null; exampleJson = "\n 123456789\n doggie\n \n aeiou\n \n \n \n aeiou\n"; - exampleJson = "{\n \"photoUrls\" : [ \"photoUrls\", \"photoUrls\" ],\n \"name\" : \"doggie\",\n \"id\" : 0,\n \"category\" : {\n \"name\" : \"name\",\n \"id\" : 6\n },\n \"tags\" : [ {\n \"name\" : \"name\",\n \"id\" : 1\n }, {\n \"name\" : \"name\",\n \"id\" : 1\n } ],\n \"status\" : \"available\"\n}"; + exampleJson = "{\n \"tags\" : [ {\n \"id\" : 1,\n \"name\" : \"name\"\n }, {\n \"id\" : 1,\n \"name\" : \"name\"\n } ],\n \"id\" : 0,\n \"category\" : {\n \"id\" : 6,\n \"name\" : \"name\"\n },\n \"status\" : \"available\",\n \"name\" : \"doggie\",\n \"photoUrls\" : [ \"photoUrls\", \"photoUrls\" ]\n}"; var example = exampleJson != null ? JsonConvert.DeserializeObject(exampleJson) @@ -232,7 +232,7 @@ public virtual IActionResult UploadFile([FromRoute][Required]long? petId, [FromF // return StatusCode(200, default(ApiResponse)); string exampleJson = null; - exampleJson = "{\n \"code\" : 0,\n \"type\" : \"type\",\n \"message\" : \"message\"\n}"; + exampleJson = "{\n \"message\" : \"message\",\n \"code\" : 0,\n \"type\" : \"type\"\n}"; var example = exampleJson != null ? JsonConvert.DeserializeObject(exampleJson) diff --git a/samples/server/petstore/aspnetcore/src/IO.Swagger/Controllers/StoreApi.cs b/samples/server/petstore/aspnetcore/src/IO.Swagger/Controllers/StoreApi.cs index 306edc31d52..621ef4cfbc0 100644 --- a/samples/server/petstore/aspnetcore/src/IO.Swagger/Controllers/StoreApi.cs +++ b/samples/server/petstore/aspnetcore/src/IO.Swagger/Controllers/StoreApi.cs @@ -103,7 +103,7 @@ public virtual IActionResult GetOrderById([FromRoute][Required][Range(1, 5)]long string exampleJson = null; exampleJson = "\n 123456789\n 123456789\n 123\n 2000-01-23T04:56:07.000Z\n aeiou\n true\n"; - exampleJson = "{\n \"petId\" : 6,\n \"quantity\" : 1,\n \"id\" : 0,\n \"shipDate\" : \"2000-01-23T04:56:07.000+00:00\",\n \"complete\" : false,\n \"status\" : \"placed\"\n}"; + exampleJson = "{\n \"id\" : 0,\n \"petId\" : 6,\n \"complete\" : false,\n \"status\" : \"placed\",\n \"quantity\" : 1,\n \"shipDate\" : \"2000-01-23T04:56:07.000+00:00\"\n}"; var example = exampleJson != null ? JsonConvert.DeserializeObject(exampleJson) @@ -134,7 +134,7 @@ public virtual IActionResult PlaceOrder([FromBody]Order body) string exampleJson = null; exampleJson = "\n 123456789\n 123456789\n 123\n 2000-01-23T04:56:07.000Z\n aeiou\n true\n"; - exampleJson = "{\n \"petId\" : 6,\n \"quantity\" : 1,\n \"id\" : 0,\n \"shipDate\" : \"2000-01-23T04:56:07.000+00:00\",\n \"complete\" : false,\n \"status\" : \"placed\"\n}"; + exampleJson = "{\n \"id\" : 0,\n \"petId\" : 6,\n \"complete\" : false,\n \"status\" : \"placed\",\n \"quantity\" : 1,\n \"shipDate\" : \"2000-01-23T04:56:07.000+00:00\"\n}"; var example = exampleJson != null ? JsonConvert.DeserializeObject(exampleJson) diff --git a/samples/server/petstore/aspnetcore/src/IO.Swagger/Controllers/UserApi.cs b/samples/server/petstore/aspnetcore/src/IO.Swagger/Controllers/UserApi.cs index 29e97a7b35e..f337dac0006 100644 --- a/samples/server/petstore/aspnetcore/src/IO.Swagger/Controllers/UserApi.cs +++ b/samples/server/petstore/aspnetcore/src/IO.Swagger/Controllers/UserApi.cs @@ -134,7 +134,7 @@ public virtual IActionResult GetUserByName([FromRoute][Required]string username) string exampleJson = null; exampleJson = "\n 123456789\n aeiou\n aeiou\n aeiou\n aeiou\n aeiou\n aeiou\n 123\n"; - exampleJson = "{\n \"firstName\" : \"firstName\",\n \"lastName\" : \"lastName\",\n \"password\" : \"password\",\n \"userStatus\" : 6,\n \"phone\" : \"phone\",\n \"id\" : 0,\n \"email\" : \"email\",\n \"username\" : \"username\"\n}"; + exampleJson = "{\n \"id\" : 0,\n \"lastName\" : \"lastName\",\n \"phone\" : \"phone\",\n \"username\" : \"username\",\n \"email\" : \"email\",\n \"userStatus\" : 6,\n \"firstName\" : \"firstName\",\n \"password\" : \"password\"\n}"; var example = exampleJson != null ? JsonConvert.DeserializeObject(exampleJson) diff --git a/samples/server/petstore/aspnetcore/src/IO.Swagger/Dockerfile b/samples/server/petstore/aspnetcore/src/IO.Swagger/Dockerfile index 6b07232e561..2fc62d322e0 100644 --- a/samples/server/petstore/aspnetcore/src/IO.Swagger/Dockerfile +++ b/samples/server/petstore/aspnetcore/src/IO.Swagger/Dockerfile @@ -1,4 +1,4 @@ -FROM microsoft/aspnetcore-build:2.0 AS build-env +FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS build-env WORKDIR /app ENV DOTNET_CLI_TELEMETRY_OPTOUT 1 @@ -12,7 +12,7 @@ COPY . ./ RUN dotnet publish -c Release -o out # build runtime image -FROM microsoft/aspnetcore:2.0 +FROM mcr.microsoft.com/dotnet/core/aspnet:3.0 WORKDIR /app COPY --from=build-env /app/out . ENTRYPOINT ["dotnet", "IO.Swagger.dll"] diff --git a/samples/server/petstore/aspnetcore/src/IO.Swagger/Filters/BasePathFilter.cs b/samples/server/petstore/aspnetcore/src/IO.Swagger/Filters/BasePathFilter.cs index f3c528eada2..c9d95d6d189 100644 --- a/samples/server/petstore/aspnetcore/src/IO.Swagger/Filters/BasePathFilter.cs +++ b/samples/server/petstore/aspnetcore/src/IO.Swagger/Filters/BasePathFilter.cs @@ -2,6 +2,7 @@ using System.Text.RegularExpressions; using Swashbuckle.AspNetCore.Swagger; using Swashbuckle.AspNetCore.SwaggerGen; +using Microsoft.OpenApi.Models; namespace IO.Swagger.Filters { @@ -28,11 +29,11 @@ public BasePathFilter(string basePath) /// /// Apply the filter /// - /// SwaggerDocument + /// OpenApiDocument /// FilterContext - public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context) + public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { - swaggerDoc.BasePath = this.BasePath; + swaggerDoc.Servers.Add(new OpenApiServer() { Url = this.BasePath }); var pathsToModify = swaggerDoc.Paths.Where(p => p.Key.StartsWith(this.BasePath)).ToList(); diff --git a/samples/server/petstore/aspnetcore/src/IO.Swagger/Filters/GeneratePathParamsValidationFilter.cs b/samples/server/petstore/aspnetcore/src/IO.Swagger/Filters/GeneratePathParamsValidationFilter.cs index a0e2cb6871d..a16d303b32a 100644 --- a/samples/server/petstore/aspnetcore/src/IO.Swagger/Filters/GeneratePathParamsValidationFilter.cs +++ b/samples/server/petstore/aspnetcore/src/IO.Swagger/Filters/GeneratePathParamsValidationFilter.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc.Controllers; using Swashbuckle.AspNetCore.Swagger; using Swashbuckle.AspNetCore.SwaggerGen; +using Microsoft.OpenApi.Models; namespace IO.Swagger.Filters { @@ -16,7 +17,7 @@ public class GeneratePathParamsValidationFilter : IOperationFilter /// /// Operation /// OperationFilterContext - public void Apply(Operation operation, OperationFilterContext context) + public void Apply(OpenApiOperation operation, OperationFilterContext context) { var pars = context.ApiDescription.ParameterDescriptions; @@ -40,9 +41,9 @@ public void Apply(Operation operation, OperationFilterContext context) if (regexAttr != null) { string regex = (string)regexAttr.ConstructorArguments[0].Value; - if (swaggerParam is NonBodyParameter) + if (swaggerParam is OpenApiParameter) { - ((NonBodyParameter)swaggerParam).Pattern = regex; + ((OpenApiParameter)swaggerParam).Schema.Pattern = regex; } } @@ -70,10 +71,10 @@ public void Apply(Operation operation, OperationFilterContext context) maxLength = (int)maxLengthAttr.ConstructorArguments[0].Value; } - if (swaggerParam is NonBodyParameter) + if (swaggerParam is OpenApiParameter) { - ((NonBodyParameter)swaggerParam).MinLength = minLenght; - ((NonBodyParameter)swaggerParam).MaxLength = maxLength; + ((OpenApiParameter)swaggerParam).Schema.MinLength = minLenght; + ((OpenApiParameter)swaggerParam).Schema.MaxLength = maxLength; } // Range [Range] @@ -83,10 +84,10 @@ public void Apply(Operation operation, OperationFilterContext context) int rangeMin = (int)rangeAttr.ConstructorArguments[0].Value; int rangeMax = (int)rangeAttr.ConstructorArguments[1].Value; - if (swaggerParam is NonBodyParameter) + if (swaggerParam is OpenApiParameter) { - ((NonBodyParameter)swaggerParam).Minimum = rangeMin; - ((NonBodyParameter)swaggerParam).Maximum = rangeMax; + ((OpenApiParameter)swaggerParam).Schema.Minimum = rangeMin; + ((OpenApiParameter)swaggerParam).Schema.Maximum = rangeMax; } } } diff --git a/samples/server/petstore/aspnetcore/src/IO.Swagger/IO.Swagger.csproj b/samples/server/petstore/aspnetcore/src/IO.Swagger/IO.Swagger.csproj index 616076b6078..b864e584350 100644 --- a/samples/server/petstore/aspnetcore/src/IO.Swagger/IO.Swagger.csproj +++ b/samples/server/petstore/aspnetcore/src/IO.Swagger/IO.Swagger.csproj @@ -2,18 +2,19 @@ IO.Swagger IO.Swagger - netcoreapp2.2 + netcoreapp3.0 true true IO.Swagger IO.Swagger - - - + + + + - + diff --git a/samples/server/petstore/aspnetcore/src/IO.Swagger/Startup.cs b/samples/server/petstore/aspnetcore/src/IO.Swagger/Startup.cs index 73dc4b97234..3cb7c12d86a 100644 --- a/samples/server/petstore/aspnetcore/src/IO.Swagger/Startup.cs +++ b/samples/server/petstore/aspnetcore/src/IO.Swagger/Startup.cs @@ -10,11 +10,14 @@ using System; using System.IO; +using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using Microsoft.OpenApi.Models; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Serialization; using Swashbuckle.AspNetCore.Swagger; @@ -22,8 +25,6 @@ using IO.Swagger.Filters; using IO.Swagger.Security; -using Microsoft.AspNetCore.Authentication; - namespace IO.Swagger { /// @@ -31,7 +32,7 @@ namespace IO.Swagger /// public class Startup { - private readonly IHostingEnvironment _hostingEnv; + private readonly IWebHostEnvironment _hostingEnv; private IConfiguration Configuration { get; } @@ -40,7 +41,7 @@ public class Startup /// /// /// - public Startup(IHostingEnvironment env, IConfiguration configuration) + public Startup(IWebHostEnvironment env, IConfiguration configuration) { _hostingEnv = env; Configuration = configuration; @@ -54,13 +55,15 @@ public void ConfigureServices(IServiceCollection services) { // Add framework services. services - .AddMvc() - .AddJsonOptions(opts => + .AddMvc(options => + { + options.InputFormatters.RemoveType(); + options.OutputFormatters.RemoveType(); + }) + .AddNewtonsoftJson(opts => { opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); - opts.SerializerSettings.Converters.Add(new StringEnumConverter { - CamelCaseText = true - }); + opts.SerializerSettings.Converters.Add(new StringEnumConverter(new CamelCaseNamingStrategy())); }) .AddXmlSerializerFormatters(); @@ -71,21 +74,20 @@ public void ConfigureServices(IServiceCollection services) services .AddSwaggerGen(c => { - c.SwaggerDoc("1.0.0", new Info + c.SwaggerDoc("1.0.0", new OpenApiInfo { Version = "1.0.0", Title = "Swagger Petstore", - Description = "Swagger Petstore (ASP.NET Core 2.0)", - Contact = new Contact() + Description = "Swagger Petstore (ASP.NET Core 3.0)", + Contact = new OpenApiContact() { Name = "Swagger Codegen Contributors", - Url = "https://github.com/swagger-api/swagger-codegen", + Url = new Uri("https://github.com/swagger-api/swagger-codegen"), Email = "apiteam@swagger.io" }, - TermsOfService = "http://swagger.io/terms/" + TermsOfService = new Uri("http://swagger.io/terms/") }); - c.CustomSchemaIds(type => type.FriendlyId(true)); - c.DescribeAllEnumsAsStrings(); + c.CustomSchemaIds(type => type.FullName); c.IncludeXmlComments($"{AppContext.BaseDirectory}{Path.DirectorySeparatorChar}{_hostingEnv.ApplicationName}.xml"); // Sets the basePath property in the Swagger document generated c.DocumentFilter("/v2"); @@ -102,21 +104,32 @@ public void ConfigureServices(IServiceCollection services) /// /// /// - public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) { - app - .UseMvc() - .UseDefaultFiles() - .UseStaticFiles() - .UseSwagger() - .UseSwaggerUI(c => - { - //TODO: Either use the SwaggerGen generated Swagger contract (generated from C# classes) - c.SwaggerEndpoint("/swagger/1.0.0/swagger.json", "Swagger Petstore"); + app.UseRouting(); - //TODO: Or alternatively use the original Swagger contract that's included in the static files - // c.SwaggerEndpoint("/swagger-original.json", "Swagger Petstore Original"); - }); + //TODO: Uncomment this if you need wwwroot folder + // app.UseStaticFiles(); + + app.UseAuthorization(); + + app.UseSwagger(); + app.UseSwaggerUI(c => + { + //TODO: Either use the SwaggerGen generated Swagger contract (generated from C# classes) + c.SwaggerEndpoint("/swagger/1.0.0/swagger.json", "Swagger Petstore"); + + //TODO: Or alternatively use the original Swagger contract that's included in the static files + // c.SwaggerEndpoint("/swagger-original.json", "Swagger Petstore Original"); + }); + + //TODO: Use Https Redirection + // app.UseHttpsRedirection(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); if (env.IsDevelopment()) { @@ -125,7 +138,9 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF else { //TODO: Enable production exception handling (https://docs.microsoft.com/en-us/aspnet/core/fundamentals/error-handling) - // app.UseExceptionHandler("/Home/Error"); + app.UseExceptionHandler("/Error"); + + app.UseHsts(); } } } diff --git a/samples/server/petstore/aspnetcore/src/IO.Swagger/wwwroot/swagger-original.json b/samples/server/petstore/aspnetcore/src/IO.Swagger/wwwroot/swagger-original.json index 55fa5c40e20..79c777eae67 100644 --- a/samples/server/petstore/aspnetcore/src/IO.Swagger/wwwroot/swagger-original.json +++ b/samples/server/petstore/aspnetcore/src/IO.Swagger/wwwroot/swagger-original.json @@ -108,8 +108,8 @@ "type" : "array", "items" : { "type" : "string", - "default" : "available", - "enum" : [ "available", "pending", "sold" ] + "enum" : [ "available", "pending", "sold" ], + "default" : "available" }, "collectionFormat" : "csv" } ], @@ -688,12 +688,12 @@ }, "description" : "An order for a pets from the pet store", "example" : { - "petId" : 6, - "quantity" : 1, "id" : 0, - "shipDate" : "2000-01-23T04:56:07.000+00:00", + "petId" : 6, "complete" : false, - "status" : "placed" + "status" : "placed", + "quantity" : 1, + "shipDate" : "2000-01-23T04:56:07.000+00:00" } }, "Category" : { @@ -713,8 +713,8 @@ }, "description" : "A category for a pet", "example" : { - "name" : "name", - "id" : 6 + "id" : 6, + "name" : "name" } }, "User" : { @@ -754,14 +754,14 @@ }, "description" : "A User who is purchasing from the pet store", "example" : { - "firstName" : "firstName", + "id" : 0, "lastName" : "lastName", - "password" : "password", - "userStatus" : 6, "phone" : "phone", - "id" : 0, + "username" : "username", "email" : "email", - "username" : "username" + "userStatus" : 6, + "firstName" : "firstName", + "password" : "password" } }, "Tag" : { @@ -781,8 +781,8 @@ }, "description" : "A tag for a pet", "example" : { - "name" : "name", - "id" : 1 + "id" : 1, + "name" : "name" } }, "Pet" : { @@ -832,21 +832,21 @@ }, "description" : "A pet for sale in the pet store", "example" : { - "photoUrls" : [ "photoUrls", "photoUrls" ], - "name" : "doggie", - "id" : 0, - "category" : { - "name" : "name", - "id" : 6 - }, "tags" : [ { - "name" : "name", - "id" : 1 + "id" : 1, + "name" : "name" }, { - "name" : "name", - "id" : 1 + "id" : 1, + "name" : "name" } ], - "status" : "available" + "id" : 0, + "category" : { + "id" : 6, + "name" : "name" + }, + "status" : "available", + "name" : "doggie", + "photoUrls" : [ "photoUrls", "photoUrls" ] } }, "ApiResponse" : { @@ -866,9 +866,9 @@ "title" : "An uploaded response", "description" : "Describes the result of uploading an image resource", "example" : { + "message" : "message", "code" : 0, - "type" : "type", - "message" : "message" + "type" : "type" } }, "Amount" : {