Configure OpenAPI as part of webapi project template creation (#25110)

* Configure OpenAPI as part of webapi project template creation
Fixes https://github.com/dotnet/aspnetcore/issues/25080

* Update to default to WebAPI
This commit is contained in:
Pranav K 2020-08-21 16:44:11 -07:00 committed by GitHub
parent 50815ed598
commit 0960a7a0c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 106 additions and 34 deletions

View File

@ -274,6 +274,7 @@
<SerilogSinksFilePackageVersion>4.0.0</SerilogSinksFilePackageVersion>
<StackExchangeRedisPackageVersion>2.0.593</StackExchangeRedisPackageVersion>
<SystemReactiveLinqPackageVersion>3.1.1</SystemReactiveLinqPackageVersion>
<SwashbuckleAspNetCorePackageVersion>5.5.1</SwashbuckleAspNetCorePackageVersion>
<XunitAbstractionsPackageVersion>2.0.3</XunitAbstractionsPackageVersion>
<XunitAnalyzersPackageVersion>0.10.0</XunitAnalyzersPackageVersion>
<XunitVersion>2.4.1</XunitVersion>

View File

@ -23,6 +23,7 @@
MicrosoftNETCoreAppRuntimeVersion=$(MicrosoftNETCoreAppRuntimeVersion);
SystemNetHttpJsonPackageVersion=$(SystemNetHttpJsonPackageVersion);
MicrosoftGraphPackageVersion=$(MicrosoftGraphPackageVersion);
SwashbuckleAspNetCorePackageVersion=$(SwashbuckleAspNetCorePackageVersion);
</GeneratedContentProperties>
</PropertyGroup>

View File

@ -6,13 +6,14 @@
<NoDefaultLaunchSettingsFile Condition="'$(ExcludeLaunchSettings)' == 'True'">True</NoDefaultLaunchSettingsFile>
<RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">Company.WebApplication1</RootNamespace>
</PropertyGroup>
<!--#if (OrganizationalAuth || IndividualB2CAuth) -->
<!--#if (OrganizationalAuth || IndividualB2CAuth || EnableOpenAPI) -->
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="${MicrosoftAspNetCoreAuthenticationJwtBearerPackageVersion}" NoWarn="NU1605" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="${MicrosoftAspNetCoreAuthenticationOpenIdConnectPackageVersion}" NoWarn="NU1605" />
<PackageReference Include="Microsoft.Identity.Web" Version="${MicrosoftIdentityWebPackageVersion}" />
<PackageReference Include="Microsoft.Graph" Version="${MicrosoftGraphPackageVersion}" Condition=" '$(GenerateGraph)' == 'True' "/>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="${MicrosoftAspNetCoreAuthenticationJwtBearerPackageVersion}" NoWarn="NU1605" Condition="'$(OrganizationalAuth)' == 'True' OR '$(IndividualB2CAuth)' == 'True'"/>
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="${MicrosoftAspNetCoreAuthenticationOpenIdConnectPackageVersion}" NoWarn="NU1605" Condition="'$(OrganizationalAuth)' == 'True' OR '$(IndividualB2CAuth)' == 'True'"/>
<PackageReference Include="Microsoft.Identity.Web" Version="${MicrosoftIdentityWebPackageVersion}" Condition="'$(OrganizationalAuth)' == 'True' OR '$(IndividualB2CAuth)' == 'True'"/>
<PackageReference Include="Microsoft.Graph" Version="${MicrosoftGraphPackageVersion}" Condition="'$(GenerateGraph)' == 'True'"/>
<PackageReference Include="Swashbuckle.AspNetCore" Version="${SwashbuckleAspNetCorePackageVersion}" Condition="'$(EnableOpenAPI)' == 'True'" />
</ItemGroup>
<!--#endif -->

View File

@ -57,19 +57,23 @@
"shortName": ""
},
"CalledApiUrl": {
"longName": "called-api-url",
"shortName": ""
"longName": "called-api-url",
"shortName": ""
},
"CalledApiScopes": {
"longName": "called-api-scopes",
"shortName": ""
"longName": "called-api-scopes",
"shortName": ""
},
"CallsMicrosoftGraph": {
"longName": "calls-graph",
"shortName": ""
"longName": "calls-graph",
"shortName": ""
},
"DisableOpenAPI": {
"longName": "no-openapi",
"shortName": ""
}
},
"usageExamples": [
""
]
}
}

View File

