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();