From 5e201182ba497543750c16882f8270b723fd9730 Mon Sep 17 00:00:00 2001 From: StevanFreeborn Date: Tue, 21 Jun 2022 17:17:32 -0500 Subject: [PATCH] added xml comments for existing api parts and pieces. --- server/Controllers/v1/EpisodesController.cs | 31 ++++++++++++++++----- server/Controllers/v1/SeasonsController.cs | 12 ++++---- server/Filters/ApiVersionOperationFilter.cs | 20 +++++++++++++ server/Models/Character.cs | 27 ++++++++++++++++++ server/Models/Episode.cs | 30 ++++++++++++++++++++ server/Models/Quote.cs | 18 ++++++++++++ server/Models/Season.cs | 15 ++++++++++ server/Options/ConfigureSwaggerOptions.cs | 8 +++++- server/Program.cs | 2 ++ 9 files changed, 149 insertions(+), 14 deletions(-) create mode 100644 server/Filters/ApiVersionOperationFilter.cs diff --git a/server/Controllers/v1/EpisodesController.cs b/server/Controllers/v1/EpisodesController.cs index 2140d50..1e0da3c 100644 --- a/server/Controllers/v1/EpisodesController.cs +++ b/server/Controllers/v1/EpisodesController.cs @@ -17,11 +17,19 @@ namespace server.Controllers.v1 _episodeRepository = episodeRepository; } + /// + /// Gets a collection of episodes. + /// + /// Filter parameters passed from query string. + /// Returns the collection of episodes requested. + /// Not a valid request. + /// Failed to get episodes. + /// A collection of episodes. [MapToApiVersion("1.0")] [HttpGet] - [ProducesResponseType(typeof(List), 200)] - [ProducesResponseType(typeof(ValidationProblemDetails), 400)] - [ProducesResponseType(typeof(ProblemDetails), 500)] + [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] public async Task>> GetEpisodesAsync([FromQuery] EpisodeFilter? filter) { try @@ -36,12 +44,21 @@ namespace server.Controllers.v1 } } + /// + /// Gets an episode by its number in the series. + /// + /// The number of the episode in the series. + /// Returns the episode requested. + /// Not a valid request. + /// Unable to find an episode with the provided number. + /// Failed to get episode. + /// The episode requested. [MapToApiVersion("1.0")] [HttpGet("{number:int}")] - [ProducesResponseType(typeof(Episode), 200)] - [ProducesResponseType(typeof(ValidationProblemDetails), 400)] - [ProducesResponseType(typeof(ProblemDetails), 404)] - [ProducesResponseType(typeof(ProblemDetails), 500)] + [ProducesResponseType(typeof(Episode), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] public async Task> GetEpisodeByNumberAsync(int number) { try diff --git a/server/Controllers/v1/SeasonsController.cs b/server/Controllers/v1/SeasonsController.cs index 1280ae4..1759726 100644 --- a/server/Controllers/v1/SeasonsController.cs +++ b/server/Controllers/v1/SeasonsController.cs @@ -19,8 +19,8 @@ namespace server.Controllers.v1 [MapToApiVersion("1.0")] [HttpGet] - [ProducesResponseType(typeof(List), 200)] - [ProducesResponseType(typeof(ProblemDetails), 500)] + [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] public async Task>> GetSeasonsAsync() { try @@ -37,10 +37,10 @@ namespace server.Controllers.v1 [MapToApiVersion("1.0")] [HttpGet("{number:int}")] - [ProducesResponseType(typeof(Season), 200)] - [ProducesResponseType(typeof(ValidationProblemDetails), 400)] - [ProducesResponseType(typeof(ProblemDetails), 404)] - [ProducesResponseType(typeof(ProblemDetails),500)] + [ProducesResponseType(typeof(Season), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] public async Task> GetSeasonByNumberAsync(int number) { try diff --git a/server/Filters/ApiVersionOperationFilter.cs b/server/Filters/ApiVersionOperationFilter.cs new file mode 100644 index 0000000..b49cd1c --- /dev/null +++ b/server/Filters/ApiVersionOperationFilter.cs @@ -0,0 +1,20 @@ +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace server.Filters +{ + public class ApiVersionOperationFilter : IOperationFilter + { + public void Apply(OpenApiOperation operation, OperationFilterContext context) + { + var headerParameter = operation.Parameters.Where(p => p.Name == "x-api-version").SingleOrDefault(); + + if (headerParameter != null) + { + headerParameter.Description = "Header value that identifies target version of api."; + headerParameter.Schema.Default = new OpenApiString(context.DocumentName.ToLower().Replace("v", "")); + } + } + } +} diff --git a/server/Models/Character.cs b/server/Models/Character.cs index 69c0868..46fada7 100644 --- a/server/Models/Character.cs +++ b/server/Models/Character.cs @@ -5,31 +5,58 @@ namespace server.Models { public class Character { + /// + /// Identifier for the character. + /// [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } + /// + /// The character's first name. + /// [BsonElement("firstName")] public string? FirstName { get; set; } + /// + /// The character's last name. + /// [BsonElement("lastName")] public string? LastName { get; set; } + /// + /// The first name of the actor who potrayed the character. + /// [BsonElement("actorFirstName")] public string? ActorFirstName { get; set; } + /// + /// The last name of the actor who potrayed the character. + /// [BsonElement("actorLastName")] public string? ActorLastName { get; set; } + /// + /// The seasons in which the character appeared. + /// [BsonElement("seasons")] public int[]? Seasons { get; set; } + /// + /// The first episode where the character appeared. + /// [BsonElement("firstEpisode")] public string? FirstEpisode { get; set; } + /// + /// The last episode where the character appeared. + /// [BsonElement("lastEpisode")] public string? LastEpisode { get; set; } + /// + /// A link to an image of the character. + /// [BsonElement("image")] public string? Image { get; set; } } diff --git a/server/Models/Episode.cs b/server/Models/Episode.cs index 5187d19..dbe31b8 100644 --- a/server/Models/Episode.cs +++ b/server/Models/Episode.cs @@ -5,35 +5,65 @@ namespace server.Models { public class Episode { + /// + /// Identifier for the episode. + /// [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } + /// + /// Season number for the episode. + /// [BsonElement("season")] public int? Season { get; set; } + /// + /// The episde number relative to the entire series. + /// [BsonElement("numberInSeries")] public int? NumberInSeries { get; set; } + /// + /// The episode number relative to its season. + /// [BsonElement("numberInSeason")] public int? NumberInSeason { get; set; } + /// + /// The title of the episode. + /// [BsonElement("title")] public string? Title { get; set; } + /// + /// A brief summary of the episode. + /// [BsonElement("summary")] public string? Summary { get; set; } + /// + /// The director of the episode. + /// [BsonElement("directedBy")] public string? DirectedBy { get; set; } + /// + /// The writer of the episode. + /// [BsonElement("writtenBy")] public string[]? WrittenBy { get; set; } + /// + /// Date the episode aired. + /// [BsonElement("airDate")] [BsonDateTimeOptions(DateOnly = true)] public DateTime? AirDate { get; set; } + /// + /// Number of us viewers in millions for the episode. + /// [BsonElement("usViewersInMillions")] public double? UsViewersInMillions { get; set; } diff --git a/server/Models/Quote.cs b/server/Models/Quote.cs index 8e39049..a8ed1be 100644 --- a/server/Models/Quote.cs +++ b/server/Models/Quote.cs @@ -5,22 +5,40 @@ namespace server.Models { public class Quote { + /// + /// Identifier for the quote. + /// [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } + /// + /// The season number during which the quote was said. + /// [BsonElement("season")] public int? Season { get; set; } + /// + /// The episode number during which the quote was said. + /// [BsonElement("episode")] public int Episode { get; set; } + /// + /// The quote text. + /// [BsonElement("text")] public string? Text { get; set; } + /// + /// The source of the quote. + /// [BsonElement("source")] public string? Source { get; set; } + /// + /// The narrator of the quote. + /// [BsonElement("narrator")] public string? Narrator { get; set; } } diff --git a/server/Models/Season.cs b/server/Models/Season.cs index 66f6e56..52d50c3 100644 --- a/server/Models/Season.cs +++ b/server/Models/Season.cs @@ -5,20 +5,35 @@ namespace server.Models { public class Season { + /// + /// Identifier for the season. + /// [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } + /// + /// The season number. + /// [BsonElement("seasonNumber")] public int? SeasonNumber { get; set; } + /// + /// The number of episodes in the season. + /// [BsonElement("numberOfEpisodes")] public int? NumberOfEpisodes { get; set; } + /// + /// The date the season first aired. + /// [BsonElement("dateFirstAired")] [BsonDateTimeOptions(DateOnly = true)] public DateTime? DateFirstAired { get; set; } + /// + /// The date the season last aired. + /// [BsonElement("dateLastAired")] [BsonDateTimeOptions(DateOnly = true)] public DateTime? DateLastAired { get; set; } diff --git a/server/Options/ConfigureSwaggerOptions.cs b/server/Options/ConfigureSwaggerOptions.cs index f4af72f..9892c54 100644 --- a/server/Options/ConfigureSwaggerOptions.cs +++ b/server/Options/ConfigureSwaggerOptions.cs @@ -30,7 +30,13 @@ namespace server.Options { Title = "criminalmindsapi", Version = description.ApiVersion.ToString(), - Description = "An api that provides information about the Criminal Minds series." + Description = "An api that provides information about the Criminal Minds series.", + Contact = new OpenApiContact + { + Name = "Stevan Freeborn", + Email = "stevan.freeborn@gmail.com", + Url = new Uri("https://stevanfreeborn.com") + } }; return info; diff --git a/server/Program.cs b/server/Program.cs index eb82ced..cbd113f 100644 --- a/server/Program.cs +++ b/server/Program.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.AspNetCore.Mvc.Versioning; using Microsoft.Extensions.Options; using Microsoft.OpenApi.Models; +using server.Filters; using server.Options; using server.Persistence; using server.Persistence.Repositories; @@ -48,6 +49,7 @@ builder.Services.AddSwaggerGen(options => var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); options.IncludeXmlComments(xmlPath); + options.OperationFilter(); }); builder.Services.ConfigureOptions();