Skip to content

Commit 80b1ce8

Browse files
author
Adrian Hall
committed
(#199) Tweak to CreateNextLink to use QueryHelpers.
1 parent 0a2d8d4 commit 80b1ce8

File tree

5 files changed

+14
-33
lines changed

5 files changed

+14
-33
lines changed

src/CommunityToolkit.Datasync.Server/Controllers/TableController.Query.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
using Microsoft.OData;
1717
using System.Diagnostics.CodeAnalysis;
1818
using CommunityToolkit.Datasync.Server.OData;
19+
using Microsoft.AspNetCore.Http.Extensions;
20+
using Microsoft.AspNetCore.WebUtilities;
21+
using Microsoft.Extensions.Primitives;
22+
using System.Globalization;
1923

2024
namespace CommunityToolkit.Datasync.Server;
2125

@@ -155,23 +159,18 @@ internal PagedResult BuildPagedResult(ODataQueryOptions queryOptions, IEnumerabl
155159
// Internal function to create the nextLink property for the paged result.
156160
static string CreateNextLink(HttpRequest request, int skip = 0, int top = 0)
157161
{
158-
string? queryString = request.QueryString.Value;
159-
List<string> query = (queryString ?? "").TrimStart('?')
160-
.Split('&')
161-
.Where(q => !q.StartsWith($"{SkipParameterName}=") && !q.StartsWith($"{TopParameterName}="))
162-
.ToList();
163-
162+
Dictionary<string, StringValues> query = QueryHelpers.ParseNullableQuery(request.QueryString.Value) ?? [];
164163
if (skip > 0)
165164
{
166-
query.Add($"{SkipParameterName}={skip}");
165+
query[SkipParameterName] = skip.ToString(CultureInfo.InvariantCulture);
167166
}
168167

169168
if (top > 0)
170169
{
171-
query.Add($"{TopParameterName}={top}");
170+
query[TopParameterName] = top.ToString(CultureInfo.InvariantCulture);
172171
}
173172

174-
return string.Join('&', query).TrimStart('&');
173+
return QueryHelpers.AddQueryString(string.Empty, query).TrimStart('?');
175174
}
176175

177176
PagedResult result = new(results ?? []) { Count = queryOptions.Count != null ? count : null };

src/CommunityToolkit.Datasync.Server/Extensions/InternalExtensions.cs

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,7 @@ internal static IQueryable<T> ApplyDeletedView<T>(this IQueryable<T> query, Http
5555
/// <param name="settings">The query settings being used.</param>
5656
/// <returns>A modified <see cref="IQueryable{T}"/> representing the filtered data.</returns>
5757
internal static IQueryable<T> ApplyODataFilter<T>(this IQueryable<T> query, FilterQueryOption? filterQueryOption, ODataQuerySettings settings)
58-
{
59-
if (filterQueryOption is null)
60-
{
61-
return query;
62-
}
63-
64-
return ((IQueryable<T>?)filterQueryOption.ApplyTo(query, settings)) ?? query;
65-
}
58+
=> (IQueryable<T>)(filterQueryOption?.ApplyTo(query, settings) ?? query);
6659

6760
/// <summary>
6861
/// Applies the <c>$orderBy</c> OData query option to the provided query.
@@ -73,21 +66,7 @@ internal static IQueryable<T> ApplyODataFilter<T>(this IQueryable<T> query, Filt
7366
/// <param name="settings">The query settings being used.</param>
7467
/// <returns>A modified <see cref="IQueryable{T}"/> representing the ordered data.</returns>
7568
internal static IQueryable<T> ApplyODataOrderBy<T>(this IQueryable<T> query, OrderByQueryOption? orderingQueryOption, ODataQuerySettings settings) where T : ITableData
76-
{
77-
// Note that we ALWAYS do a sort so that the ordering is consistent across all queries.
78-
if (orderingQueryOption is null)
79-
{
80-
return query.OrderBy(e => e.Id);
81-
}
82-
83-
IOrderedQueryable<T>? orderedQuery = orderingQueryOption.ApplyTo(query, settings);
84-
if (orderedQuery is null)
85-
{
86-
return query.OrderBy(e => e.Id);
87-
}
88-
89-
return orderedQuery.ThenBy(x => x.Id);
90-
}
69+
=> orderingQueryOption?.ApplyTo(query, settings).ThenBy(e => e.Id) ?? query.OrderBy(e => e.Id);
9170

9271
/// <summary>
9372
/// Applies the <c>$skip</c> and <c>$top</c> OData query options to the provided query.

tests/CommunityToolkit.Datasync.Server.Test/Helpers/LiveControllerTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace CommunityToolkit.Datasync.Server.Test.Helpers;
1010
/// <summary>
1111
/// The base set of tests for the controller tests going against a live server.
1212
/// </summary>
13-
/// <typeparam name="TEntity"></typeparam>
13+
[ExcludeFromCodeCoverage]
1414
public abstract class LiveControllerTests<TEntity> : BaseTest where TEntity : class, ITableData
1515
{
1616
/// <summary>

tests/CommunityToolkit.Datasync.Server.Test/Helpers/LiveTestsCollection.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace CommunityToolkit.Datasync.Server.Test.Helpers;
77
/// <summary>
88
/// This can be used to share state between the various live tests. It isn't used right now.
99
/// </summary>
10+
[ExcludeFromCodeCoverage]
1011
public class DatabaseFixture
1112
{
1213
public bool AzureSqlIsInitialized { get; set; } = false;
@@ -15,6 +16,7 @@ public class DatabaseFixture
1516
public bool PgIsInitialized { get; set; } = false;
1617
}
1718

19+
[ExcludeFromCodeCoverage]
1820
[CollectionDefinition("LiveTestsCollection", DisableParallelization = true)]
1921
public class LiveTestsCollection : ICollectionFixture<DatabaseFixture>
2022
{

tests/CommunityToolkit.Datasync.TestService/AccessControlProviders/MovieAccessControlProvider.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace CommunityToolkit.Datasync.TestService.AccessControlProviders;
99

10+
[ExcludeFromCodeCoverage]
1011
public class MovieAccessControlProvider<T> : AccessControlProvider<T> where T : class, IMovie, ITableData
1112
{
1213
/// <summary>

0 commit comments

Comments
 (0)