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> <SerilogSinksFilePackageVersion>4.0.0</SerilogSinksFilePackageVersion>
<StackExchangeRedisPackageVersion>2.0.593</StackExchangeRedisPackageVersion> <StackExchangeRedisPackageVersion>2.0.593</StackExchangeRedisPackageVersion>
<SystemReactiveLinqPackageVersion>3.1.1</SystemReactiveLinqPackageVersion> <SystemReactiveLinqPackageVersion>3.1.1</SystemReactiveLinqPackageVersion>
<SwashbuckleAspNetCorePackageVersion>5.5.1</SwashbuckleAspNetCorePackageVersion>
<XunitAbstractionsPackageVersion>2.0.3</XunitAbstractionsPackageVersion> <XunitAbstractionsPackageVersion>2.0.3</XunitAbstractionsPackageVersion>
<XunitAnalyzersPackageVersion>0.10.0</XunitAnalyzersPackageVersion> <XunitAnalyzersPackageVersion>0.10.0</XunitAnalyzersPackageVersion>
<XunitVersion>2.4.1</XunitVersion> <XunitVersion>2.4.1</XunitVersion>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -26,6 +26,10 @@ using Microsoft.Extensions.Logging;
#if (GenerateGraph) #if (GenerateGraph)
using Microsoft.Graph; using Microsoft.Graph;
#endif #endif
#if (EnableOpenAPI)
using Microsoft.OpenApi.Models;
#endif
namespace Company.WebApplication1 namespace Company.WebApplication1
{ {
public class Startup public class Startup
@ -71,6 +75,12 @@ namespace Company.WebApplication1
#endif #endif
services.AddControllers(); 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. // 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()) if (env.IsDevelopment())
{ {
app.UseDeveloperExceptionPage(); app.UseDeveloperExceptionPage();
#if (EnableOpenAPI)
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Company.WebApplication1 v1"));
#endif
} }
#if (RequiresHttps) #if (RequiresHttps)
app.UseHttpsRedirection(); app.UseHttpsRedirection();
#endif #endif
app.UseRouting(); app.UseRouting();
#if (OrganizationalAuth || IndividualAuth) #if (OrganizationalAuth || IndividualAuth)

View File

@ -39,6 +39,26 @@ namespace Templates.Test
[SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] [SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")]
public Task WebApiTemplateCSharp() => WebApiTemplateCore(languageOverride: null); 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) 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); 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)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
await aspNetProcess.AssertOk("weatherforecast"); await aspNetProcess.AssertOk("weatherforecast");
await aspNetProcess.AssertOk("swagger");
await aspNetProcess.AssertNotFound("/"); await aspNetProcess.AssertNotFound("/");
} }
@ -91,6 +112,8 @@ namespace Templates.Test
await aspNetProcess.AssertOk("weatherforecast"); await aspNetProcess.AssertOk("weatherforecast");
// Swagger is only available in Development
await aspNetProcess.AssertNotFound("swagger");
await aspNetProcess.AssertNotFound("/"); await aspNetProcess.AssertNotFound("/");
} }
} }