Skip to content

Commit 2630fa1

Browse files
Moved DynamoDB items rendering to frontend and added ability to load more items
1 parent 65611c7 commit 2630fa1

File tree

10 files changed

+422
-71
lines changed

10 files changed

+422
-71
lines changed

GuiStack/Controllers/DynamoDB/TablesController.cs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,18 @@
88
*/
99

1010
using System;
11+
using System.IO;
12+
using System.IO.Compression;
13+
using System.Linq;
1114
using System.Net;
1215
using System.Threading.Tasks;
1316
using Amazon.DynamoDBv2;
1417
using GuiStack.Extensions;
1518
using GuiStack.Models;
1619
using GuiStack.Repositories;
1720
using Microsoft.AspNetCore.Mvc;
21+
using Microsoft.AspNetCore.WebUtilities;
22+
using Newtonsoft.Json;
1823

1924
namespace GuiStack.Controllers.DynamoDB
2025
{
@@ -29,6 +34,40 @@ public TablesController(IDynamoDBRepository dynamodbRepository)
2934
this.dynamodbRepository = dynamodbRepository;
3035
}
3136

37+
private static DynamoDBItemModel DeserializeItem(string data)
38+
{
39+
using var resultStream = new MemoryStream();
40+
using var reader = new StreamReader(resultStream);
41+
42+
using (var compressedStream = new MemoryStream(WebEncoders.Base64UrlDecode(data)))
43+
using (var decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress))
44+
{
45+
decompressionStream.CopyTo(resultStream);
46+
}
47+
48+
resultStream.Position = 0;
49+
50+
var json = reader.ReadToEnd();
51+
52+
// Utilizing Newtonsoft.Json as it better handles scalar types (string, int, etc.) when the target property is of type System.Object
53+
// System.Text.Json deserializes these as JsonElement, which is not ideal
54+
return JsonConvert.DeserializeObject<DynamoDBItemModel>(json);
55+
}
56+
57+
private static string SerializeItem(DynamoDBItemModel model)
58+
{
59+
using var stream = new MemoryStream();
60+
61+
using (var compressionStream = new GZipStream(stream, CompressionLevel.Fastest))
62+
using (var writer = new StreamWriter(compressionStream))
63+
{
64+
var json = JsonConvert.SerializeObject(model);
65+
writer.Write(json);
66+
}
67+
68+
return WebEncoders.Base64UrlEncode(stream.ToArray());
69+
}
70+
3271
private ActionResult HandleException(Exception ex)
3372
{
3473
if(ex == null)
@@ -85,6 +124,51 @@ public async Task<ActionResult> DeleteTable([FromRoute] string tableName)
85124
}
86125
}
87126

127+
[HttpGet("{tableName}")]
128+
[Produces("application/json")]
129+
public async Task<ActionResult> GetItems([FromRoute] string tableName, [FromQuery] int limit = 50, [FromQuery(Name = "lastEvaluatedKey")] string lastKey = null)
130+
{
131+
if(string.IsNullOrWhiteSpace(tableName) || limit < 1 || limit > 500)
132+
return StatusCode((int)HttpStatusCode.BadRequest);
133+
134+
tableName = tableName.DecodeRouteParameter();
135+
136+
try
137+
{
138+
var lastKeyItem = !string.IsNullOrWhiteSpace(lastKey)
139+
? DeserializeItem(lastKey)
140+
: null;
141+
142+
var table = await dynamodbRepository.GetTableInfoAsync(tableName);
143+
var result = await dynamodbRepository.ScanAsync(tableName, limit, lastKeyItem);
144+
145+
var lastEvaluatedKey = result.LastEvaluatedKey != null
146+
? SerializeItem(result.LastEvaluatedKey)
147+
: null;
148+
149+
var attributeNames = new[] { table.PartitionKey.Name, table.SortKey?.Name } // Ensure PartitionKey and SortKey are always first
150+
.Where(name => name != null)
151+
.Concat(result.Items // Join with the rest of the fields
152+
.SelectMany(item => item.Select(kvp => kvp.Key))
153+
.Where(name => name != table.PartitionKey.Name && (table.SortKey == null || name != table.SortKey.Name))
154+
.Distinct()
155+
)
156+
.ToArray();
157+
158+
return Json(new DynamoDBTableContentsModel() {
159+
PartitionKey = table.PartitionKey,
160+
SortKey = table.SortKey,
161+
AttributeNames = attributeNames,
162+
LastEvaluatedKey = lastEvaluatedKey,
163+
Items = result.Items
164+
});
165+
}
166+
catch(Exception ex)
167+
{
168+
return HandleException(ex);
169+
}
170+
}
171+
88172
[HttpPut("{tableName}")]
89173
[Consumes("application/json")]
90174
public async Task<ActionResult> PutItem([FromRoute] string tableName, [FromBody] DynamoDBItemModel model)

