Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Represents the **NuGet** versions.

## v3.30.2
- *Fixed:* Missing `QueryArgs.IncludeText` added to set the `$text=true` equivalent.
- *Fixed:* Simplification of creating and setting the `QueryArgs.Filter` using an implict string operator.

## v3.30.1
- *Fixed:* Added support for `SettingsBase.DateTimeTransform`, `StringTransform`, `StringTrim` and `StringCase` to allow specification via configuration.
- *Fixed:* Added support for `CoreEx:` hierarchy (optional) for all _CoreEx_ settings to enable a more structured and explicit configuration.
Expand Down
2 changes: 1 addition & 1 deletion Common.targets
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>3.30.1</Version>
<Version>3.30.2</Version>
<LangVersion>preview</LangVersion>
<Authors>Avanade</Authors>
<Company>Avanade</Company>
Expand Down
25 changes: 25 additions & 0 deletions src/CoreEx/Entities/QueryArgs.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) Avanade. Licensed under the MIT License. See https://github.com/Avanade/CoreEx

using CoreEx.RefData;
using System.Collections.Generic;

namespace CoreEx.Entities
Expand Down Expand Up @@ -39,6 +40,12 @@ public class QueryArgs
/// <remarks>Currently these are <b>only</b> used within <i>CoreEx</i> for JSON serialization filtering (see <see cref="CoreEx.Json.IJsonSerializer.TryApplyFilter{T}(T, IEnumerable{string}?, out object, Json.JsonPropertyFilter, System.StringComparison, System.Action{Json.IJsonPreFilterInspector}?)"/>).</remarks>
public List<string>? ExcludeFields { get; set; }

/// <summary>
/// Indicates whether to include any related texts for the item(s).
/// </summary>
/// <remarks>For example, include corresponding <see cref="IReferenceData.Text"/> for any <b>ReferenceData</b> values returned in the JSON response payload.</remarks>
public bool IsTextIncluded { get; set; }

/// <summary>
/// Appends the <paramref name="fields"/> to the <see cref="IncludeFields"/>.
/// </summary>
Expand All @@ -60,5 +67,23 @@ public QueryArgs Exclude(params string[] fields)
(ExcludeFields ??= []).AddRange(fields);
return this;
}

/// <summary>
/// Indicates whether to include any related texts for the item(s); see <see cref="IsTextIncluded"/>.
/// </summary>
/// <returns>The <see cref="QueryArgs"/> to support fluent-style method-chaining.</returns>
/// <remarks>For example, include corresponding <see cref="IReferenceData.Text"/> for any <b>ReferenceData</b> values returned in the JSON response payload.</remarks>
public QueryArgs IncludeText()
{
IsTextIncluded = true;
return this;
}

/// <summary>
/// An implicit cast from a filter <see cref="string"/> to a <see cref="QueryArgs"/>.
/// </summary>
/// <param name="filter">The <see cref="Filter"/>.</param>
/// <returns>The corresponding <see cref="QueryArgs"/>.</returns>
public static implicit operator QueryArgs(string? filter) => Create(filter);
}
}
5 changes: 4 additions & 1 deletion src/CoreEx/Http/HttpRequestOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ public HttpRequestOptions WithQuery(QueryArgs? query)

if (Query.ExcludeFields is not null)
query.Exclude([.. Query.ExcludeFields]);

if (Query.IsTextIncluded)
query.IsTextIncluded = true;
}

Query = query;
Expand Down Expand Up @@ -255,7 +258,7 @@ public HttpRequestOptions WithPaging(PagingArgs? paging)
AddNameValuePairs(sb, QueryStringNameExcludeFields, Query.ExcludeFields.Where(x => !string.IsNullOrEmpty(x)).Select(x => HttpUtility.UrlEncode(x)).ToArray(), false, true);
}

if (IncludeText)
if (IncludeText || (Query is not null && Query.IsTextIncluded))
AddNameValuePair(sb, QueryStringNameIncludeText, "true", false);

if (IncludeInactive)
Expand Down
12 changes: 6 additions & 6 deletions tests/CoreEx.Test/Framework/Data/QueryArgsConfigTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ private static void AssertException(QueryArgsConfig config, string? filter, stri
Assert.That(ex.Messages, Has.Count.EqualTo(1));
Assert.Multiple(() =>
{
Assert.That(ex.Messages.First().Property, Is.EqualTo("$filter"));
Assert.That(ex.Messages.First().Text, Does.StartWith(expected));
Assert.That(ex.Messages!.First().Property, Is.EqualTo("$filter"));
Assert.That(ex.Messages!.First().Text, Does.StartWith(expected));
});
}

Expand Down Expand Up @@ -305,12 +305,12 @@ public void OrderByParser_Invalid()
void AssertException(string? orderBy, string expected)
{
var ex = Assert.Throws<QueryOrderByParserException>(() => _queryConfig.OrderByParser.Parse(orderBy).ThrowOnError());
Assert.That(ex.Messages, Is.Not.Null);
Assert.That(ex.Messages, Has.Count.EqualTo(1));
Assert.That(ex?.Messages, Is.Not.Null);
Assert.That(ex!.Messages, Has.Count.EqualTo(1));
Assert.Multiple(() =>
{
Assert.That(ex.Messages.First().Property, Is.EqualTo("$orderby"));
Assert.That(ex.Messages.First().Text, Does.StartWith(expected));
Assert.That(ex.Messages!.First().Property, Is.EqualTo("$orderby"));
Assert.That(ex.Messages!.First().Text, Does.StartWith(expected));
});
}

Expand Down
13 changes: 12 additions & 1 deletion tests/CoreEx.Test/Framework/Http/HttpRequestOptionsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,23 @@ public void UrlQueryString()
[Test]
public void QueryArgsQueryString()
{
var qa = QueryArgs.Create("name eq 'bob'");
QueryArgs qa = "name eq 'bob'";
var hr = new HttpRequestMessage(HttpMethod.Get, "https://unittest/testing");
var ro = new HttpRequestOptions() { IncludeInactive = true }.Include("name", "text");
ro = ro.WithQuery(qa);
hr.ApplyRequestOptions(ro);
Assert.That(hr.RequestUri!.AbsoluteUri, Is.EqualTo("https://unittest/testing?$filter=name+eq+%27bob%27&$fields=name,text&$inactive=true"));
}

[Test]
public void QueryArgsQueryStringWithIncludeText()
{
var qa = QueryArgs.Create("name eq 'bob'").IncludeText();
var hr = new HttpRequestMessage(HttpMethod.Get, "https://unittest/testing");
var ro = new HttpRequestOptions() { IncludeInactive = true }.Include("name", "text");
ro = ro.WithQuery(qa);
hr.ApplyRequestOptions(ro);
Assert.That(hr.RequestUri!.AbsoluteUri, Is.EqualTo("https://unittest/testing?$filter=name+eq+%27bob%27&$fields=name,text&$text=true&$inactive=true"));
}
}
}
Loading