@ -39,14 +39,14 @@
},
{
"condition": "(!GenerateApi)",
"exclude": [
"Services/DownstreamWebApi.cs"
]
"exclude": [
"Services/DownstreamWebApi.cs"
]
},
{
"condition": "(!GenerateGraph)",
"exclude": [
"Services/MicrosoftGraphServiceExtensions.cs",
"Services/MicrosoftGraphServiceExtensions.cs",
"Services/TokenAcquisitionCredentialProvider.cs"
]
}
@ -244,35 +244,45 @@
"defaultValue": "false"
},
"CalledApiUrl": {
"type": "parameter",
"datatype": "string",
"replaces": "[WebApiUrl]",
"defaultValue" : "https://graph.microsoft.com/v1.0",
"description": "URL of the API to call from the web app. This option only applies if --auth SingleOrg or --auth IndividualB2C is specified."
"type": "parameter",
"datatype": "string",
"replaces": "[WebApiUrl]",
"defaultValue": "https://graph.microsoft.com/v1.0",
"description": "URL of the API to call from the web app. This option only applies if --auth SingleOrg or --auth IndividualB2C is specified."
},
"CallsMicrosoftGraph": {
"type": "parameter",
"datatype": "bool",
"defaultValue": "false",
"description": "Specifies if the web app calls Microsoft Graph. This option only applies if --auth SingleOrg is specified."
"type": "parameter",
"datatype": "bool",
"defaultValue": "false",
"description": "Specifies if the web app calls Microsoft Graph. This option only applies if --auth SingleOrg is specified."
},
"CalledApiScopes": {
"type": "parameter",
"datatype": "string",
"replaces" : "user.read",
"replaces": "user.read",
"description": "Scopes to request to call the API from the web app. This option only applies if --auth SingleOrg or --auth IndividualB2C is specified."
},
"GenerateApi": {
"type": "computed",
"value": "((IndividualB2CAuth || OrganizationalAuth) && (CalledApiUrl != \"https://graph.microsoft.com/v1.0\" || CalledApiScopes != \"user.read\"))"
"type": "computed",
"value": "((IndividualB2CAuth || OrganizationalAuth) && (CalledApiUrl != \"https://graph.microsoft.com/v1.0\" || CalledApiScopes != \"user.read\"))"
},
"GenerateGraph": {
"type": "computed",
"value": "(OrganizationalAuth && CallsMicrosoftGraph)"
"type": "computed",
"value": "(OrganizationalAuth && CallsMicrosoftGraph)"
},
"GenerateApiOrGraph": {
"type": "computed",
"value": "(GenerateApi || GenerateGraph)"
"type": "computed",
"value": "(GenerateApi || GenerateGraph)"
},
"DisableOpenAPI": {
"type": "parameter",
"dataType": "bool",
"defaultValue": "false",
"description": "Disable OpenAPI (Swagger) support"
},
"EnableOpenAPI": {
"type": "computed",
"value": "(!DisableOpenAPI)"
}
},
"primaryOutputs": [
@ -294,4 +304,4 @@
"continueOnError": true
}
]
}
}

View File

@ -49,6 +49,17 @@
"useHttps": true
}
],
"symbolInfo": [
{
"id": "DisableOpenAPI",
"name": {
"text": "Enable _OpenAPI support"
},
"invertBoolean": true,
"isVisible": true,
"defaultValue": true
}
],
"excludeLaunchSettings": false,
"azureReplyUrlPortName": "HttpsPort",
"minFullFrameworkVersion": "4.6.1",

View File

@ -21,7 +21,11 @@
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
//#if(EnableOpenAPI)
"launchUrl": "swagger",
//#else
"launchUrl": "weatherforecast",
//#endif
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
@ -30,7 +34,11 @@
"commandName": "Project",
"dotnetRunMessages": "true",
"launchBrowser": true,
//#if(EnableOpenAPI)
"launchUrl": "swagger",
//#else
"launchUrl": "weatherforecast",
//#endif
//#if(RequiresHttps)
"applicationUrl": "https://localhost:5001;http://localhost:5000",
//#else

View File

@ -26,6 +26,10 @@ using Microsoft.Extensions.Logging;
#if (GenerateGraph)
using Microsoft.Graph;
#endif
#if (EnableOpenAPI)
using Microsoft.OpenApi.Models;
#endif
namespace Company.WebApplication1
{
public class Startup
@ -71,6 +75,12 @@ namespace Company.WebApplication1
#endif
services.AddControllers();
#if (EnableOpenAPI)
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Company.WebApplication1", Version = "v1" });
});
#endif
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@ -79,12 +89,15 @@ namespace Company.WebApplication1
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
#if (EnableOpenAPI)
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Company.WebApplication1 v1"));
#endif
}
#if (RequiresHttps)
app.UseHttpsRedirection();
#endif
app.UseRouting();
#if (OrganizationalAuth || IndividualAuth)

View File

@ -39,6 +39,26 @@ namespace Templates.Test
[SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")]
public Task WebApiTemplateCSharp() => WebApiTemplateCore(languageOverride: null);
[ConditionalFact]
[SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")]
public async Task WebApiTemplateCSharp_WithoutOpenAPI()
{
Project = await FactoryFixture.GetOrCreateProject("webapinoopenapi", Output);
var createResult = await Project.RunDotNetNewAsync("webapi", args: new[] { "--no-openapi" });
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
var buildResult = await Project.RunDotNetBuildAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult));
using var aspNetProcess = Project.StartBuiltProjectAsync();
Assert.False(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
await aspNetProcess.AssertNotFound("swagger");
}
private async Task PublishAndBuildWebApiTemplate(string languageOverride, string auth, string[] args)
{
Project = await FactoryFixture.GetOrCreateProject("webapi" + (languageOverride == "F#" ? "fsharp" : "csharp") + Guid.NewGuid().ToString().Substring(0, 10).ToLower(), Output);
@ -80,6 +100,7 @@ namespace Templates.Test
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
await aspNetProcess.AssertOk("weatherforecast");
await aspNetProcess.AssertOk("swagger");
await aspNetProcess.AssertNotFound("/");
}
@ -91,6 +112,8 @@ namespace Templates.Test
await aspNetProcess.AssertOk("weatherforecast");
// Swagger is only available in Development
await aspNetProcess.AssertNotFound("swagger");
await aspNetProcess.AssertNotFound("/");
}
}