Skip to content

Dian Jing's Pull request for parkinglot API #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions ParkingLotApi/Controllers/ParkingLotsController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using ParkingLotApi.DTOs;
using ParkingLotApi.Exceptions;
using ParkingLotApi.Models;
using ParkingLotApi.Services;

namespace ParkingLotApi.Controllers
{
[ApiController]
[Route("[controller]")]
public class ParkingLotsController : ControllerBase
{
private readonly ParkingLotService _parkingLotSaervice;
private readonly int pageSize = 15;
public ParkingLotsController(ParkingLotService parkingLotService)
{
this._parkingLotSaervice = parkingLotService;
}

[HttpPost]
public async Task<ActionResult<ParkingLotDTO>> CreateParkingLotAsync([FromBody] ParkingLotDTO parkingLotDto)
{

return StatusCode(StatusCodes.Status201Created, await _parkingLotSaervice.AddAsync(parkingLotDto));

}

[HttpDelete("{id}")]
public async Task<ActionResult> DeleteParkingLotAsync(string id)
{
bool isSuccess = _parkingLotSaervice.DeleteAsync(id).Result;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

此处采用了阻塞的方法,不好,这样30行的方法不需要声明为 async

if (isSuccess)
{
return NoContent();
}
return NotFound();
}

[HttpGet]
public async Task<ActionResult<List<ParkingLot>>> GetParkingLotByPage([FromQuery] int? pageIndex)
{

return StatusCode(StatusCodes.Status200OK,
await _parkingLotSaervice.GetParkingLotByPageSizeAsync(pageIndex, pageSize));


}

[HttpGet("{id}")]
public async Task<ActionResult<ParkingLot>> GetParkingLotByPage(string id)
{
var result = await _parkingLotSaervice.GetParkingLotById(id);
if (result == null)
{
return NotFound();
}

return StatusCode(StatusCodes.Status200OK, result);
; }

[HttpPatch("{id}")]
public async Task<ActionResult<ParkingLot>> UpdateParkingLotAsync(string id, [FromBody] ParkingLotWithCapacityDTO parkingLotWithCapacity)
{
var result =await _parkingLotSaervice.UpdateParkingLotById(id, parkingLotWithCapacity.Capacity);
if (result == null)
{
return NotFound();
}

return StatusCode(StatusCodes.Status200OK, result);
}
}
}
21 changes: 21 additions & 0 deletions ParkingLotApi/DTOs/ParkingLotDTO.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using ParkingLotApi.Models;

namespace ParkingLotApi.DTOs
{
public class ParkingLotDTO
{
public string Name { get; set; }
public int Capacity { get; set; }
public string Location { get; set; }

internal ParkingLot ToEntity()
{
return new ParkingLot()
{
Name = Name,
Capacity = Capacity,
Location = Location
};
}
}
}
7 changes: 7 additions & 0 deletions ParkingLotApi/DTOs/ParkingLotWithCapacityDTO.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace ParkingLotApi.DTOs
{
public class ParkingLotWithCapacityDTO
{
public int Capacity { get; set; }
}
}
6 changes: 6 additions & 0 deletions ParkingLotApi/Exceptions/InvalidCapacityException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace ParkingLotApi.Exceptions
{
public class InvalidCapacityException : Exception
{
}
}
6 changes: 6 additions & 0 deletions ParkingLotApi/Exceptions/InvalidPageIndexException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace ParkingLotApi.Exceptions
{
public class InvalidPageIndexException: Exception
{
}
}
29 changes: 29 additions & 0 deletions ParkingLotApi/Filters/InvalidCapacityExceptionFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using ParkingLotApi.Exceptions;

