From 0ca71cfcf97a73ba2a3019a40787c691e6a930b4 Mon Sep 17 00:00:00 2001 From: Ruidy Nemausat Date: Tue, 11 Feb 2020 15:02:41 +0100 Subject: [PATCH] preparation to api testing with postman --- Controllers/ProjectsController.cs | 39 ++++++++++++++++++++-------- Models/Project.cs | 42 ++++++++++++++++++++++++------- Program.cs | 2 ++ README.md | 6 ++--- Startup.cs | 12 ++++++--- TicketManager.csproj | 8 ++---- appsettings.json | 1 + 7 files changed, 77 insertions(+), 33 deletions(-) diff --git a/Controllers/ProjectsController.cs b/Controllers/ProjectsController.cs index 0610fb8..0d4e0b8 100644 --- a/Controllers/ProjectsController.cs +++ b/Controllers/ProjectsController.cs @@ -119,13 +119,28 @@ namespace TicketManager.Controllers return project; } - [HttpPost("{id}/addMembers")] + [HttpPut("{id}/addMembers")] public async Task> AddMembersToProject(int id, List usersToAdd) { + if (usersToAdd == null) + { + return BadRequest(); + } Project project = await GetProjectByIdAsync(id); project.AddMembers(usersToAdd); - await _context.SaveChangesAsync(); + try + { + await _context.SaveChangesAsync(); + } + catch (DbUpdateException /* ex */) + { + //Log the error (uncomment ex variable name and write a log.) + ModelState.AddModelError("", "Unable to save changes. " + + "Try again, and if the problem persists, " + + "see your system administrator."); + } + return project; } @@ -147,23 +162,25 @@ namespace TicketManager.Controllers } private async Task>> GetAllProjectsAsync() { - return await _context.Projects - .Include(p => p.Assignments) - .Include(p => p.Tickets) - .Include(p => p.Manager) - .Include(p => p.Files) - .AsNoTracking() + return await makeProjectsQueryAsync() .ToListAsync(); } private async Task GetProjectByIdAsync(int id) { - return await _context.Projects + return await makeProjectsQueryAsync() + .FirstOrDefaultAsync(p => p.Id == id); + } + + private IQueryable makeProjectsQueryAsync() + { + return _context.Projects .Include(p => p.Assignments) + .ThenInclude(a => a.User) .Include(p => p.Tickets) .Include(p => p.Manager) .Include(p => p.Files) - .AsNoTracking() - .FirstOrDefaultAsync(p => p.Id == id); + .AsNoTracking(); } + } } diff --git a/Models/Project.cs b/Models/Project.cs index fd11ef6..9354748 100644 --- a/Models/Project.cs +++ b/Models/Project.cs @@ -1,38 +1,62 @@ using System; using System.Collections.Generic; using System.Linq; +using System.ComponentModel.DataAnnotations; namespace TicketManager.Models { public class Project : ITask { + public Project() + { + + } public int Id { get; set; } + + [Required] + [StringLength(50)] + [Display(Name = "Title")] public string Title { get; set; } + + [StringLength(200)] + [Display(Name = "Short Description")] public string Description { get; set; } - public DateTime CreatedAt { get; set; } = DateTime.Now; + + [DataType(DataType.Date)] + [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = false)] + public DateTime CreatedAt { get; private set; } = DateTime.Now; + + [DataType(DataType.Date)] + [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] public DateTime PlannedEnding { get; set; } + + [Display(Name = "Progress")] public float Progression { get { - return Tickets.Count() == 0 ? 0 : (float)this.Tickets. + return Tickets.Count() == 0 ? 0 : + (float)this.Tickets. Where(t => t.Status == Status.Done).Count() / this.Tickets.Count() * 100; } } + + [Display(Name = "Project Status")] public Status Status { get; set; } = Status.ToDo; + [Display(Name = "Project Manager")] public User Manager { get; set; } public Guid ManagerId { get; set; } private List _assignments; - public List Assignments - { - get - { return _assignments ?? new List(); } - set - { _assignments = value; } - } + public List Assignments { get; set; } = new List(); + // { + // get + // { return _assignments ?? new List(); } + // set + // { _assignments = value; } + // } private List _tickets; public List Tickets { diff --git a/Program.cs b/Program.cs index b3c5cf8..35c5cb4 100644 --- a/Program.cs +++ b/Program.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.Logging; namespace TicketManager { +#pragma warning disable CS1591 public class Program { public static void Main(string[] args) @@ -23,4 +24,5 @@ namespace TicketManager webBuilder.UseStartup(); }); } +#pragma warning restore CS1591 } diff --git a/README.md b/README.md index e4ebba9..0232ef5 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,9 @@ ## TO DO +- Write API tests using Postman: request + test, environment variables, mock server +- Annotate API request in controllers +- Annotate Properties in Models - Write backend tests -- Reinitialize db -- Write Project SetMembers Method and related API endpoint code -- Write Project GetMembers Method and related API endpoint code - Ensure Tickets Edits belong to Project Edits - Ensure Tickets Files belong to Project Files diff --git a/Startup.cs b/Startup.cs index 825d07d..37ce7c0 100644 --- a/Startup.cs +++ b/Startup.cs @@ -60,12 +60,12 @@ namespace TicketManager Url = new Uri("https://ruidywebsite.herokuapp.com/"), } }); - // Set the comments path for the Swagger JSON and UI. var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); }); + services.AddSwaggerGenNewtonsoftSupport(); // explicit opt-in - needs to be placed after AddSwaggerGen() } @@ -77,10 +77,14 @@ namespace TicketManager { app.UseDeveloperExceptionPage(); } + else + { + app.UseHsts(); + } - + app.UseHttpsRedirection(); app.UseDefaultFiles(); - app.UseStaticFiles(); + app.UseSwagger(); @@ -89,7 +93,7 @@ namespace TicketManager c.SwaggerEndpoint("/swagger/v1/swagger.json", "Ticket Manager API V1"); }); - app.UseHttpsRedirection(); + app.UseSpaStaticFiles(); app.UseRouting(); diff --git a/TicketManager.csproj b/TicketManager.csproj index b4ab051..79dbdef 100644 --- a/TicketManager.csproj +++ b/TicketManager.csproj @@ -28,14 +28,10 @@ - - + + - - - - \ No newline at end of file diff --git a/appsettings.json b/appsettings.json index 51642cd..390f10c 100644 --- a/appsettings.json +++ b/appsettings.json @@ -1,4 +1,5 @@ { + "https_port": 443, "Logging": { "LogLevel": { "Default": "Information",