Skip to content

Commit

Permalink
Merge branch 'release/1.6.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Ushakov committed May 6, 2024
2 parents 7c88ead + 8b31bcb commit 09374d9
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 24 deletions.
36 changes: 32 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Key concepts:
- `GET /api/[controller]/?[page={page}&size={size}&sort={sort}&order={order}]` to get `PagedDataDto<T>`
now we also have possibility to send **ANY number of query params**, you just have to pass filter func to `EfModelManager` or do it in your own way like in [WeatherControl example with edgedb](https://github.com/Wissance/WeatherControl/blob/master/WeatherControl/Wissance.WeatherControl.WebApi.V2/Helpers/EqlResolver.cs). We also pass sort (column name) && order (`asc` or `desc`) to manager classes,
`EfModelManager` allows to sort **by any column**.
Unfortunately here we have a ***ONE disadvantage*** - **we should override `Swagger` info to show query parameters usage!!!**
<strike> Unfortunately here we have a ***ONE disadvantage*** - **we should override `Swagger` info to show query parameters usage!!!** </strike> Starting from `1.6.0` it is possible to see all parameters in `Swagger` and use them.
- `GET /api/[controller]/{id}` to get one object by `id`
- full `CRUD` controller (`BasicCrudController`) = basic read controller (`BasicReadController`) + `Create`, `Update` and `Delete` operations :
- `POST /api/[controller]` - for new object creation
Expand Down Expand Up @@ -119,7 +119,7 @@ public MoidelContext: DbContext<ModelContext>, IModelContext
5. Create `Controller` class and a manager class pair, i.e. consider here full `CRUD`
```csharp
[ApiController]
public class BookController : BasicCrudController<BookDto, BookEntity, int>
public class BookController : BasicCrudController<BookDto, BookEntity, int, EmptyAdditionalFilters>
{
public BookController(BookManager manager)
{
Expand All @@ -130,7 +130,7 @@ public class BookController : BasicCrudController<BookDto, BookEntity, int>
private BookManager _manager;
}

public class BookManager : EfModelManager<BookEntity, BookDto, int>
public class BookManager : EfModelManager<BookEntity, BookDto, int, EmptyAdditionalFilters>
{
public BookManager(ModelContext modelContext, ILoggerFactory loggerFactory) : base(modelContext, BookFactory.Create, loggerFactory)
{
Expand All @@ -150,6 +150,34 @@ public class BookManager : EfModelManager<BookEntity, BookDto, int>
private readonly ModelContext _modelContext;
}
```

Last generic parameter in above example - `EmptyAdditionalFilters` is a class that holds
additional parameters for search to see in Swagger, just specify a new class implementing
`IReadFilterable` i.e.:

```csharp
public class BooksFilterable : IReadFilterable
{
public IDictionary<string, string> SelectFilters()
{
IDictionary<string, string> additionalFilters = new Dictionary<string, string>();
if (!string.IsNullOrEmpty(Title))
{
additionalFilters.Add(FilterParamsNames.TitleParameter, Title);
}

if (Authors != null && Authors.Length > 0)
{
additionalFilters.Add(FilterParamsNames.AuthorsParameter, string.Join(",", Authors));
}

return additionalFilters;
}

[FromQuery(Name = "title")] public string Title { get; set; }
[FromQuery(Name = "author")] public string[] Authors { get; set; }
}
```

### 5. Nuget package
You could find nuget-package [here](https://www.nuget.org/packages/Wissance.WebApiToolkit)
Expand All @@ -159,7 +187,7 @@ You could find nuget-package [here](https://www.nuget.org/packages/Wissance.WebA

```csharp
[ApiController]
public class StationController : BasicCrudController<StationDto, StationEntity, int>
public class StationController : BasicCrudController<StationDto, StationEntity, int, EmptyAdditionalFilters>
{
public StationController(StationManager manager)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Wissance.WebApiToolkit.Data;
using Wissance.WebApiToolkit.Dto;

namespace Wissance.WebApiToolkit.Controllers
{
public class BasicBulkCrudController<TRes, TData, TId> : BasicReadController<TRes, TData, TId>
public class BasicBulkCrudController<TRes, TData, TId, TFilter> : BasicReadController<TRes, TData, TId, TFilter>
where TRes : class
where TFilter: class, IReadFilterable
{
[HttpPost]
[Route("api/bulk/[controller]")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Wissance.WebApiToolkit.Data;
using Wissance.WebApiToolkit.Dto;

namespace Wissance.WebApiToolkit.Controllers
{
public abstract class BasicCrudController <TRes, TData, TId> : BasicReadController<TRes, TData, TId>
public abstract class BasicCrudController <TRes, TData, TId, TFilter> : BasicReadController<TRes, TData, TId, TFilter>
where TRes : class
where TFilter: class, IReadFilterable
{
[HttpPost]
[Route("api/[controller]")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,22 @@
namespace Wissance.WebApiToolkit.Controllers
{

public abstract class BasicReadController<TRes, TData, TId> : BasicPagedDataController
public abstract class BasicReadController<TRes, TData, TId, TFilter> : BasicPagedDataController
where TRes: class
where TFilter: class, IReadFilterable
{
[HttpGet]
[Route("api/[controller]")]
public virtual async Task<PagedDataDto<TRes>> ReadAsync([FromQuery] int? page, [FromQuery] int? size, [FromQuery] string sort,
[FromQuery] string order)
[FromQuery] string order, TFilter additionalFilters = null)
{
int pageNumber = GetPage(page);
int pageSize = GetPageSize(size);
SortOption sorting = !string.IsNullOrEmpty(sort) ? new SortOption(sort, order) : null;
string queryStrValue = HttpContext.Request.QueryString.Value;
IDictionary<string, StringValues> queryDictionary = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(queryStrValue);
IDictionary<string, string> parameters = queryDictionary.Where(kv => _paramsToOmit.All(p => !string.Equals(p, kv.Key.ToLower())))
.ToDictionary(k => k.Key, v => v.Value.ToString());
OperationResultDto<Tuple<IList<TRes>, long>> result = await Manager.GetAsync(pageNumber, pageSize, sorting, parameters);
IDictionary<string, string> additionalQueryParams = additionalFilters != null
? additionalFilters.SelectFilters()
: new Dictionary<string, string>();
OperationResultDto<Tuple<IList<TRes>, long>> result = await Manager.GetAsync(pageNumber, pageSize, sorting, additionalQueryParams);
HttpContext.Response.StatusCode = result.Status;
return new PagedDataDto<TRes>(pageNumber, result.Data.Item2, PagingUtils.GetTotalPages(result.Data.Item2, pageSize), result.Data.Item1);
}
Expand All @@ -41,17 +41,6 @@ public async Task<TRes> ReadByIdAsync([FromRoute] TId id)
HttpContext.Response.StatusCode = result.Status;
return result.Data;
}

private const string PageQueryParam = "page";
private const string SizeQueryParam = "size";
private const string SortQueryParam = "sort";
private const string OrderQueryParam = "order";

private readonly IList<string> _paramsToOmit = new List<string>()
{
PageQueryParam, SizeQueryParam, SortQueryParam, OrderQueryParam
};

public IModelManager<TRes, TData, TId> Manager { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Collections.Generic;

namespace Wissance.WebApiToolkit.Data
{
public class EmptyAdditionalFilters : IReadFilterable
{
public IDictionary<string, string> SelectFilters()
{
return new Dictionary<string, string>();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Collections.Generic;

namespace Wissance.WebApiToolkit.Data
{
public interface IReadFilterable
{
IDictionary<string, string> SelectFilters();
}
}

0 comments on commit 09374d9

Please sign in to comment.