namespace ParkingLotApi.Filters
{
public class InvalidCapacityExceptionFilter : IActionFilter, IOrderedFilter
{
int IOrderedFilter.Order => int.MaxValue - 10;
void IActionFilter.OnActionExecuted(ActionExecutedContext context)
{
if (context.Exception is InvalidCapacityException invalidCapacityException)
{
context.Result = new BadRequestResult();
context.ExceptionHandled = true;
}
else if (context.Exception is InvalidPageIndexException invalidPageException)
{
context.Result = new BadRequestResult();
context.ExceptionHandled = true;
}
}

void IActionFilter.OnActionExecuting(ActionExecutingContext context)
{

}
}
}
17 changes: 17 additions & 0 deletions ParkingLotApi/Models/ParkingLot.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

namespace ParkingLotApi.Models
{
public class ParkingLot
{

[BsonId] [BsonRepresentation(BsonType.ObjectId)]
public string? Id { get; set; }
public string Name { get; set; }
public int Capacity { get; set; }
public string Location { get; set; }


}
}
9 changes: 9 additions & 0 deletions ParkingLotApi/Models/ParkinglotDatabaseSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace ParkingLotApi.Models
{
public class ParkinglotDatabaseSettings
{
public string ConnectionString { get; set; } = null;
public string DatabaseName { get; set; } = null;
public string CollectionName { get; set; } = null;
}
}
18 changes: 16 additions & 2 deletions ParkingLotApi/Program.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
using ParkingLotApi.Exceptions;
using ParkingLotApi.Filters;
using ParkingLotApi.Models;
using ParkingLotApi.Repositories;
using ParkingLotApi.Services;
using System.Net.NetworkInformation;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
builder.Services.AddControllers(options => { options.Filters.Add<InvalidCapacityExceptionFilter>();});
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddScoped<ParkingLotService>();
builder.Services.AddSingleton<IParkingLotRepository, ParkingLotRepository>();
builder.Services.Configure<ParkinglotDatabaseSettings>(builder.Configuration.GetSection("ParkingLotDatabase"));

var app = builder.Build();

Expand All @@ -22,4 +32,8 @@

app.MapControllers();

app.Run();
app.Run();

public partial class Program
{
}
14 changes: 14 additions & 0 deletions ParkingLotApi/Repositories/IParkingLotRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using ParkingLotApi.DTOs;
using ParkingLotApi.Models;

namespace ParkingLotApi.Repositories
{
public interface IParkingLotRepository
{
public Task<ParkingLot> CreateParkingLot(ParkingLot parkingLot);
public Task<bool> DeleteParkingLot(string id);
public Task<List<ParkingLot>> GetParkingLot();
public Task<ParkingLot> GetParkingLotById(string id);
public Task<ParkingLot> UpdateParkingLotById(string id, int capacity);
}
}
52 changes: 52 additions & 0 deletions ParkingLotApi/Repositories/ParkingLotRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using MongoDB.Driver;
using ParkingLotApi.Models;
using System.Security.Cryptography;

namespace ParkingLotApi.Repositories
{
public class ParkingLotRepository:IParkingLotRepository
{
private readonly IMongoCollection<ParkingLot> _parkingLotCollection;

public ParkingLotRepository(IOptions<ParkinglotDatabaseSettings> parkingLotDatabaseSetting)
{
var mongoClient = new MongoClient(parkingLotDatabaseSetting.Value.ConnectionString);
var mongoDatabase = mongoClient.GetDatabase(parkingLotDatabaseSetting.Value.DatabaseName);
_parkingLotCollection =
mongoDatabase.GetCollection<ParkingLot>(parkingLotDatabaseSetting.Value.CollectionName);
}

public async Task<ParkingLot> CreateParkingLot(ParkingLot parkinglot)
{
await _parkingLotCollection.InsertOneAsync(parkinglot);
return await _parkingLotCollection.Find(parking => parking.Id == parkinglot.Id).FirstAsync();
}

public async Task<bool> DeleteParkingLot(string id)
{
var result = _parkingLotCollection.DeleteOneAsync(parkinglot => parkinglot.Id == id).Result;
return result.DeletedCount > 0 ;

}

public async Task<List<ParkingLot>> GetParkingLot()
{
return await _parkingLotCollection.Find(_ => true).ToListAsync();
}

public async Task<ParkingLot> GetParkingLotById(string id)
{
return await _parkingLotCollection.Find(parkingLot => parkingLot.Id == id).FirstOrDefaultAsync();
}

public async Task<ParkingLot> UpdateParkingLotById(string id, int capacity)
{
var update = Builders<ParkingLot>.Update.Set("Capacity", capacity);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

也可以用builder

await _parkingLotCollection.UpdateOneAsync(parkingLot => parkingLot.Id == id,
update);
return await _parkingLotCollection.Find(parkingLot => parkingLot.Id == id).FirstOrDefaultAsync();
}
}
}
62 changes: 62 additions & 0 deletions ParkingLotApi/Services/ParkingLotService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using Microsoft.AspNetCore.Http.HttpResults;
using ParkingLotApi.DTOs;
using ParkingLotApi.Exceptions;
using ParkingLotApi.Models;
using ParkingLotApi.Repositories;

