diff --git a/server/Controllers/v1/CharactersController.cs b/server/Controllers/v1/CharactersController.cs
index 9f94a33..9e1c3e6 100644
--- a/server/Controllers/v1/CharactersController.cs
+++ b/server/Controllers/v1/CharactersController.cs
@@ -7,7 +7,7 @@ namespace server.Controllers.v1
{
[ApiController]
[ApiVersion("1.0")]
- [Route("/api/episodes")]
+ [Route("/api/characters")]
[Produces("application/json")]
public class CharactersController : ControllerBase
{
diff --git a/server/Models/Character.cs b/server/Models/Character.cs
index 46fada7..15e18ab 100644
--- a/server/Models/Character.cs
+++ b/server/Models/Character.cs
@@ -12,6 +12,12 @@ namespace server.Models
[BsonRepresentation(BsonType.ObjectId)]
public string? Id { get; set; }
+ ///
+ /// The character's full name.
+ ///
+ [BsonElement("fullName")]
+ public string FullName => $"{FirstName} {LastName}";
+
///
/// The character's first name.
///
@@ -24,6 +30,12 @@ namespace server.Models
[BsonElement("lastName")]
public string? LastName { get; set; }
+ ///
+ /// The full name of the actor who potrayed the character.
+ ///
+ [BsonElement("actorFullName")]
+ public string ActorFullName => $"{ActorFirstName} {ActorLastName}";
+
///
/// The first name of the actor who potrayed the character.
///
diff --git a/server/Models/CharacterFilter.cs b/server/Models/CharacterFilter.cs
index 75e83dd..3d84338 100644
--- a/server/Models/CharacterFilter.cs
+++ b/server/Models/CharacterFilter.cs
@@ -8,6 +8,19 @@ namespace server.Models
{
public class CharacterFilter
{
- // TODO: Build character filter model
+ ///
+ /// Used to filter characters by their name.
+ ///
+ public string? Name { get; set; } = null;
+
+ ///
+ /// Used to filter characters by the actor's name.
+ ///
+ public string? ActorName { get; set; } = null;
+
+ ///
+ /// Used to filter characters by a season.
+ ///
+ public int? Season { get; set; } = null;
}
}
diff --git a/server/Persistence/Repositories/CharacterRepository.cs b/server/Persistence/Repositories/CharacterRepository.cs
index ab14804..5838d55 100644
--- a/server/Persistence/Repositories/CharacterRepository.cs
+++ b/server/Persistence/Repositories/CharacterRepository.cs
@@ -1,19 +1,59 @@
using server.Models;
+using MongoDB.Driver;
+using MongoDB.Driver.Linq;
namespace server.Persistence.Repositories
{
public class CharacterRepository : ICharacterRepository
{
- // TODO: Implement getcharactersasync
- public Task> GetCharactersAsync(CharacterFilter filter)
+ private readonly IDbContext _context;
+
+ public CharacterRepository(IDbContext context)
{
- throw new NotImplementedException();
+ _context = context;
}
- // TODO: Implement getcharacterbyidasync
- public Task GetCharacterByIdAsync(string id)
+ public async Task> GetCharactersAsync(CharacterFilter filter)
{
- throw new NotImplementedException();
+ try
+ {
+ var query = _context.Characters.AsQueryable();
+
+ if (filter?.Name != null)
+ {
+ query = query.Where(character => character.FullName.ToLower().Contains(filter.Name.ToLower()));
+ }
+
+ if (filter?.ActorName != null)
+ {
+ query = query.Where(character => character.ActorFullName.ToLower().Contains(filter.ActorName.ToLower()));
+ }
+
+ if (filter?.Season != null)
+ {
+ query = query.Where(character => character.Seasons.Any(season => season == filter.Season));
+ }
+
+ return await query.ToListAsync();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ throw;
+ }
+ }
+
+ public async Task GetCharacterByIdAsync(string id)
+ {
+ try
+ {
+ return await _context.Characters.Find(character => character.Id == id).SingleOrDefaultAsync();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ throw;
+ }
}
}
}
diff --git a/server/Program.cs b/server/Program.cs
index 247734d..f4a4ea9 100644
--- a/server/Program.cs
+++ b/server/Program.cs
@@ -2,13 +2,13 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Versioning;
using Microsoft.Extensions.Options;
-using server.Options;
+using server.SwaggerOptions;
using server.Persistence;
using server.Persistence.Repositories;
using server.Persistence.Seed;
using System.Reflection;
using AspNetCoreRateLimit;
-using server.Options.Filters;
+using server.SwaggerOptions.Filters;
if (args.Length == 2 && args[0].ToLower() == "seed")
{
@@ -34,99 +34,102 @@ if (args.Length == 2 && args[0].ToLower() == "seed")
await seeder.SeedCharactersAsync();
}
}
-
-var builder = WebApplication.CreateBuilder(args);
-
-builder.Services.AddMemoryCache();
-
-builder.Services.Configure(
- builder.Configuration.GetSection("IpRateLimiting"));
-
-builder.Services.Configure(
- builder.Configuration.GetSection("IpRateLimitPolicies"));
-
-builder.Services.AddInMemoryRateLimiting();
-
-builder.Services.AddSingleton();
-
-builder.Services.Configure(
- builder.Configuration.GetSection("MongoDBSettings"));
-
-builder.Services.AddSingleton(sp =>
- sp.GetRequiredService>().Value);
-
-builder.Services.AddSingleton();
-
-builder.Services.AddScoped();
-
-builder.Services.AddScoped();
-
-builder.Services.AddScoped();
-
-builder.Services.AddScoped();
-
-builder.Services.AddControllers();
-
-builder.Services.AddEndpointsApiExplorer();
-
-builder.Services.AddSwaggerGen(options =>
+else
{
- var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
- var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
- options.IncludeXmlComments(xmlPath);
- options.OperationFilter();
-});
+ var builder = WebApplication.CreateBuilder(args);
-builder.Services.ConfigureOptions();
+ builder.Services.AddMemoryCache();
-builder.Services.AddApiVersioning(config =>
-{
- config.DefaultApiVersion = new ApiVersion(1, 0);
- config.AssumeDefaultVersionWhenUnspecified = true;
- config.ReportApiVersions = true;
- config.ApiVersionReader = new HeaderApiVersionReader("x-api-version");
-});
+ builder.Services.Configure(
+ builder.Configuration.GetSection("IpRateLimiting"));
-builder.Services.AddVersionedApiExplorer(config =>
-{
- config.GroupNameFormat = "'v'VVV";
-});
+ builder.Services.Configure(
+ builder.Configuration.GetSection("IpRateLimitPolicies"));
-var app = builder.Build();
+ builder.Services.AddInMemoryRateLimiting();
-app.UseStaticFiles();
+ builder.Services.AddSingleton();
-app.UseSwagger(options =>
-{
- options.RouteTemplate = "/{documentName}/docs.json";
-});
+ builder.Services.Configure(
+ builder.Configuration.GetSection("MongoDBSettings"));
-app.UseSwaggerUI(options =>
-{
- var provider = app.Services.GetRequiredService();
+ builder.Services.AddSingleton(sp =>
+ sp.GetRequiredService>().Value);
- foreach (var description in provider.ApiVersionDescriptions)
+ builder.Services.AddSingleton();
+
+ builder.Services.AddScoped();
+
+ builder.Services.AddScoped();
+
+ builder.Services.AddScoped();
+
+ builder.Services.AddScoped();
+
+ builder.Services.AddControllers();
+
+ builder.Services.AddEndpointsApiExplorer();
+
+ builder.Services.AddSwaggerGen(options =>
{
- var url = $"/{description.GroupName}/docs.json";
- var name = $"criminalmindsapi v{description.ApiVersion}";
+ var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
+ var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
- options.RoutePrefix = String.Empty;
- options.SwaggerEndpoint(url, name);
- options.EnableTryItOutByDefault();
- options.DisplayRequestDuration();
- options.DocumentTitle = "criminalmindsapi";
- }
-});
+ options.IncludeXmlComments(xmlPath);
+ options.OperationFilter();
+ });
-app.UseHttpsRedirection();
+ builder.Services.ConfigureOptions();
-app.UseAuthorization();
+ builder.Services.AddApiVersioning(config =>
+ {
+ config.DefaultApiVersion = new ApiVersion(1, 0);
+ config.AssumeDefaultVersionWhenUnspecified = true;
+ config.ReportApiVersions = true;
+ config.ApiVersionReader = new HeaderApiVersionReader("x-api-version");
+ });
-app.MapControllers();
+ builder.Services.AddVersionedApiExplorer(config =>
+ {
+ config.GroupNameFormat = "'v'VVV";
+ });
-app.UseIpRateLimiting();
+ var app = builder.Build();
-app.Run();
+ app.UseStaticFiles();
+
+ app.UseSwagger(options =>
+ {
+ options.RouteTemplate = "/{documentName}/docs.json";
+ });
+
+ app.UseSwaggerUI(options =>
+ {
+ var provider = app.Services.GetRequiredService();
+
+ foreach (var description in provider.ApiVersionDescriptions)
+ {
+ var url = $"/{description.GroupName}/docs.json";
+ var name = $"criminalmindsapi v{description.ApiVersion}";
+
+ options.RoutePrefix = String.Empty;
+ options.SwaggerEndpoint(url, name);
+ options.EnableTryItOutByDefault();
+ options.DisplayRequestDuration();
+ options.DocumentTitle = "criminalmindsapi";
+ }
+ });
+
+ app.UseHttpsRedirection();
+
+ app.UseAuthorization();
+
+ app.MapControllers();
+
+ app.UseIpRateLimiting();
+
+ app.Run();
+}
diff --git a/server/Options/ConfigureSwaggerOptions.cs b/server/SwaggerOptions/ConfigureSwaggerOptions.cs
similarity index 97%
rename from server/Options/ConfigureSwaggerOptions.cs
rename to server/SwaggerOptions/ConfigureSwaggerOptions.cs
index 8d2a8aa..a919623 100644
--- a/server/Options/ConfigureSwaggerOptions.cs
+++ b/server/SwaggerOptions/ConfigureSwaggerOptions.cs
@@ -3,7 +3,7 @@ using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
-namespace server.Options
+namespace server.SwaggerOptions
{
public class ConfigureSwaggerOptions : IConfigureOptions
{
diff --git a/server/Options/Filters/ApiVersionOperationFilter.cs b/server/SwaggerOptions/Filters/ApiVersionOperationFilter.cs
similarity index 94%
rename from server/Options/Filters/ApiVersionOperationFilter.cs
rename to server/SwaggerOptions/Filters/ApiVersionOperationFilter.cs
index 3d5eaf5..4445471 100644
--- a/server/Options/Filters/ApiVersionOperationFilter.cs
+++ b/server/SwaggerOptions/Filters/ApiVersionOperationFilter.cs
@@ -2,7 +2,7 @@
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
-namespace server.Options.Filters
+namespace server.SwaggerOptions.Filters
{
public class ApiVersionOperationFilter : IOperationFilter
{