From 995035ad2285f08da7be06bc03a9385f00911015 Mon Sep 17 00:00:00 2001 From: StevanFreeborn Date: Fri, 24 Jun 2022 00:16:23 -0500 Subject: [PATCH 01/11] added seeding for characters --- server/Persistence/Seed/Data/characters.json | 351 +++++++++++++++++++ server/Persistence/Seed/Seeder.cs | 27 +- server/Program.cs | 5 + 3 files changed, 379 insertions(+), 4 deletions(-) create mode 100644 server/Persistence/Seed/Data/characters.json diff --git a/server/Persistence/Seed/Data/characters.json b/server/Persistence/Seed/Data/characters.json new file mode 100644 index 0000000..c1c10b1 --- /dev/null +++ b/server/Persistence/Seed/Data/characters.json @@ -0,0 +1,351 @@ +[ + { + "FirstName": "Jason", + "LastName": "Gideon", + "ActorFirstName": "Mandy", + "ActorLastName": "Patinkin", + "Seasons": [ + 1, + 2, + 3, + 10, + 15 + ], + "FirstEpisode": "Extreme Aggressor", + "LastEpisode": "In Name and Blood", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/jason-gideon.png" + }, + { + "FirstName": "Derek", + "LastName": "Morgan", + "ActorFirstName": "Shemar", + "ActorLastName": "Moore", + "Seasons": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14 + ], + "FirstEpisode": "Extreme Aggressor", + "LastEpisode": "A Beautiful Disaster", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/derek-morgan.png" + }, + { + "FirstName": "Aaron", + "LastName": "Hotchner", + "ActorFirstName": "Thomas", + "ActorLastName": "Gibson", + "Seasons": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12 + ], + "FirstEpisode": "Extreme Aggressor", + "LastEpisode": "Sick Day", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/aaron-hotchner.png" + }, + { + "FirstName": "Spencer", + "LastName": "Reid", + "ActorFirstName": "Matthew", + "ActorLastName": "Gubler", + "Seasons": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15 + ], + "FirstEpisode": "Extreme Aggressor", + "LastEpisode": "And in the End", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/spencer-reid.png" + }, + { + "FirstName": "Max", + "LastName": "Ryan", + "ActorFirstName": "Geoff", + "ActorLastName": "Pierson", + "Seasons": [ + 1 + ], + "FirstEpisode": "Unfinished Business", + "LastEpisode": "Unfinished Business", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/max-ryan.png" + }, + { + "FirstName": "Elle", + "LastName": "Greenaway", + "ActorFirstName": "Lola", + "ActorLastName": "Glaudini", + "Seasons": [ + 1, + 2 + ], + "FirstEpisode": "Extreme Aggressor", + "LastEpisode": "The Boogeyman", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/elle-greenaway.png" + }, + { + "FirstName": "Jennifer", + "LastName": "Jareau", + "ActorFirstName": "A.J.", + "ActorLastName": "Cook", + "Seasons": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15 + ], + "FirstEpisode": "Complusion", + "LastEpisode": "And in the End", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/jennifer-jareau.png" + }, + { + "FirstName": "Emily", + "LastName": "Prentiss", + "ActorFirstName": "Paget", + "ActorLastName": "Brewster", + "Seasons": [ + 2, + 3, + 4, + 5, + 6, + 7, + 9, + 11, + 12, + 13, + 14, + 15 + ], + "FirstEpisode": "The Last Word", + "LastEpisode": "And in the End", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/emily-prentiss.png" + }, + { + "FirstName": "David", + "LastName": "Rossi", + "ActorFirstName": "Joe", + "ActorLastName": "Mantegna", + "Seasons": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15 + ], + "FirstEpisode": "About Face", + "LastEpisode": "And in the End", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/david-rossi.png" + }, + { + "FirstName": "Penelope", + "LastName": "Garcia", + "ActorFirstName": "Kirsten", + "ActorLastName": "Vangsness", + "Seasons": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15 + ], + "FirstEpisode": "Extreme Aggressor", + "LastEpisode": "And in the End", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/penelope-garcia.png" + }, + { + "FirstName": "Ian", + "LastName": "Doyle", + "ActorFirstName": "Timothy", + "ActorLastName": "Murphy", + "Seasons": [ + 6, + 7 + ], + "FirstEpisode": "The Thirteenth Step", + "LastEpisode": "It Takes a Village", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/ian-doyle.png" + }, + { + "FirstName": "Ashley", + "LastName": "Seaver", + "ActorFirstName": "Rachel", + "ActorLastName": "Nichols", + "Seasons": [ + 6 + ], + "FirstEpisode": "What Happens at Home", + "LastEpisode": "Supply & Demand", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/ashley-seaver.png" + }, + { + "FirstName": "Alex", + "LastName": "Blake", + "ActorFirstName": "Jeanne", + "ActorLastName": "Tripplehorn", + "Seasons": [ + 8, + 9 + ], + "FirstEpisode": "The Silencer", + "LastEpisode": "Demons", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/alex-blake.png" + }, + { + "FirstName": "Kate", + "LastName": "Callahan", + "ActorFirstName": "Jennifer", + "ActorLastName": "Hewitt", + "Seasons": [ + 10 + ], + "FirstEpisode": "X", + "LastEpisode": "The Hunt", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/kate-callahan.png" + }, + { + "FirstName": "Jack", + "LastName": "Garrett", + "ActorFirstName": "Gary", + "ActorLastName": "Sinise", + "Seasons": [ + 10 + ], + "FirstEpisode": "Beyond Borders", + "LastEpisode": "Beyond Borders", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/jack-garrett.png" + }, + { + "FirstName": "Tara", + "LastName": "Lewis", + "ActorFirstName": "Aisha", + "ActorLastName": "Tyler", + "Seasons": [ + 11, + 12, + 13, + 14, + 15 + ], + "FirstEpisode": "The Job", + "LastEpisode": "And in the End", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/tara-lewis.png" + }, + { + "FirstName": "Luke", + "LastName": "Alvez", + "ActorFirstName": "Adam", + "ActorLastName": "Rodriguez", + "Seasons": [ + 12, + 13, + 14, + 15 + ], + "FirstEpisode": "The Crimson King", + "LastEpisode": "And in the End", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/luke-alvez.png" + }, + { + "FirstName": "Stephen", + "LastName": "Walker", + "ActorFirstName": "Damon", + "ActorLastName": "Gupton", + "Seasons": [ + 12, + 13 + ], + "FirstEpisode": "Scarecrow", + "LastEpisode": "Wheels Up", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/stephen-walker.png" + }, + { + "FirstName": "Matthew", + "LastName": "Simmons", + "ActorFirstName": "Daniel", + "ActorLastName": "Henney", + "Seasons": [ + 13, + 14, + 15 + ], + "FirstEpisode": "Beyond Borders", + "LastEpisode": "And in the End", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/matthew-simmons.png" + }, + { + "FirstName": "Krystall", + "LastName": "Richards", + "ActorFirstName": "Gail", + "ActorLastName": "O'Grady", + "Seasons": [ + 8, + 13, + 14, + 15 + ], + "FirstEpisode": "The Dance of Love", + "LastEpisode": "And in the End", + "Image": "https://criminalmindsapi.stevanfreeborn.com/characters/krystall-richards.png" + } +] \ No newline at end of file diff --git a/server/Persistence/Seed/Seeder.cs b/server/Persistence/Seed/Seeder.cs index 521bb7a..d48a210 100644 --- a/server/Persistence/Seed/Seeder.cs +++ b/server/Persistence/Seed/Seeder.cs @@ -9,6 +9,7 @@ namespace server.Persistence.Seed private readonly IMongoCollection _seasons; private readonly IMongoCollection _episodes; private readonly IMongoCollection _quotes; + private readonly IMongoCollection _characters; public Seeder() { @@ -23,6 +24,7 @@ namespace server.Persistence.Seed _seasons = database.GetCollection(config.GetSection("MongoDBSettings:SeasonsCollection").Value); _episodes = database.GetCollection(config.GetSection("MongoDBSettings:EpisodesCollection").Value); _quotes = database.GetCollection(config.GetSection("MongoDBSettings:QuotesCollection").Value); + _characters = database.GetCollection(config.GetSection("MongoDBSettings:CharactersCollection").Value); } public async Task SeedSeasonsAsync() @@ -37,7 +39,7 @@ namespace server.Persistence.Seed if(seasons != null) { await _seasons.InsertManyAsync(seasons); - Console.WriteLine($"Seeded databases with seasons from {fileName}"); + Console.WriteLine($"Seeded databases with {nameof(seasons)} from {fileName}"); } } @@ -53,13 +55,13 @@ namespace server.Persistence.Seed if (episodes != null) { await _episodes.InsertManyAsync(episodes); - Console.WriteLine($"Seeded databases with episodes from {fileName}"); + Console.WriteLine($"Seeded databases with {nameof(episodes)} from {fileName}"); } } public async Task SeedQuotesAsync() { - await _quotes.DeleteManyAsync(quotes => true); + await _quotes.DeleteManyAsync(quote => true); const string fileName = "quotes.json"; var quotesFilePath = Path.Combine(AppContext.BaseDirectory, $"Persistence/Seed/Data/{fileName}"); @@ -69,7 +71,24 @@ namespace server.Persistence.Seed if (quotes != null) { await _quotes.InsertManyAsync(quotes); - Console.WriteLine($"Seeded databases with quotes from {fileName}"); + Console.WriteLine($"Seeded databases with {nameof(quotes)} from {fileName}"); + } + + } + + public async Task SeedCharactersAsync() + { + await _characters.DeleteManyAsync(character => true); + + const string fileName = "characters.json"; + var charactersFilePath = Path.Combine(AppContext.BaseDirectory, $"Persistence/Seed/Data/{fileName}"); + var charactersJson = await File.ReadAllTextAsync(charactersFilePath); + var characters = JsonSerializer.Deserialize>(charactersJson); + + if (characters != null) + { + await _characters.InsertManyAsync(characters); + Console.WriteLine($"Seeded databases with {nameof(characters)} from {fileName}"); } } diff --git a/server/Program.cs b/server/Program.cs index baa6bb0..72fae26 100644 --- a/server/Program.cs +++ b/server/Program.cs @@ -28,6 +28,11 @@ if (args.Length == 2 && args[0].ToLower() == "seed") { await seeder.SeedQuotesAsync(); } + + if (args[1].ToLower() == "characters") + { + await seeder.SeedCharactersAsync(); + } } var builder = WebApplication.CreateBuilder(args); From 21d9fdab16ff269260c61fb7155f307f8566af1a Mon Sep 17 00:00:00 2001 From: StevanFreeborn Date: Fri, 24 Jun 2022 09:58:35 -0500 Subject: [PATCH 02/11] add characters controller and repository --- server/Controllers/v1/CharactersController.cs | 12 ++ server/Controllers/v1/QuotesController.cs | 10 +- .../Repositories/CharacterRepository.cs | 6 + .../Repositories/ICharacterRepository.cs | 13 ++ server/Program.cs | 2 + .../profile.arm.json | 113 ++++++++++++++++++ 6 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 server/Controllers/v1/CharactersController.cs create mode 100644 server/Persistence/Repositories/CharacterRepository.cs create mode 100644 server/Persistence/Repositories/ICharacterRepository.cs create mode 100644 server/Properties/ServiceDependencies/criminalmindsapi - Web Deploy/profile.arm.json diff --git a/server/Controllers/v1/CharactersController.cs b/server/Controllers/v1/CharactersController.cs new file mode 100644 index 0000000..2a31a84 --- /dev/null +++ b/server/Controllers/v1/CharactersController.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; + +namespace server.Controllers.v1 +{ + [ApiController] + [ApiVersion("1.0")] + [Route("/api/episodes")] + [Produces("application/json")] + public class CharactersController : ControllerBase + { + } +} diff --git a/server/Controllers/v1/QuotesController.cs b/server/Controllers/v1/QuotesController.cs index 08de272..e8f838c 100644 --- a/server/Controllers/v1/QuotesController.cs +++ b/server/Controllers/v1/QuotesController.cs @@ -46,7 +46,15 @@ namespace server.Controllers.v1 } } - // TODO: Add xml comments + /// + /// Gets a quote by its id. + /// + /// The id of the quote being requested. + /// Returns the quote requested. + /// Not a valid request. + /// Quote with the given id not found. + /// Failed to get quote. + /// Returns a quote. [MapToApiVersion("1.0")] [HttpGet("{id}")] [ProducesResponseType(typeof(Quote), StatusCodes.Status200OK)] diff --git a/server/Persistence/Repositories/CharacterRepository.cs b/server/Persistence/Repositories/CharacterRepository.cs new file mode 100644 index 0000000..a06868f --- /dev/null +++ b/server/Persistence/Repositories/CharacterRepository.cs @@ -0,0 +1,6 @@ +namespace server.Persistence.Repositories +{ + public class CharacterRepository : ICharacterRepository + { + } +} diff --git a/server/Persistence/Repositories/ICharacterRepository.cs b/server/Persistence/Repositories/ICharacterRepository.cs new file mode 100644 index 0000000..2882fa5 --- /dev/null +++ b/server/Persistence/Repositories/ICharacterRepository.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace server.Persistence.Repositories +{ + public interface ICharacterRepository + { + + } +} diff --git a/server/Program.cs b/server/Program.cs index 72fae26..7095bca 100644 --- a/server/Program.cs +++ b/server/Program.cs @@ -63,6 +63,8 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); + builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); diff --git a/server/Properties/ServiceDependencies/criminalmindsapi - Web Deploy/profile.arm.json b/server/Properties/ServiceDependencies/criminalmindsapi - Web Deploy/profile.arm.json new file mode 100644 index 0000000..9d32f2f --- /dev/null +++ b/server/Properties/ServiceDependencies/criminalmindsapi - Web Deploy/profile.arm.json @@ -0,0 +1,113 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_dependencyType": "compute.appService.windows" + }, + "parameters": { + "resourceGroupName": { + "type": "string", + "defaultValue": "StevanFreeborn", + "metadata": { + "description": "Name of the resource group for the resource. It is recommended to put resources under same resource group for better tracking." + } + }, + "resourceGroupLocation": { + "type": "string", + "defaultValue": "centralus", + "metadata": { + "description": "Location of the resource group. Resource groups could have different location than resources, however by default we use API versions from latest hybrid profile which support all locations for resource types we support." + } + }, + "resourceName": { + "type": "string", + "defaultValue": "criminalmindsapi", + "metadata": { + "description": "Name of the main resource to be created by this template." + } + }, + "resourceLocation": { + "type": "string", + "defaultValue": "[parameters('resourceGroupLocation')]", + "metadata": { + "description": "Location of the resource. By default use resource group's location, unless the resource provider is not supported there." + } + } + }, + "variables": { + "appServicePlan_name": "[concat('Plan', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]", + "appServicePlan_ResourceId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('resourceGroupName'), '/providers/Microsoft.Web/serverFarms/', variables('appServicePlan_name'))]" + }, + "resources": [ + { + "type": "Microsoft.Resources/resourceGroups", + "name": "[parameters('resourceGroupName')]", + "location": "[parameters('resourceGroupLocation')]", + "apiVersion": "2019-10-01" + }, + { + "type": "Microsoft.Resources/deployments", + "name": "[concat(parameters('resourceGroupName'), 'Deployment', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]", + "resourceGroup": "[parameters('resourceGroupName')]", + "apiVersion": "2019-10-01", + "dependsOn": [ + "[parameters('resourceGroupName')]" + ], + "properties": { + "mode": "Incremental", + "template": { + "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [ + { + "location": "[parameters('resourceLocation')]", + "name": "[parameters('resourceName')]", + "type": "Microsoft.Web/sites", + "apiVersion": "2015-08-01", + "tags": { + "[concat('hidden-related:', variables('appServicePlan_ResourceId'))]": "empty" + }, + "dependsOn": [ + "[variables('appServicePlan_ResourceId')]" + ], + "kind": "app", + "properties": { + "name": "[parameters('resourceName')]", + "kind": "app", + "httpsOnly": true, + "reserved": false, + "serverFarmId": "[variables('appServicePlan_ResourceId')]", + "siteConfig": { + "metadata": [ + { + "name": "CURRENT_STACK", + "value": "dotnetcore" + } + ] + } + }, + "identity": { + "type": "SystemAssigned" + } + }, + { + "location": "[parameters('resourceLocation')]", + "name": "[variables('appServicePlan_name')]", + "type": "Microsoft.Web/serverFarms", + "apiVersion": "2015-08-01", + "sku": { + "name": "S1", + "tier": "Standard", + "family": "S", + "size": "S1" + }, + "properties": { + "name": "[variables('appServicePlan_name')]" + } + } + ] + } + } + } + ] +} \ No newline at end of file From 9bc24949b7da2f3be6b1f60909411d2e15edf21f Mon Sep 17 00:00:00 2001 From: StevanFreeborn Date: Fri, 24 Jun 2022 10:10:02 -0500 Subject: [PATCH 03/11] implement character controller methods --- server/Controllers/v1/CharactersController.cs | 75 +++++++++++++++++++ server/Models/CharacterFilter.cs | 13 ++++ .../Filters/ApiVersionOperationFilter.cs | 2 +- .../Repositories/CharacterRepository.cs | 15 +++- .../Repositories/ICharacterRepository.cs | 9 +-- server/Program.cs | 2 +- 6 files changed, 107 insertions(+), 9 deletions(-) create mode 100644 server/Models/CharacterFilter.cs rename server/{ => Options}/Filters/ApiVersionOperationFilter.cs (95%) diff --git a/server/Controllers/v1/CharactersController.cs b/server/Controllers/v1/CharactersController.cs index 2a31a84..9f94a33 100644 --- a/server/Controllers/v1/CharactersController.cs +++ b/server/Controllers/v1/CharactersController.cs @@ -1,4 +1,7 @@ using Microsoft.AspNetCore.Mvc; +using MongoDB.Bson; +using server.Models; +using server.Persistence.Repositories; namespace server.Controllers.v1 { @@ -8,5 +11,77 @@ namespace server.Controllers.v1 [Produces("application/json")] public class CharactersController : ControllerBase { + private readonly ICharacterRepository _characterRepository; + + public CharactersController(ICharacterRepository characterRepository) + { + _characterRepository = characterRepository; + } + + /// + /// Gets a collection of characters. + /// + /// Filter parameters passed from query string. + /// Returns the collection of characters requested. + /// Not a valid request. + /// Failed to get characters. + /// Returns a collection of characters. + [MapToApiVersion("1.0")] + [HttpGet] + [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + public async Task>> GetCharactersAsync([FromQuery] CharacterFilter? filter) + { + try + { + var character = await _characterRepository.GetCharactersAsync(filter); + return Ok(character); + } + catch (Exception e) + { + Console.WriteLine(e); + return Problem(detail: "Failed to get characters", statusCode: 500); + } + } + + /// + /// Gets a character by its id. + /// + /// The id of the character being requested. + /// Returns the character requested. + /// Not a valid request. + /// Character with the given id not found. + /// Failed to get character. + /// Returns a character. + [MapToApiVersion("1.0")] + [HttpGet("{id}")] + [ProducesResponseType(typeof(Character), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + public async Task> GetCharacterByIdAsync(string id) + { + + if (!ObjectId.TryParse(id, out _)) + { + ModelState.AddModelError(nameof(id), $"{id} is not a valid id"); + return ValidationProblem(); + } + + try + { + var quote = await _characterRepository.GetCharacterByIdAsync(id); + + return quote == null ? + Problem(detail: $"Could not find character {id}", statusCode: 404) : + Ok(quote); + } + catch (Exception e) + { + Console.WriteLine(e); + return Problem(detail: "Failed to get character", statusCode: 500); + } + } } } diff --git a/server/Models/CharacterFilter.cs b/server/Models/CharacterFilter.cs new file mode 100644 index 0000000..75e83dd --- /dev/null +++ b/server/Models/CharacterFilter.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace server.Models +{ + public class CharacterFilter + { + // TODO: Build character filter model + } +} diff --git a/server/Filters/ApiVersionOperationFilter.cs b/server/Options/Filters/ApiVersionOperationFilter.cs similarity index 95% rename from server/Filters/ApiVersionOperationFilter.cs rename to server/Options/Filters/ApiVersionOperationFilter.cs index b49cd1c..3d5eaf5 100644 --- a/server/Filters/ApiVersionOperationFilter.cs +++ b/server/Options/Filters/ApiVersionOperationFilter.cs @@ -2,7 +2,7 @@ using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; -namespace server.Filters +namespace server.Options.Filters { public class ApiVersionOperationFilter : IOperationFilter { diff --git a/server/Persistence/Repositories/CharacterRepository.cs b/server/Persistence/Repositories/CharacterRepository.cs index a06868f..ab14804 100644 --- a/server/Persistence/Repositories/CharacterRepository.cs +++ b/server/Persistence/Repositories/CharacterRepository.cs @@ -1,6 +1,19 @@ -namespace server.Persistence.Repositories +using server.Models; + +namespace server.Persistence.Repositories { public class CharacterRepository : ICharacterRepository { + // TODO: Implement getcharactersasync + public Task> GetCharactersAsync(CharacterFilter filter) + { + throw new NotImplementedException(); + } + + // TODO: Implement getcharacterbyidasync + public Task GetCharacterByIdAsync(string id) + { + throw new NotImplementedException(); + } } } diff --git a/server/Persistence/Repositories/ICharacterRepository.cs b/server/Persistence/Repositories/ICharacterRepository.cs index 2882fa5..b9b74a5 100644 --- a/server/Persistence/Repositories/ICharacterRepository.cs +++ b/server/Persistence/Repositories/ICharacterRepository.cs @@ -1,13 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using server.Models; namespace server.Persistence.Repositories { public interface ICharacterRepository { - + Task> GetCharactersAsync(CharacterFilter filter); + Task GetCharacterByIdAsync(string id); } } diff --git a/server/Program.cs b/server/Program.cs index 7095bca..247734d 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.Filters; using server.Options; using server.Persistence; using server.Persistence.Repositories; using server.Persistence.Seed; using System.Reflection; using AspNetCoreRateLimit; +using server.Options.Filters; if (args.Length == 2 && args[0].ToLower() == "seed") { From 15eea06073973651ee3ca2455698042b7a3c2f34 Mon Sep 17 00:00:00 2001 From: StevanFreeborn Date: Fri, 24 Jun 2022 11:35:33 -0500 Subject: [PATCH 04/11] finished implementing characters endpoints --- server/Controllers/v1/CharactersController.cs | 2 +- server/Models/Character.cs | 12 ++ server/Models/CharacterFilter.cs | 15 +- .../Repositories/CharacterRepository.cs | 52 +++++- server/Program.cs | 161 +++++++++--------- .../ConfigureSwaggerOptions.cs | 2 +- .../Filters/ApiVersionOperationFilter.cs | 2 +- 7 files changed, 157 insertions(+), 89 deletions(-) rename server/{Options => SwaggerOptions}/ConfigureSwaggerOptions.cs (97%) rename server/{Options => SwaggerOptions}/Filters/ApiVersionOperationFilter.cs (94%) 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 { From 5185323d7be40be412d4faa5ad92024898d000c6 Mon Sep 17 00:00:00 2001 From: StevanFreeborn Date: Fri, 24 Jun 2022 12:22:40 -0500 Subject: [PATCH 05/11] cleanup. refactored program.cs to make use of static setup classes --- server/Models/CharacterFilter.cs | 8 +-- server/Program.cs | 102 ++----------------------------- server/Setup/Middleware.cs | 41 +++++++++++++ server/Setup/Services.cs | 80 ++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 104 deletions(-) create mode 100644 server/Setup/Middleware.cs create mode 100644 server/Setup/Services.cs diff --git a/server/Models/CharacterFilter.cs b/server/Models/CharacterFilter.cs index 3d84338..35b0ef0 100644 --- a/server/Models/CharacterFilter.cs +++ b/server/Models/CharacterFilter.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace server.Models +namespace server.Models { public class CharacterFilter { diff --git a/server/Program.cs b/server/Program.cs index f4a4ea9..8f4acd6 100644 --- a/server/Program.cs +++ b/server/Program.cs @@ -1,14 +1,5 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.ApiExplorer; -using Microsoft.AspNetCore.Mvc.Versioning; -using Microsoft.Extensions.Options; -using server.SwaggerOptions; -using server.Persistence; -using server.Persistence.Repositories; using server.Persistence.Seed; -using System.Reflection; -using AspNetCoreRateLimit; -using server.SwaggerOptions.Filters; +using server.Setup; if (args.Length == 2 && args[0].ToLower() == "seed") { @@ -36,98 +27,15 @@ if (args.Length == 2 && args[0].ToLower() == "seed") } else { - 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 => - { - var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; - var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); - - options.IncludeXmlComments(xmlPath); - options.OperationFilter(); - }); - - builder.Services.ConfigureOptions(); - - 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.AddVersionedApiExplorer(config => - { - config.GroupNameFormat = "'v'VVV"; - }); + Services.SetupDb(builder); + Services.SetupMvC(builder); + Services.SetupSwagger(builder); var app = builder.Build(); - 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(); + Middleware.Setup(app); app.Run(); } diff --git a/server/Setup/Middleware.cs b/server/Setup/Middleware.cs new file mode 100644 index 0000000..90cfe6f --- /dev/null +++ b/server/Setup/Middleware.cs @@ -0,0 +1,41 @@ +using AspNetCoreRateLimit; +using Microsoft.AspNetCore.Mvc.ApiExplorer; + +namespace server.Setup +{ + public static class Middleware + { + public static void Setup(WebApplication app) + { + 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(); + } + } +} diff --git a/server/Setup/Services.cs b/server/Setup/Services.cs new file mode 100644 index 0000000..cb5c1f0 --- /dev/null +++ b/server/Setup/Services.cs @@ -0,0 +1,80 @@ +using AspNetCoreRateLimit; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Versioning; +using Microsoft.Extensions.Options; +using server.Persistence; +using server.Persistence.Repositories; +using server.SwaggerOptions; +using server.SwaggerOptions.Filters; +using System.Reflection; + +namespace server.Setup +{ + public static class Services + { + public static void SetupDb(WebApplicationBuilder builder) + { + 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(); + } + + public static void SetupMvC(WebApplicationBuilder builder) + { + 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.AddControllers(); + + builder.Services.AddEndpointsApiExplorer(); + + 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.AddVersionedApiExplorer(config => + { + config.GroupNameFormat = "'v'VVV"; + }); + } + + public static void SetupSwagger(WebApplicationBuilder builder) + { + builder.Services.AddSwaggerGen(options => + { + var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; + var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); + + options.IncludeXmlComments(xmlPath); + options.OperationFilter(); + }); + + builder.Services.ConfigureOptions(); + } + } +} From 4035b6e91906e7df78574f306dd06aac57bcfc1f Mon Sep 17 00:00:00 2001 From: StevanFreeborn Date: Fri, 24 Jun 2022 14:03:43 -0500 Subject: [PATCH 06/11] refactored program.cs to have more of a fluent like syntax --- server/Program.cs | 17 +++++++---------- server/Setup/Middleware.cs | 4 +++- server/Setup/Services.cs | 12 +++++++++--- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/server/Program.cs b/server/Program.cs index 8f4acd6..a16fe7c 100644 --- a/server/Program.cs +++ b/server/Program.cs @@ -27,17 +27,14 @@ if (args.Length == 2 && args[0].ToLower() == "seed") } else { - var builder = WebApplication.CreateBuilder(args); + var app = WebApplication + .CreateBuilder(args) + .SetupDb() + .SetupMvC() + .SetupSwagger() + .Build(); - Services.SetupDb(builder); - Services.SetupMvC(builder); - Services.SetupSwagger(builder); - - var app = builder.Build(); - - Middleware.Setup(app); - - app.Run(); + app.SetupMiddleware().Run(); } diff --git a/server/Setup/Middleware.cs b/server/Setup/Middleware.cs index 90cfe6f..7799abf 100644 --- a/server/Setup/Middleware.cs +++ b/server/Setup/Middleware.cs @@ -5,7 +5,7 @@ namespace server.Setup { public static class Middleware { - public static void Setup(WebApplication app) + public static WebApplication SetupMiddleware(this WebApplication app) { app.UseSwagger(options => { @@ -36,6 +36,8 @@ namespace server.Setup app.MapControllers(); app.UseIpRateLimiting(); + + return app; } } } diff --git a/server/Setup/Services.cs b/server/Setup/Services.cs index cb5c1f0..1ba5bab 100644 --- a/server/Setup/Services.cs +++ b/server/Setup/Services.cs @@ -12,7 +12,7 @@ namespace server.Setup { public static class Services { - public static void SetupDb(WebApplicationBuilder builder) + public static WebApplicationBuilder SetupDb(this WebApplicationBuilder builder) { builder.Services.Configure( builder.Configuration.GetSection("MongoDBSettings")); @@ -29,9 +29,11 @@ namespace server.Setup builder.Services.AddScoped(); builder.Services.AddScoped(); + + return builder; } - public static void SetupMvC(WebApplicationBuilder builder) + public static WebApplicationBuilder SetupMvC(this WebApplicationBuilder builder) { builder.Services.AddMemoryCache(); @@ -61,9 +63,11 @@ namespace server.Setup { config.GroupNameFormat = "'v'VVV"; }); + + return builder; } - public static void SetupSwagger(WebApplicationBuilder builder) + public static WebApplicationBuilder SetupSwagger(this WebApplicationBuilder builder) { builder.Services.AddSwaggerGen(options => { @@ -75,6 +79,8 @@ namespace server.Setup }); builder.Services.ConfigureOptions(); + + return builder; } } } From 78c404a43b74e87aba09f2edad6605f0d528eda3 Mon Sep 17 00:00:00 2001 From: StevanFreeborn Date: Fri, 24 Jun 2022 14:05:03 -0500 Subject: [PATCH 07/11] removed unused web deploy profile --- .../profile.arm.json | 113 ------------------ 1 file changed, 113 deletions(-) delete mode 100644 server/Properties/ServiceDependencies/criminalminds-server - Web Deploy/profile.arm.json diff --git a/server/Properties/ServiceDependencies/criminalminds-server - Web Deploy/profile.arm.json b/server/Properties/ServiceDependencies/criminalminds-server - Web Deploy/profile.arm.json deleted file mode 100644 index 4b91ec2..0000000 --- a/server/Properties/ServiceDependencies/criminalminds-server - Web Deploy/profile.arm.json +++ /dev/null @@ -1,113 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_dependencyType": "compute.appService.windows" - }, - "parameters": { - "resourceGroupName": { - "type": "string", - "defaultValue": "StevanFreeborn", - "metadata": { - "description": "Name of the resource group for the resource. It is recommended to put resources under same resource group for better tracking." - } - }, - "resourceGroupLocation": { - "type": "string", - "defaultValue": "centralus", - "metadata": { - "description": "Location of the resource group. Resource groups could have different location than resources, however by default we use API versions from latest hybrid profile which support all locations for resource types we support." - } - }, - "resourceName": { - "type": "string", - "defaultValue": "criminalminds-server", - "metadata": { - "description": "Name of the main resource to be created by this template." - } - }, - "resourceLocation": { - "type": "string", - "defaultValue": "[parameters('resourceGroupLocation')]", - "metadata": { - "description": "Location of the resource. By default use resource group's location, unless the resource provider is not supported there." - } - } - }, - "variables": { - "appServicePlan_name": "[concat('Plan', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]", - "appServicePlan_ResourceId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('resourceGroupName'), '/providers/Microsoft.Web/serverFarms/', variables('appServicePlan_name'))]" - }, - "resources": [ - { - "type": "Microsoft.Resources/resourceGroups", - "name": "[parameters('resourceGroupName')]", - "location": "[parameters('resourceGroupLocation')]", - "apiVersion": "2019-10-01" - }, - { - "type": "Microsoft.Resources/deployments", - "name": "[concat(parameters('resourceGroupName'), 'Deployment', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]", - "resourceGroup": "[parameters('resourceGroupName')]", - "apiVersion": "2019-10-01", - "dependsOn": [ - "[parameters('resourceGroupName')]" - ], - "properties": { - "mode": "Incremental", - "template": { - "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [ - { - "location": "[parameters('resourceLocation')]", - "name": "[parameters('resourceName')]", - "type": "Microsoft.Web/sites", - "apiVersion": "2015-08-01", - "tags": { - "[concat('hidden-related:', variables('appServicePlan_ResourceId'))]": "empty" - }, - "dependsOn": [ - "[variables('appServicePlan_ResourceId')]" - ], - "kind": "app", - "properties": { - "name": "[parameters('resourceName')]", - "kind": "app", - "httpsOnly": true, - "reserved": false, - "serverFarmId": "[variables('appServicePlan_ResourceId')]", - "siteConfig": { - "metadata": [ - { - "name": "CURRENT_STACK", - "value": "dotnetcore" - } - ] - } - }, - "identity": { - "type": "SystemAssigned" - } - }, - { - "location": "[parameters('resourceLocation')]", - "name": "[variables('appServicePlan_name')]", - "type": "Microsoft.Web/serverFarms", - "apiVersion": "2015-08-01", - "sku": { - "name": "S1", - "tier": "Standard", - "family": "S", - "size": "S1" - }, - "properties": { - "name": "[variables('appServicePlan_name')]" - } - } - ] - } - } - } - ] -} \ No newline at end of file From c5903ad901ee71ed2eaf545048d852560aa66982 Mon Sep 17 00:00:00 2001 From: StevanFreeborn Date: Fri, 24 Jun 2022 14:25:28 -0500 Subject: [PATCH 08/11] tighten up program.cs and add optionality to seed data however --- server/Program.cs | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/server/Program.cs b/server/Program.cs index a16fe7c..22027c5 100644 --- a/server/Program.cs +++ b/server/Program.cs @@ -1,29 +1,17 @@ using server.Persistence.Seed; using server.Setup; -if (args.Length == 2 && args[0].ToLower() == "seed") +if (args.Length > 0 && args[0].ToLower() == "seed") { var seeder = new Seeder(); - if (args[1].ToLower() == "seasons") - { - await seeder.SeedSeasonsAsync(); - } + if (args.Contains("seasons")) await seeder.SeedSeasonsAsync(); - if (args[1].ToLower() == "episodes") - { - await seeder.SeedEpisodesAsync(); - } + if (args.Contains("episodes")) await seeder.SeedEpisodesAsync(); - if (args[1].ToLower() == "quotes") - { - await seeder.SeedQuotesAsync(); - } + if (args.Contains("quotes")) await seeder.SeedQuotesAsync(); - if (args[1].ToLower() == "characters") - { - await seeder.SeedCharactersAsync(); - } + if (args.Contains("characters")) await seeder.SeedCharactersAsync(); } else { From d6ff4829d8f041f726773f5be7d9c687669b122d Mon Sep 17 00:00:00 2001 From: StevanFreeborn Date: Fri, 24 Jun 2022 15:30:20 -0500 Subject: [PATCH 09/11] added vs code --- .vscode/launch.json | 35 +++++++++++++++++++++++++++++++++++ .vscode/tasks.json | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..4e6a45b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,35 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/server/bin/Debug/net6.0/server.dll", + "args": [], + "cwd": "${workspaceFolder}/server", + "stopAtEntry": false, + // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser + "serverReadyAction": { + "action": "openExternally", + "pattern": "\\bNow listening on:\\s+(https?://\\S+)" + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..5239770 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/server/server.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/server/server.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/server/server.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file From 6b4caf2c3ee5841fbd9ad99a72c18bfb1c248039 Mon Sep 17 00:00:00 2001 From: StevanFreeborn Date: Fri, 24 Jun 2022 15:35:10 -0500 Subject: [PATCH 10/11] setup deployment from vs code --- .vscode/settings.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..4db21f2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "appService.defaultWebAppToDeploy": "/subscriptions/d031910a-7ca1-44c2-9bb1-0bdb42cd9f43/microsoft.web/sites/subscriptions/d031910a-7ca1-44c2-9bb1-0bdb42cd9f43/resourceGroups/StevanFreeborn/providers/Microsoft.Web/sites/criminalmindsapi", + "appService.deploySubpath": "server" +} \ No newline at end of file From 775d98497dea83ae82e0df184bf97ae0a4d595e5 Mon Sep 17 00:00:00 2001 From: StevanFreeborn Date: Fri, 24 Jun 2022 15:54:21 -0500 Subject: [PATCH 11/11] updated client to use correct api url --- client/src/App.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/App.js b/client/src/App.js index 4ec4478..ccfadae 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -55,7 +55,7 @@ export default class App extends Component { let url = '/api/seasons'; if (process.env.NODE_ENV === 'production') { - url = 'https://criminalminds-server.azurewebsites.net' + url; + url = 'https://criminalmindsapi.azurewebsites.net' + url; } const response = await fetch(url);