Skip to content

Commit d50348c

Browse files
committed
Merge branch 'release/1.5.0'
2 parents 1297b92 + 23203fa commit d50348c

File tree

8 files changed

+161
-18
lines changed

8 files changed

+161
-18
lines changed
Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
using Microsoft.AspNetCore.Mvc;
2+
using Wissance.WebApiToolkit.Utils;
23

34
namespace Wissance.WebApiToolkit.Controllers
45
{
56
public abstract class BasicPagedDataController : ControllerBase
67
{
78
protected int GetPage(int? page)
89
{
9-
int selectedPage = page ?? DefaultPage;
10-
return selectedPage < 1 ? 1 : selectedPage;
10+
return PagingUtils.GetPage(page);
1111
}
1212

1313
protected int GetPageSize(int? size)
1414
{
15-
return size ?? DefaultSize;
15+
return PagingUtils.GetPageSize(size);
1616
}
17-
18-
private const int DefaultPage = 1;
19-
private const int DefaultSize = 25;
2017
}
2118
}

Wissance.WebApiToolkit/Wissance.WebApiToolkit/Controllers/BasicReadController.cs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using Wissance.WebApiToolkit.Data;
99
using Wissance.WebApiToolkit.Dto;
1010
using Wissance.WebApiToolkit.Managers;
11+
using Wissance.WebApiToolkit.Utils;
1112

