Ok, everything seems to be working except for the api explorer so now can turn back to that. (api explorer issues are caused by the api versioning system as removing it fixes the missing api explorer routes
This commit is contained in:
@@ -62,31 +62,36 @@ namespace AyaNova
|
||||
{
|
||||
_log.LogDebug("BOOT: initializing services...");
|
||||
|
||||
//dotnet 3.x added this wasn't here before
|
||||
services.AddControllers();
|
||||
|
||||
services.AddSwaggerGen(c =>
|
||||
{
|
||||
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
|
||||
});
|
||||
|
||||
//Server state service for shutting people out of api
|
||||
_log.LogDebug("BOOT: init ApiServerState service");
|
||||
services.AddSingleton(new AyaNova.Api.ControllerHelpers.ApiServerState());
|
||||
|
||||
//Init controllers
|
||||
_log.LogDebug("BOOT: init controllers");
|
||||
var MvcBuilder = services.AddControllers(config =>
|
||||
{
|
||||
config.Filters.Add(new AyaNova.Api.ControllerHelpers.ApiCustomExceptionFilter(AyaNova.Util.ApplicationLogging.LoggerFactory));
|
||||
});
|
||||
|
||||
_log.LogDebug("BOOT: init JSON");
|
||||
MvcBuilder.AddNewtonsoftJson(options =>
|
||||
{
|
||||
options.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
|
||||
});
|
||||
|
||||
//2019-10-17 METRICS will not work just yet with .netcore 3.1 see here https://github.com/AppMetrics/AppMetrics/issues/480
|
||||
//awaiting a new release from them
|
||||
//_log.LogDebug("BOOT: init Metrics service");
|
||||
//MvcBuilder.AddMetrics();
|
||||
|
||||
//dotnet 3 commented this out, new project doesn't have it
|
||||
//Init mvc
|
||||
// _log.LogDebug("BOOT: init MVC Core service");
|
||||
// var mvc = services.AddMvcCore();
|
||||
// _log.LogDebug("BOOT: add json service");
|
||||
// mvc.AddNewtonsoftJson();
|
||||
|
||||
|
||||
// add the versioned api explorer, which also adds IApiVersionDescriptionProvider service
|
||||
// note: the specified format code will format the version as "'v'major[.minor][-status]"
|
||||
_log.LogDebug("BOOT: init ApiExplorer service");
|
||||
// services.AddVersionedApiExplorer(o => o.GroupNameFormat = "'v'VVV");
|
||||
services.AddVersionedApiExplorer(o => o.GroupNameFormat = "'v'VVV");
|
||||
|
||||
_log.LogDebug("BOOT: ensuring user and backup folders exist and are separate locations...");
|
||||
FileUtil.EnsureUserAndUtilityFoldersExistAndAreNotIdentical(_hostingEnvironment.ContentRootPath);
|
||||
@@ -143,46 +148,31 @@ namespace AyaNova
|
||||
#endregion
|
||||
|
||||
_log.LogDebug("BOOT: init ApiVersioning service");
|
||||
// services
|
||||
// .AddApiVersioning(options =>
|
||||
// {
|
||||
// options.AssumeDefaultVersionWhenUnspecified = true;
|
||||
// options.DefaultApiVersion = Microsoft.AspNetCore.Mvc.ApiVersion.Parse("8.0");
|
||||
// options.ReportApiVersions = true;
|
||||
// });
|
||||
// services.AddApiVersioning(o => o.ReportApiVersions = true);
|
||||
services
|
||||
.AddApiVersioning(options =>
|
||||
{
|
||||
options.AssumeDefaultVersionWhenUnspecified = true;
|
||||
options.DefaultApiVersion = Microsoft.AspNetCore.Mvc.ApiVersion.Parse("8.0");
|
||||
options.ReportApiVersions = true;
|
||||
});
|
||||
|
||||
|
||||
//v3 commented out to try to figure out why the swagger docs aren't generating and may be superfluous
|
||||
// // Add service and create Policy with options
|
||||
// _log.LogDebug("BOOT: init CORS service");
|
||||
// services.AddCors(options =>
|
||||
// {
|
||||
// options.AddPolicy("CorsPolicy",
|
||||
// builder => builder.AllowAnyOrigin()
|
||||
// .AllowAnyMethod()
|
||||
// .AllowAnyHeader()
|
||||
// //.AllowCredentials()
|
||||
// );
|
||||
// });
|
||||
// Add service and create Policy with options
|
||||
_log.LogDebug("BOOT: init CORS service");
|
||||
services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("CorsPolicy",
|
||||
builder => builder.AllowAnyOrigin()
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader()
|
||||
//.AllowCredentials()
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
_log.LogDebug("BOOT: init MVC service");
|
||||
_log.LogDebug("BOOT: init Metrics service");
|
||||
|
||||
|
||||
// services.AddMvc(config =>
|
||||
// {
|
||||
// //was this but needed logging, not certain about the new way of adding so keeping this in case it all goes sideways in testing
|
||||
// //config.Filters.Add(typeof(AyaNova.Api.ControllerHelpers.ApiCustomExceptionFilter));
|
||||
// config.Filters.Add(new AyaNova.Api.ControllerHelpers.ApiCustomExceptionFilter(AyaNova.Util.ApplicationLogging.LoggerFactory));
|
||||
|
||||
// }).AddMetrics().AddJsonOptions(options =>
|
||||
// {
|
||||
// //2019-10-15 - removed this due to fuckery after update, is it required??? Not sure at this point
|
||||
// //if metrics have wrong dates then it's important I guess
|
||||
// //options.JsonSerializerOptions.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
|
||||
// });
|
||||
|
||||
|
||||
#region Swagger
|
||||
//https://docs.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?tabs=visual-studio-code
|
||||
@@ -190,112 +180,73 @@ namespace AyaNova
|
||||
//https://github.com/domaindrivendev/Swashbuckle.AspNetCore
|
||||
|
||||
_log.LogDebug("BOOT: init API explorer service");
|
||||
// services.AddSwaggerGen(c =>
|
||||
// {
|
||||
// c.SwaggerDoc("v8", new OpenApiInfo { Title = "My API", Version = "v8" });
|
||||
// c.OperationFilter<AuthResponsesOperationFilter>();
|
||||
services.AddSwaggerGen(
|
||||
c =>
|
||||
{
|
||||
// resolve the IApiVersionDescriptionProvider service
|
||||
// note: that we have to build a temporary service provider here because one has not been created yet
|
||||
var provider = services.BuildServiceProvider().GetRequiredService<IApiVersionDescriptionProvider>();
|
||||
|
||||
// });
|
||||
// services.AddSwaggerGen(
|
||||
// c =>
|
||||
// {
|
||||
// add a swagger document for each discovered API version
|
||||
// note: you might choose to skip or document deprecated API versions differently
|
||||
foreach (var description in provider.ApiVersionDescriptions)
|
||||
{
|
||||
c.SwaggerDoc(description.GroupName, CreateInfoForApiVersion(description));
|
||||
}
|
||||
|
||||
// add a custom operation filter which sets default values
|
||||
//Removed because will no longer compile the SwaggerDefaultValues but may be needed, not sure it's all a bit muddled
|
||||
// c.OperationFilter<SwaggerDefaultValues>();
|
||||
|
||||
// c.DocInclusionPredicate((docName, apiDesc) =>
|
||||
// {
|
||||
// if (!apiDesc.TryGetMethodInfo(out MethodInfo methodInfo)) return false;
|
||||
|
||||
// // Get the MapToApiVersion attributes of the action
|
||||
// var mapApiVersions = methodInfo
|
||||
// .GetCustomAttributes(true)
|
||||
// .OfType<MapToApiVersionAttribute>()
|
||||
// .SelectMany(attr => attr.Versions);
|
||||
|
||||
// //if it contains MapToApiVersion attributes, then we should check those as the ApiVersion ones are ignored
|
||||
// if (mapApiVersions.Any() && mapApiVersions.Any(v => $"v{v.ToString()}" == docName))
|
||||
// return true;
|
||||
|
||||
// // Get the ApiVersion attributes of the controller
|
||||
// var versions = methodInfo.DeclaringType
|
||||
// .GetCustomAttributes(true)
|
||||
// .OfType<ApiVersionAttribute>()
|
||||
// .SelectMany(attr => attr.Versions);
|
||||
|
||||
// return versions.Any(v => $"v{v.ToString()}" == docName);
|
||||
// });
|
||||
// integrate xml comments
|
||||
c.IncludeXmlComments(XmlCommentsFilePath);
|
||||
|
||||
|
||||
|
||||
// // resolve the IApiVersionDescriptionProvider service
|
||||
// // note: that we have to build a temporary service provider here because one has not been created yet
|
||||
// var provider = services.BuildServiceProvider().GetRequiredService<IApiVersionDescriptionProvider>();
|
||||
//2019-10-15 - Removed this because apikeyscheme is no longer recognized and it appears it *may* not be necessary... TWT
|
||||
//If I have any issues with bearer tokens in swagger then this is probably necessary but in a new way
|
||||
//this is required to allow authentication when testing secure routes via swagger UI
|
||||
// c.AddSecurityDefinition("Bearer", new ApiKeyScheme
|
||||
// {
|
||||
// Description = "JWT Authorization header using the Bearer scheme. Get your token by logging in via the Auth route then enter it here with the \"Bearer \" prefix. Example: \"Bearer {token}\"",
|
||||
// Name = "Authorization",
|
||||
// In = "header",
|
||||
// Type = "apiKey"
|
||||
|
||||
// // add a swagger document for each discovered API version
|
||||
// // note: you might choose to skip or document deprecated API versions differently
|
||||
// foreach (var description in provider.ApiVersionDescriptions)
|
||||
// {
|
||||
// c.SwaggerDoc(description.GroupName, CreateInfoForApiVersion(description));
|
||||
// }
|
||||
|
||||
// // add a custom operation filter which sets default values
|
||||
// // c.OperationFilter<SwaggerDefaultValues>();
|
||||
|
||||
// //test filter WTF?
|
||||
// //c.OperationFilter<AuthResponsesOperationFilter>();
|
||||
|
||||
// // integrate xml comments
|
||||
// c.IncludeXmlComments(XmlCommentsFilePath);
|
||||
|
||||
|
||||
|
||||
// // //2019-10-15 - Removed this because apikeyscheme is no longer recognized and it appears it *may* not be necessary... TWT
|
||||
// // //If I have any issues with bearer tokens in swagger then this is probably necessary but in a new way
|
||||
// // //this is required to allow authentication when testing secure routes via swagger UI
|
||||
// // c.AddSecurityDefinition("Bearer", new ApiKeyScheme
|
||||
// // {
|
||||
// // Description = "JWT Authorization header using the Bearer scheme. Get your token by logging in via the Auth route then enter it here with the \"Bearer \" prefix. Example: \"Bearer {token}\"",
|
||||
// // Name = "Authorization",
|
||||
// // In = "header",
|
||||
// // Type = "apiKey"
|
||||
|
||||
// // });
|
||||
// });
|
||||
|
||||
|
||||
|
||||
|
||||
// //Obsolete way
|
||||
// // c.AddSecurityRequirement(new System.Collections.Generic.Dictionary<string, System.Collections.Generic.IEnumerable<string>>
|
||||
// // {
|
||||
// // { "Bearer", new string[] { } }
|
||||
// // });
|
||||
//Obsolete way
|
||||
// c.AddSecurityRequirement(new System.Collections.Generic.Dictionary<string, System.Collections.Generic.IEnumerable<string>>
|
||||
// {
|
||||
// { "Bearer", new string[] { } }
|
||||
// });
|
||||
|
||||
// //https://stackoverflow.com/questions/56234504/migrating-to-swashbuckle-aspnetcore-version-5
|
||||
// //First we define the security scheme
|
||||
// c.AddSecurityDefinition("Bearer", //Name the security scheme
|
||||
// new OpenApiSecurityScheme
|
||||
// {
|
||||
// Description = "JWT Authorization header using the Bearer scheme.",
|
||||
// Type = SecuritySchemeType.Http, //We set the scheme type to http since we're using bearer authentication
|
||||
// Scheme = "bearer" //The name of the HTTP Authorization scheme to be used in the Authorization header. In this case "bearer".
|
||||
// });
|
||||
//https://stackoverflow.com/questions/56234504/migrating-to-swashbuckle-aspnetcore-version-5
|
||||
//First we define the security scheme
|
||||
c.AddSecurityDefinition("Bearer", //Name the security scheme
|
||||
new OpenApiSecurityScheme
|
||||
{
|
||||
Description = "JWT Authorization header using the Bearer scheme.",
|
||||
Type = SecuritySchemeType.Http, //We set the scheme type to http since we're using bearer authentication
|
||||
Scheme = "bearer" //The name of the HTTP Authorization scheme to be used in the Authorization header. In this case "bearer".
|
||||
});
|
||||
|
||||
// c.AddSecurityRequirement(new OpenApiSecurityRequirement{
|
||||
// {
|
||||
// new OpenApiSecurityScheme{
|
||||
// Reference = new OpenApiReference{
|
||||
// Id = "Bearer", //The name of the previously defined security scheme.
|
||||
// Type = ReferenceType.SecurityScheme
|
||||
// }
|
||||
// },new List<string>()
|
||||
// }
|
||||
// });
|
||||
c.AddSecurityRequirement(new OpenApiSecurityRequirement{
|
||||
{
|
||||
new OpenApiSecurityScheme{
|
||||
Reference = new OpenApiReference{
|
||||
Id = "Bearer", //The name of the previously defined security scheme.
|
||||
Type = ReferenceType.SecurityScheme
|
||||
}
|
||||
},new List<string>()
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// //https://github.com/domaindrivendev/Swashbuckle.AspNetCore
|
||||
// //ARGGHHHHHHHH!!!!!
|
||||
|
||||
|
||||
// });
|
||||
});
|
||||
|
||||
|
||||
#endregion
|
||||
@@ -367,20 +318,14 @@ namespace AyaNova
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
//
|
||||
public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IWebHostEnvironment env,
|
||||
AyContext dbContext, AyaNova.Api.ControllerHelpers.ApiServerState apiServerState, IServiceProvider serviceProvider)
|
||||
AyContext dbContext, IApiVersionDescriptionProvider provider, AyaNova.Api.ControllerHelpers.ApiServerState apiServerState, IServiceProvider serviceProvider)
|
||||
{
|
||||
//This was in constructor right after dbcontext: IApiVersionDescriptionProvider provider,
|
||||
_log.LogDebug("BOOT: configuring request pipeline...");
|
||||
|
||||
//dotnet3 test added
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
//This is in new templates generated for webapi but it errors out for me so removing it for now
|
||||
// app.UseHttpsRedirection();
|
||||
|
||||
//Store a reference to the dependency injection service for static classes
|
||||
ServiceProviderProvider.Provider = app.ApplicationServices;
|
||||
|
||||
@@ -394,15 +339,26 @@ namespace AyaNova
|
||||
_log.LogDebug("BOOT: pipeline - static files");
|
||||
app.UseDefaultFiles();
|
||||
app.UseStaticFiles();
|
||||
|
||||
//Might need the following if the page doesn't update in the client properly
|
||||
//however the vue build process will automatically uniquify each build file names so maybe not required
|
||||
// app.UseStaticFiles(new StaticFileOptions
|
||||
// {
|
||||
// OnPrepareResponse = context =>
|
||||
// {
|
||||
// if (context.File.Name == "index.html")
|
||||
// {
|
||||
// context.Context.Response.Headers.Add("Cache-Control", "no-cache, no-store");
|
||||
// context.Context.Response.Headers.Add("Expires", "-1");
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
#endregion
|
||||
|
||||
_log.LogDebug("BOOT: pipeline - ROUTING");
|
||||
app.UseRouting();//this wasn't here for 2.2 but added for 3.0, needs to come before the stuff after
|
||||
|
||||
//v3test
|
||||
// _log.LogDebug("BOOT: pipeline - CORS");
|
||||
// app.UseCors("CorsPolicy");
|
||||
_log.LogDebug("BOOT: pipeline - CORS");
|
||||
app.UseCors("CorsPolicy");
|
||||
|
||||
|
||||
#region AUTH / ROLES
|
||||
@@ -413,6 +369,7 @@ namespace AyaNova
|
||||
_log.LogDebug("BOOT: pipeline - authorization");
|
||||
app.UseAuthorization();
|
||||
|
||||
|
||||
//Custom middleware to get user roles and put them into the request so
|
||||
//they can be authorized in routes.
|
||||
app.Use(async (context, next) =>
|
||||
@@ -444,46 +401,33 @@ namespace AyaNova
|
||||
|
||||
#endregion
|
||||
|
||||
//According to https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-2.2&tabs=visual-studio#migrate-startupconfigure
|
||||
_log.LogDebug("BOOT: pipeline - ENDPOINTS");
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
|
||||
|
||||
#region SWAGGER
|
||||
|
||||
_log.LogDebug("BOOT: pipeline - api explorer");
|
||||
// // Enable middleware to serve generated Swagger as a JSON endpoint.
|
||||
// app.UseSwagger();
|
||||
|
||||
// app.UseSwaggerUI(c =>
|
||||
// {
|
||||
// // build a swagger endpoint for each discovered API version
|
||||
// foreach (var description in provider.ApiVersionDescriptions)
|
||||
// {
|
||||
// c.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
|
||||
// }
|
||||
|
||||
// //clean up the swagger explorer UI page and remove the branding
|
||||
// //via our own css
|
||||
// //NOTE: this broke when updated to v2.x of swagger and it can be fixed according to docs:
|
||||
// //https://github.com/domaindrivendev/Swashbuckle.AspNetCore#inject-custom-css
|
||||
// // c.InjectStylesheet("/api/sw.css");
|
||||
|
||||
// c.DefaultModelsExpandDepth(-1);
|
||||
// c.DocumentTitle = "AyaNova API explorer";
|
||||
// c.RoutePrefix = "api-docs";
|
||||
|
||||
// });
|
||||
|
||||
app.UseSwagger();
|
||||
// Enable middleware to serve generated Swagger as a JSON endpoint.
|
||||
app.UseSwagger();
|
||||
|
||||
app.UseSwaggerUI(c =>
|
||||
{
|
||||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
|
||||
c.DefaultModelsExpandDepth(-1);
|
||||
// build a swagger endpoint for each discovered API version
|
||||
foreach (var description in provider.ApiVersionDescriptions)
|
||||
{
|
||||
c.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
|
||||
}
|
||||
|
||||
//clean up the swagger explorer UI page and remove the branding
|
||||
//via our own css
|
||||
//NOTE: this broke when updated to v2.x of swagger and it can be fixed according to docs:
|
||||
//https://github.com/domaindrivendev/Swashbuckle.AspNetCore#inject-custom-css
|
||||
// c.InjectStylesheet("/api/sw.css");
|
||||
|
||||
c.DefaultModelsExpandDepth(-1);
|
||||
c.DocumentTitle = "AyaNova API explorer";
|
||||
c.RoutePrefix = "api-docs";
|
||||
});
|
||||
@@ -494,6 +438,15 @@ namespace AyaNova
|
||||
|
||||
|
||||
|
||||
//According to https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-2.2&tabs=visual-studio#migrate-startupconfigure
|
||||
//replace use mvc with use endpoints
|
||||
// //USE MVC
|
||||
// _log.LogDebug("BOOT: pipeline - MVC");
|
||||
// app.UseMvc();
|
||||
// _log.LogDebug("BOOT: pipeline - ENDPOINTS");
|
||||
// app.UseEndpoints(endpoints => {
|
||||
// endpoints.MapControllers();
|
||||
// });
|
||||
|
||||
// ******************************************************************
|
||||
// ******************** TESTING WIPE DB *****************************
|
||||
@@ -582,33 +535,33 @@ namespace AyaNova
|
||||
|
||||
#region Swagger and API Versioning utilities
|
||||
|
||||
// static string XmlCommentsFilePath
|
||||
// {
|
||||
// get
|
||||
// {
|
||||
// //Obsolete, used new method: https://developers.de/blogs/holger_vetter/archive/2017/06/30/swagger-includexmlcomments-platformservices-obsolete-replacement.aspx
|
||||
// //var basePath = PlatformServices.Default.Application.ApplicationBasePath;
|
||||
// var basePath = AppContext.BaseDirectory;
|
||||
// var fileName = typeof(Startup).GetTypeInfo().Assembly.GetName().Name + ".xml";
|
||||
// return Path.Combine(basePath, fileName);
|
||||
// }
|
||||
// }
|
||||
static string XmlCommentsFilePath
|
||||
{
|
||||
get
|
||||
{
|
||||
//Obsolete, used new method: https://developers.de/blogs/holger_vetter/archive/2017/06/30/swagger-includexmlcomments-platformservices-obsolete-replacement.aspx
|
||||
//var basePath = PlatformServices.Default.Application.ApplicationBasePath;
|
||||
var basePath = AppContext.BaseDirectory;
|
||||
var fileName = typeof(Startup).GetTypeInfo().Assembly.GetName().Name + ".xml";
|
||||
return Path.Combine(basePath, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
// static Microsoft.OpenApi.Models.OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description)
|
||||
// {
|
||||
// var info = new Microsoft.OpenApi.Models.OpenApiInfo()
|
||||
// {
|
||||
// Title = $"AyaNova API {description.ApiVersion}",
|
||||
// Version = description.ApiVersion.ToString()
|
||||
// };
|
||||
static Microsoft.OpenApi.Models.OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description)
|
||||
{
|
||||
var info = new Microsoft.OpenApi.Models.OpenApiInfo()
|
||||
{
|
||||
Title = $"AyaNova API {description.ApiVersion}",
|
||||
Version = description.ApiVersion.ToString()
|
||||
};
|
||||
|
||||
// if (description.IsDeprecated)
|
||||
// {
|
||||
// info.Description += " This API version has been deprecated.";
|
||||
// }
|
||||
if (description.IsDeprecated)
|
||||
{
|
||||
info.Description += " This API version has been deprecated.";
|
||||
}
|
||||
|
||||
// return info;
|
||||
// }
|
||||
return info;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user