GuiStack/GuiStack.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<PackageReference Include="AWSSDK.SQS" Version="3.7.102.1" />
1515
<PackageReference Include="Google.Protobuf" Version="3.20.0" />
1616
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.9" />
17+
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
1718
</ItemGroup>
1819

1920
<ItemGroup>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2007 James Newton-King
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy of
6+
this software and associated documentation files (the "Software"), to deal in
7+
the Software without restriction, including without limitation the rights to
8+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9+
the Software, and to permit persons to whom the Software is furnished to do so,
10+
subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public
3+
* License, v. 2.0. If a copy of the MPL was not distributed with this
4+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
5+
*
6+
* Copyright © Vincent Bengtsson & Contributors 2022-2024
7+
* https://github.com/Visual-Vincent/GuiStack
8+
*/
9+
10+
using System;
11+
using System.Collections.Generic;
12+
13+
namespace GuiStack.Models
14+
{
15+
public class DynamoDBTableContentsModel
16+
{
17+
public DynamoDBAttribute PartitionKey { get; set; }
18+
public DynamoDBAttribute SortKey { get; set; }
19+
public string[] AttributeNames { get; set; }
20+
public string LastEvaluatedKey { get; set; }
21+
22+
public IEnumerable<DynamoDBItemModel> Items { get; set; }
23+
}
24+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public
3+
* License, v. 2.0. If a copy of the MPL was not distributed with this
4+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
5+
*
6+
* Copyright © Vincent Bengtsson & Contributors 2022-2024
7+
* https://github.com/Visual-Vincent/GuiStack
8+
*/
9+
10+
using System;
11+
12+
namespace GuiStack.Models
13+
{
14+
public class DynamoDBTableScanResults
15+
{
16+
public DynamoDBItemModel[] Items { get; set; }
17+
public DynamoDBItemModel LastEvaluatedKey { get; set; }
18+
}
19+
}

GuiStack/Pages/DynamoDB/Index.cshtml.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
*/
99

1010
using System;
11-
using System.Threading.Tasks;
1211
using GuiStack.Repositories;
1312
using Microsoft.AspNetCore.Mvc;
1413
using Microsoft.AspNetCore.Mvc.RazorPages;
@@ -30,11 +29,5 @@ public IndexModel(IDynamoDBRepository dynamodbRepository)
3029
public void OnGet()
3130
{
3231
}
33-
34-
public async Task<IActionResult> OnGetRenderTableContentsPartial([FromQuery] int limit = 50)
35-
{
36-
var items = await DynamoDBRepository.ScanAsync(Table, limit);
37-
return Partial("~/Pages/DynamoDB/_TableContentsPartial.cshtml", items);
38-
}
3932
}
4033
}

GuiStack/Pages/DynamoDB/_TableContentsPartial.cshtml

Lines changed: 0 additions & 52 deletions
This file was deleted.

0 commit comments

Comments
 (0)