namespace ParkingLotApi.Services
{
public class ParkingLotService
{
private readonly IParkingLotRepository _parkingLotRepository;
public ParkingLotService(IParkingLotRepository parkingLotRepository)
{
this._parkingLotRepository = parkingLotRepository;
}
public async Task<ParkingLot> AddAsync(ParkingLotDTO parkingLotDto)
{
if (parkingLotDto.Capacity < 10)
{
throw new InvalidCapacityException();
}

return await _parkingLotRepository.CreateParkingLot(parkingLotDto.ToEntity());
}

public async Task<bool> DeleteAsync(string id)
{
return await _parkingLotRepository.DeleteParkingLot(id);
}

public async Task<List<ParkingLot>> GetParkingLotByPageSizeAsync(int? pageIndex, int pageSize)
{
if (pageIndex <= 0 || pageIndex == null)
{
throw new InvalidCapacityException();
}
List<ParkingLot> parkingLots = await _parkingLotRepository.GetParkingLot();
int pageCount = parkingLots.Count / pageSize;
pageCount = parkingLots.Count % pageSize == 0? pageCount: pageCount+=1;
if ( pageSize <= parkingLots.Count && pageIndex > pageCount )
{
throw new InvalidPageIndexException();
}

return parkingLots.Skip(((int)pageIndex - 1) * (int)pageSize).Take((int)pageSize).ToList();
}

public async Task<ParkingLot> GetParkingLotById(string id)
{
return await _parkingLotRepository.GetParkingLotById(id);
}

public async Task<ParkingLot> UpdateParkingLotById(string id, int capacity)
{
if (capacity < 10)
{
throw new InvalidCapacityException();
}
return await _parkingLotRepository.UpdateParkingLotById(id, capacity);
}
}
}
34 changes: 34 additions & 0 deletions ParkingLotApiTest/Controllers/ParkingLotsControllerTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System.Net;
using System.Net.Http.Json;
using Microsoft.AspNetCore.Mvc.Testing;
using ParkingLotApi;
using ParkingLotApi.DTOs;

namespace ParkingLotApiTest.Controllers
{
public class ParkingLotsControllerTest : TestBase
{
public ParkingLotsControllerTest(WebApplicationFactory<Program> webApplicationFactory) : base(webApplicationFactory)
{
}

[Fact]
public async Task Should_return_bad_request_correctly_when_post_given_capacity_less_10()
{
//given
HttpClient _httpClient = GetClient();
ParkingLotDTO parkinglotDtoWithCapacity1 = new ParkingLotDTO()
{
Name = "name",
Capacity = 1,
Location = "S",
};

//when
HttpResponseMessage response = await _httpClient.PostAsJsonAsync("/parkinglots", parkinglotDtoWithCapacity1);

//then
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}
}
}
Loading