1213
namespace Wissance.WebApiToolkit.Controllers
1314
{
@@ -29,7 +30,7 @@ public virtual async Task<PagedDataDto<TRes>> ReadAsync([FromQuery] int? page, [
2930
.ToDictionary(k => k.Key, v => v.Value.ToString());
3031
OperationResultDto<Tuple<IList<TRes>, long>> result = await Manager.GetAsync(pageNumber, pageSize, sorting, parameters);
3132
HttpContext.Response.StatusCode = result.Status;
32-
return new PagedDataDto<TRes>(pageNumber, result.Data.Item2, GetTotalPages(result.Data.Item2, pageSize), result.Data.Item1);
33+
return new PagedDataDto<TRes>(pageNumber, result.Data.Item2, PagingUtils.GetTotalPages(result.Data.Item2, pageSize), result.Data.Item1);
3334
}
3435

3536
[HttpGet]
@@ -41,17 +42,6 @@ public async Task<TRes> ReadByIdAsync([FromRoute] TId id)
4142
return result.Data;
4243
}
4344

44-
private long GetTotalPages(long totalItems, int pageSize)
45-
{
46-
if (pageSize <= 0)
47-
{
48-
// todo(UMV): this is hardly ever possible but add logging here for jokers
49-
return -1;
50-
}
51-
52-
return (long)Math.Ceiling((double)totalItems / pageSize);
53-
}
54-
5545
private const string PageQueryParam = "page";
5646
private const string SizeQueryParam = "size";
5747
private const string SortQueryParam = "sort";
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System.Threading.Tasks;
2+
using Wissance.WebApiToolkit.Dto;
3+
4+
namespace Wissance.WebApiToolkit.Services
5+
{
6+
/// <summary>
7+
/// This is a Resource based CRUD Service interface to interact in a Resource-oriented way
8+
/// via GRPC, could be used also for others Frameworks &amp;&amp; Protocols like SignalR &amp;&amp; WCF. This interface should be
9+
/// implemented in some real service classes. Examples will be here: https://github.com/Wissance/WeatherControl . Contains methods
10+
/// for Create, Update and Delete TData item respectively.
11+
/// </summary>
12+
/// <typeparam name="TRes">TRes (Resource) means Representation of Persistent data in external system i.e. DTO</typeparam>
13+
/// <typeparam name="TData">Persistent item type, in terms of Web App it is a Table or some ORM Entity Class</typeparam>
14+
/// <typeparam name="TId">Unique Identifier type (could be different for different apps i.e int/string/Guid)</typeparam>
15+
public interface IResourceBasedCrudService<TRes, TData, TId> : IResourceBasedReadOnlyService<TRes, TData, TId>
16+
where TRes: class
17+
{
18+
Task<OperationResultDto<TRes>> CreateAsync(TRes data);
19+
Task<OperationResultDto<TRes>> UpdateAsync(TId id, TRes data);
20+
Task<OperationResultDto<bool>> DeleteAsync(TId id);
21+
}
22+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.Collections.Generic;
2+
using System.Threading.Tasks;
3+
using Wissance.WebApiToolkit.Dto;
4+
5+
namespace Wissance.WebApiToolkit.Services
6+
{
7+
/// <summary>
8+
/// This is a general RO-interface for object Reading. Mainly this interface is using for interact in a Resource-oriented way
9+
/// via GRPC, could be used also for others Frameworks && Protocols like SignalR && WCF. This interface should be
10+
/// implemented in some real service classes. Examples will be here: https://github.com/Wissance/WeatherControl
11+
/// </summary>
12+
/// <typeparam name="TRes">TRes (Resource) means Representation of Persistent data in external system i.e. DTO</typeparam>
13+
/// <typeparam name="TData">Persistent item type, in terms of Web App it is a Table or some ORM Entity Class</typeparam>
14+
/// <typeparam name="TId">Unique Identifier type (could be different for different apps i.e int/string/Guid)</typeparam>
15+
public interface IResourceBasedReadOnlyService<TRes, TData, TId>
16+
where TRes: class
17+
{
18+
Task<PagedDataDto<TRes>> ReadAsync(int? page, int? size, string sort, string order, IDictionary<string, string> filterParams);
19+
Task<TRes> ReadByIdAsync(TId id);
20+
}
21+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.Threading.Tasks;
2+
using Wissance.WebApiToolkit.Dto;
3+
4+
namespace Wissance.WebApiToolkit.Services
5+
{
6+
/// <summary>
7+
/// This is a full CRUD service implementation based on usage IModelManager as a service class for accessing
8+
/// persistent storage. This class has both Read operations (from ResourceBasedDataManageableReadOnlyService)
9+
/// and Create, Update and Delete operations
10+
/// </summary>
11+
/// <typeparam name="TRes">TRes (Resource) means Representation of Persistent data in external system i.e. DTO</typeparam>
12+
/// <typeparam name="TData">Persistent item type, in terms of Web App it is a Table or some ORM Entity Class</typeparam>
13+
/// <typeparam name="TId">Unique Identifier type (could be different for different apps i.e int/string/Guid)</typeparam>
14+
public class ResourceBasedDataManageableCrudService<TRes, TData, TId> : ResourceBasedDataManageableReadOnlyService<TRes, TData, TId>,
15+
IResourceBasedCrudService<TRes, TData, TId>
16+
where TRes: class
17+
{
18+
public async Task<OperationResultDto<TRes>> CreateAsync(TRes data)
19+
{
20+
OperationResultDto<TRes> result = await Manager.CreateAsync(data);
21+
return result;
22+
}
23+
24+
public async Task<OperationResultDto<TRes>> UpdateAsync(TId id, TRes data)
25+
{
26+
OperationResultDto<TRes> result = await Manager.UpdateAsync(id, data);
27+
return result;
28+
}
29+
30+
public async Task<OperationResultDto<bool>> DeleteAsync(TId id)
31+
{
32+
OperationResultDto<bool> result = await Manager.DeleteAsync(id);
33+
return result;
34+
}
35+
}
36+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Threading.Tasks;
4+
using Wissance.WebApiToolkit.Data;
5+
using Wissance.WebApiToolkit.Dto;
6+
using Wissance.WebApiToolkit.Managers;
7+
using Wissance.WebApiToolkit.Utils;
8+
9+
namespace Wissance.WebApiToolkit.Services
10+
{
11+
/// <summary>
12+
/// This is an implementation of IResourceBasedReadOnlyService based on usage IModelManager as a service class for accessing
13+
/// persistent storage. This class has 2 Operations:
14+
/// 1. Read portion (page) of TData via Manager and Transform it to TRes inside Manager (see i.e. EfModelManager, EfSoftRemovableModelManager)
15+
/// 2. Read single item from Manager and return it TRes representation
16+
/// This service class ia analog of a REST BasicReadController
17+
/// </summary>
18+
/// <typeparam name="TRes">TRes (Resource) means Representation of Persistent data in external system i.e. DTO</typeparam>
19+
/// <typeparam name="TData">Persistent item type, in terms of Web App it is a Table or some ORM Entity Class</typeparam>
20+
/// <typeparam name="TId">Unique Identifier type (could be different for different apps i.e int/string/Guid)</typeparam>
21+
public abstract class ResourceBasedDataManageableReadOnlyService<TRes, TData, TId> : IResourceBasedReadOnlyService<TRes, TData, TId>
22+
where TRes : class
23+
{
24+
public virtual async Task<PagedDataDto<TRes>> ReadAsync(int? page, int? size, string sort, string order, IDictionary<string, string> filterParams)
25+
{
26+
int pageNumber = PagingUtils.GetPage(page);
27+
int pageSize = PagingUtils.GetPageSize(size);
28+
SortOption sorting = !string.IsNullOrEmpty(sort) ? new SortOption(sort, order) : null;
29+
OperationResultDto<Tuple<IList<TRes>, long>> result = await Manager.GetAsync(pageNumber, pageSize, sorting, filterParams);
30+
return new PagedDataDto<TRes>(pageNumber, result.Data.Item2, PagingUtils.GetTotalPages(result.Data.Item2, pageSize), result.Data.Item1);
31+
}
32+
33+
public virtual async Task<TRes> ReadByIdAsync(TId id)
34+
{
35+
OperationResultDto<TRes> result = await Manager.GetByIdAsync(id);
36+
return result.Data;
37+
}
38+
39+
public IModelManager<TRes, TData, TId> Manager { get; set; }
40+
}
41+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
3+
namespace Wissance.WebApiToolkit.Utils
4+
{
5+
public static class PagingUtils
6+
{
7+
public static long GetTotalPages(long totalItems, int pageSize)
8+
{
9+
if (pageSize <= 0)
10+
{
11+
// todo(UMV): this is hardly ever possible but add logging here for jokers
12+
return -1;
13+
}
14+
15+
return (long)Math.Ceiling((double)totalItems / pageSize);
16+
}
17+
18+
public static int GetPage(int? page)
19+
{
20+
int selectedPage = page ?? DefaultPage;
21+
return selectedPage < 1 ? 1 : selectedPage;
22+
}
23+
24+
public static int GetPageSize(int? size)
25+
{
26+
return size ?? DefaultSize;
27+
}
28+
29+
private const int DefaultPage = 1;
30+
private const int DefaultSize = 25;
31+
}
32+
}

Wissance.WebApiToolkit/Wissance.WebApiToolkit/Wissance.WebApiToolkit.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
</ItemGroup>
1111

1212
<ItemGroup>
13+
<PackageReference Include="Grpc.Tools" Version="2.60.0">
14+
<PrivateAssets>all</PrivateAssets>
15+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
16+
</PackageReference>
1317
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
1418
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
1519
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.2" />

0 commit comments

Comments
 (0)