169 lines
6.4 KiB
C#
169 lines
6.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Web.Mvc;
|
|
using Portoa.Persistence;
|
|
using Portoa.Web.Controllers;
|
|
using Portoa.Web.Results;
|
|
using Portoa.Web.Util;
|
|
using VideoGameQuotes.Api;
|
|
using VideoGameQuotes.Web.Models;
|
|
|
|
namespace VideoGameQuotes.Web.Controllers {
|
|
|
|
|
|
public interface IApiService {
|
|
IEnumerable<GameDto> GetGames(ApiModel model);
|
|
IEnumerable<SystemDto> GetSystems(ApiModel model);
|
|
IEnumerable<CategoryDto> GetCategories(ApiModel model);
|
|
IEnumerable<PublisherDto> GetPublishers(ApiModel model);
|
|
IEnumerable<QuoteDto> GetQuotes(ApiModel model);
|
|
}
|
|
|
|
public class ApiService : IApiService {
|
|
private readonly IRepository<Game> gameRepository;
|
|
private readonly IRepository<GamingSystem> systemRepository;
|
|
private readonly IRepository<Category> categoryRepository;
|
|
private readonly IRepository<Publisher> publisherRepository;
|
|
private readonly IRepository<Quote> quoteRepository;
|
|
|
|
private readonly IDictionary<string, CriterionHandler<Category>> categoryHandlers = new Dictionary<string, CriterionHandler<Category>>();
|
|
private readonly IDictionary<string, CriterionHandler<GamingSystem>> systemHandlers = new Dictionary<string, CriterionHandler<GamingSystem>>();
|
|
private readonly IDictionary<string, CriterionHandler<Publisher>> publisherHandlers = new Dictionary<string, CriterionHandler<Publisher>>();
|
|
private readonly IDictionary<string, CriterionHandler<Quote>> quoteHandlers = new Dictionary<string, CriterionHandler<Quote>> {
|
|
{ "game", new Quote.GameCriterionHandler() }
|
|
};
|
|
private readonly IDictionary<string, CriterionHandler<Game>> gameHandlers = new Dictionary<string, CriterionHandler<Game>> {
|
|
{ "system", new Game.SystemCriterionHandler() },
|
|
{ "publisher", new Game.PublisherCriterionHandler() }
|
|
};
|
|
|
|
public ApiService(
|
|
IRepository<Game> gameRepository,
|
|
IRepository<GamingSystem> systemRepository,
|
|
IRepository<Category> categoryRepository,
|
|
IRepository<Publisher> publisherRepository,
|
|
IRepository<Quote> quoteRepository
|
|
) {
|
|
this.gameRepository = gameRepository;
|
|
this.systemRepository = systemRepository;
|
|
this.categoryRepository = categoryRepository;
|
|
this.publisherRepository = publisherRepository;
|
|
this.quoteRepository = quoteRepository;
|
|
}
|
|
|
|
private static IEnumerable<T> SetSortMethod<T, TKey>(IEnumerable<T> records, SortMethod sortMethod, SortOrder sortOrder, Func<T, TKey> propertySelector) where T : Entity<int> {
|
|
switch (sortMethod) {
|
|
case SortMethod.Alphabetical:
|
|
return sortOrder == SortOrder.Descending ? records.OrderByDescending(propertySelector) : records.OrderBy(propertySelector);
|
|
case SortMethod.Date:
|
|
return sortOrder == SortOrder.Descending ? records.OrderByDescending(propertySelector) : records.OrderBy(propertySelector);
|
|
default:
|
|
return records;
|
|
}
|
|
}
|
|
|
|
private static IEnumerable<TDto> GetRecords<T, TDto>(
|
|
ApiModel model,
|
|
IRepository<T> repository,
|
|
Func<T, object> sortSelector,
|
|
IDictionary<string,
|
|
CriterionHandler<T>> criterionHandlers
|
|
)
|
|
where T : Entity<int>
|
|
where TDto : new() {
|
|
IEnumerable<T> records;
|
|
if (model.FetchAll) {
|
|
records = SetSortMethod(repository.Records, model.SortMethod, model.SortOrder, sortSelector);
|
|
var expressionBuilder = new List<Func<T, bool>>();
|
|
foreach (var kvp in model.Criteria) {
|
|
if (!criterionHandlers.ContainsKey(kvp.Key)) {
|
|
throw new ApiException(string.Format("Unknown criterion: \"{0}\"", kvp.Key));
|
|
}
|
|
|
|
expressionBuilder.AddRange(criterionHandlers[kvp.Key].HandleCriterion(kvp.Value));
|
|
}
|
|
|
|
if (expressionBuilder.Count > 0) {
|
|
records = records.Where(game => expressionBuilder.Aggregate(false, (current, next) => current || next(game)));
|
|
}
|
|
} else {
|
|
records = new[] { repository.FindById(model.Id) };
|
|
}
|
|
|
|
return records.ToArray().Select(entity => entity.ToDto<TDto>());
|
|
}
|
|
|
|
[UnitOfWork]
|
|
public IEnumerable<GameDto> GetGames(ApiModel model) {
|
|
return GetRecords<Game, GameDto>(model, gameRepository, game => game.Name, gameHandlers);
|
|
}
|
|
|
|
[UnitOfWork]
|
|
public IEnumerable<SystemDto> GetSystems(ApiModel model) {
|
|
return GetRecords<GamingSystem, SystemDto>(model, systemRepository, system => system.Name, systemHandlers);
|
|
}
|
|
|
|
[UnitOfWork]
|
|
public IEnumerable<CategoryDto> GetCategories(ApiModel model) {
|
|
return GetRecords<Category, CategoryDto>(model, categoryRepository, category => category.Name, categoryHandlers);
|
|
}
|
|
|
|
[UnitOfWork]
|
|
public IEnumerable<PublisherDto> GetPublishers(ApiModel model) {
|
|
return GetRecords<Publisher, PublisherDto>(model, publisherRepository, publisher => publisher.Name, publisherHandlers);
|
|
}
|
|
|
|
[UnitOfWork]
|
|
public IEnumerable<QuoteDto> GetQuotes(ApiModel model) {
|
|
return GetRecords<Quote, QuoteDto>(model, quoteRepository, quote => quote.Id, quoteHandlers);
|
|
}
|
|
}
|
|
|
|
public class ApiController : Controller {
|
|
private readonly IApiService apiService;
|
|
|
|
public ApiController(IApiService apiService) {
|
|
this.apiService = apiService;
|
|
}
|
|
|
|
private ActionResult Error(HttpStatusCode statusCode, string message = null) {
|
|
return new StatusOverrideResult(this.SerializeToJson(this.CreateJsonErrorResponse(message ?? "Invalid request"))) { StatusCode = statusCode };
|
|
}
|
|
|
|
private ActionResult GetRecords<TDto>(Func<IApiService, IEnumerable<TDto>> recordGetter) {
|
|
if (!ModelState.IsValid) {
|
|
return Error(HttpStatusCode.BadRequest);
|
|
}
|
|
|
|
try {
|
|
return this.SerializeToJson(this.CreateJsonResponse(data: new { records = recordGetter(apiService) }));
|
|
} catch (ApiException e) {
|
|
return Error(HttpStatusCode.BadRequest, e.Message);
|
|
} catch {
|
|
return Error(HttpStatusCode.InternalServerError, "An error occurred while trying to fulfill your stupid request");
|
|
}
|
|
}
|
|
|
|
public ActionResult Game(ApiModel model) {
|
|
return GetRecords(service => service.GetGames(model));
|
|
}
|
|
|
|
public ActionResult System(ApiModel model) {
|
|
return GetRecords(service => service.GetSystems(model));
|
|
}
|
|
|
|
public ActionResult Category(ApiModel model) {
|
|
return GetRecords(service => service.GetCategories(model));
|
|
}
|
|
|
|
public ActionResult Publisher(ApiModel model) {
|
|
return GetRecords(service => service.GetPublishers(model));
|
|
}
|
|
|
|
public ActionResult Quote(ApiModel model) {
|
|
return GetRecords(service => service.GetQuotes(model));
|
|
}
|
|
}
|
|
} |