Skip to content

Commit

Permalink
Update template solution, resolves #15, decouple include/exclude json…
Browse files Browse the repository at this point in the history
… fields. (#19)

* Initial changes.

* Complete template update, fix issue 15, decouple include/exclude json fields.
  • Loading branch information
chullybun committed Jan 25, 2020
1 parent aa1ca32 commit 3b8c7d9
Show file tree
Hide file tree
Showing 41 changed files with 274 additions and 130 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ The following are references to additional documentation (these are all accessib
### Code-generation

- [Code generation](./tools/Beef.CodeGen.Core/README.md)
- [Template structure](./docs/Template-Structure.md)
- [Template structure](./docs/Template-structure.md)
- Entity-driven:
- [CodeGeneration element](./docs/Entity-CodeGeneration-element.md)
- [Entity element](./docs/Entity-Entity-element.md)
Expand Down
13 changes: 13 additions & 0 deletions samples/Demo/Beef.Demo.Business/DataSvc/Generated/PersonDataSvc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,19 @@ public static Task<PersonDetail> UpdateDetailAsync(PersonDetail value)
});
}

/// <summary>
/// Validate a DataSvc Custom generation.
/// </summary>
/// <returns>A resultant <see cref="int"/>.</returns>
public static Task<int> DataSvcCustomAsync()
{
return DataSvcInvoker.Default.InvokeAsync(typeof(PersonDataSvc), async () =>
{
var __result = await DataSvcCustomOnImplementationAsync().ConfigureAwait(false);
return __result;
});
}

/// <summary>
/// Gets the <see cref="Person"/> collection object that matches the selection criteria.
/// </summary>
Expand Down
10 changes: 8 additions & 2 deletions samples/Demo/Beef.Demo.Business/DataSvc/PersonDataSvc.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;

namespace Beef.Demo.Business.DataSvc
{
Expand All @@ -13,5 +14,10 @@ private static async Task MarkOnAfterAsync()
{
await Beef.Events.Event.PublishAsync("Wahlberg", "Demo.Mark", "Marked").ConfigureAwait(false);
}

private static Task<int> DataSvcCustomOnImplementationAsync()
{
throw new NotImplementedException();
}
}
}
}
6 changes: 6 additions & 0 deletions samples/Demo/Beef.Demo.Business/Generated/IPersonManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ public partial interface IPersonManager
/// <param name="person">The Person (see <see cref="Person"/>).</param>
Task AddAsync(Person person);

/// <summary>
/// Validate a DataSvc Custom generation.
/// </summary>
/// <returns>A resultant <see cref="int"/>.</returns>
Task<int> DataSvcCustomAsync();

/// <summary>
/// Gets the <see cref="Person"/> collection object that matches the selection criteria.
/// </summary>
Expand Down
20 changes: 20 additions & 0 deletions samples/Demo/Beef.Demo.Business/Generated/PersonManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ public partial class PersonManager : IPersonManager
private readonly Func<PersonDetail, Guid, Task> _updateDetailOnBeforeAsync;
private readonly Func<PersonDetail, Guid, Task> _updateDetailOnAfterAsync;

private readonly Func<Task> _dataSvcCustomOnBeforeAsync;
private readonly Func<int, Task> _dataSvcCustomOnAfterAsync;

private readonly Func<PersonArgs, PagingArgs, Task> _getByArgsWithEfOnPreValidateAsync;
private readonly Action<MultiValidator, PersonArgs, PagingArgs> _getByArgsWithEfOnValidate;
private readonly Func<PersonArgs, PagingArgs, Task> _getByArgsWithEfOnBeforeAsync;
Expand Down Expand Up @@ -408,6 +411,23 @@ public Task AddAsync(Person person)
});
}

/// <summary>
/// Validate a DataSvc Custom generation.
/// </summary>
/// <returns>A resultant <see cref="int"/>.</returns>
public Task<int> DataSvcCustomAsync()
{
return ManagerInvoker.Default.InvokeAsync(this, async () =>
{
ExecutionContext.Current.OperationType = OperationType.Unspecified;
if (_dataSvcCustomOnBeforeAsync != null) await _dataSvcCustomOnBeforeAsync().ConfigureAwait(false);
var __result = await PersonDataSvc.DataSvcCustomAsync().ConfigureAwait(false);
if (_dataSvcCustomOnAfterAsync != null) await _dataSvcCustomOnAfterAsync(__result).ConfigureAwait(false);
Cleaner.Clean(__result);
return __result;
});
}

/// <summary>
/// Gets the <see cref="Person"/> collection object that matches the selection criteria.
/// </summary>
Expand Down
2 changes: 2 additions & 0 deletions samples/Demo/Beef.Demo.CodeGen/Beef.Demo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
<Parameter Name="Person" Type="Person" WebApiFrom="FromBody"/>
</Operation>

<Operation Name="DataSvcCustom" OperationType="Custom" Text="Validate a DataSvc Custom generation" ReturnType="int" DataSvcCustom="true" ExcludeData="true" ExcludeIData="true" ExcludeWebApi="true" ExcludeWebApiAgent="true" />

<!-- Entity Framework -->
<Operation Name="GetByArgsWithEf" OperationType="GetColl" PagingArgs="true" WebApiRoute="args" AutoImplement="EntityFramework">
<Parameter Name="Args" Type="PersonArgs" Validator="PersonArgsValidator" />
Expand Down
5 changes: 2 additions & 3 deletions samples/Demo/Beef.Demo.Test/PersonTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -288,12 +288,11 @@ public void C110_GetAll_Paging()
public void C120_GetAll_PagingAndFieldFiltering()
{
var pa = PagingArgs.CreateSkipAndTake(1, 2);
pa.IncludeFields.Add("lastName");
pa.IncludeFields.Add("firstName");
var ro = new WebApiRequestOptions().Include("lastName", "firstName");

var pcr = AgentTester.Create<PersonAgent, PersonCollectionResult>()
.ExpectStatusCode(HttpStatusCode.OK)
.Run((a) => a.Agent.GetAllAsync(pa));
.Run((a) => a.Agent.GetAllAsync(pa, ro));

// Check only 2 are returned in the sorted order.
Assert.AreEqual(2, pcr?.Value?.Result?.Count);
Expand Down
11 changes: 7 additions & 4 deletions src/Beef.AspNetCore.WebApi/Beef.AspNetCore.WebApi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<RootNamespace>Beef.AspNetCore.WebApi</RootNamespace>
<AssemblyVersion>2.1.13</AssemblyVersion>
<FileVersion>2.1.13</FileVersion>
<Version>2.1.13</Version>
<AssemblyVersion>2.1.14</AssemblyVersion>
<FileVersion>2.1.14</FileVersion>
<Version>2.1.14</Version>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Authors>Beef Developers</Authors>
<Company>Avanade</Company>
Expand Down Expand Up @@ -36,7 +36,10 @@
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Formatters.Json" Version="2.2.0" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.3" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Http" Version="2.2.0" />
</ItemGroup>

Expand Down
3 changes: 3 additions & 0 deletions src/Beef.AspNetCore.WebApi/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

Represents the **NuGet** versions.

## v2.1.14
- *Fixed:* Decoupled (removed) the `IncludeFields` and `ExcludeFields` from the `PagingArgs` are these relate to any request not those that just include paging; these now exist as properties on the `WebApiActionBase`.

## v2.1.13
- *Enhancement:* Sprinkled `Task.ConfigureAwait(false)` as per https://devblogs.microsoft.com/dotnet/configureawait-faq/.

Expand Down
17 changes: 16 additions & 1 deletion src/Beef.AspNetCore.WebApi/WebApiActionBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@ public static T Value<T>(T value)
PagingArgs = WebApiQueryString.CreatePagingArgs(Controller);
ExecutionContext.Current.PagingArgs = PagingArgs;

// Get the other request options.
var (include, exclude) = WebApiQueryString.GetOtherRequestOptions(Controller);
IncludeFields.AddRange(include);
ExcludeFields.AddRange(exclude);

// Add to the ExecutionContext in case we need access to the originating request at any stage.
ExecutionContext.Current.Properties.Add(ExecutionContextPropertyKey, this);
}
Expand Down Expand Up @@ -242,6 +247,16 @@ public static T Value<T>(T value)
/// </summary>
public PagingArgs PagingArgs { get; private set; }

/// <summary>
/// Gets or sets the list of <b>included</b> fields (JSON property names) to limit the serialized data payload (url query string: "$fields=x,y,z").
/// </summary>
public List<string> IncludeFields { get; } = new List<string>();

/// <summary>
/// Gets or sets the list of <b>excluded</b> fields (JSON property names) to limit the serialized data payload (url query string: "$excludefields=x,y,z").
/// </summary>
public List<string> ExcludeFields { get; } = new List<string>();

/// <summary>
/// Gets the <see cref="FromBodyAttribute"/> value.
/// </summary>
Expand Down Expand Up @@ -401,7 +416,7 @@ private async Task ExecuteResultAsyncInternal<TResult>(ActionContext context, Fu
if (ExecutionContext.HasCurrent && Controller.IncludeRefDataText())
ExecutionContext.Current.IsRefDataTextSerializationEnabled = true;

var json = JsonPropertyFilter.Apply(result, PagingArgs.IncludeFields, PagingArgs.ExcludeFields);
var json = JsonPropertyFilter.Apply(result, IncludeFields, ExcludeFields);

if (ExecutionContext.HasCurrent && !string.IsNullOrEmpty(ExecutionContext.Current.ETag))
return (json, ExecutionContext.Current.ETag);
Expand Down
37 changes: 25 additions & 12 deletions src/Beef.AspNetCore.WebApi/WebApiQueryString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ public static class WebApiQueryString
public static IEnumerable<string> PagingArgsCountQueryStringNames { get; set; } = new string[] { "$count", "$totalCount" };

/// <summary>
/// Gets or sets the list of possible <see cref="PagingArgs.IncludeFields"/> query string names.
/// Gets or sets the list of possible "include field" query string names.
/// </summary>
public static IEnumerable<string> IncludeFieldsQueryStringNames { get; set; } = new string[] { "$fields", "$includeFields", "$include" };

/// <summary>
/// Gets or sets the list of possible <see cref="PagingArgs.ExcludeFields"/> query string names.
/// Gets or sets the list of possible "exclude field" query string names.
/// </summary>
public static IEnumerable<string> ExcludeFieldsQueryStringNames { get; set; } = new string[] { "$excludeFields", "$exclude" };

Expand Down Expand Up @@ -85,14 +85,6 @@ public static PagingArgs CreatePagingArgs(this ControllerBase controller)
pa = (skip.HasValue) ? PagingArgs.CreateSkipAndTake(skip.Value, take) : PagingArgs.CreatePageAndSize(page.Value, take);

pa.IsGetCount = ParseBoolValue(GetNamedQueryString(controller, PagingArgsCountQueryStringNames));

var fields = GetNamedQueryString(controller, IncludeFieldsQueryStringNames);
if (!string.IsNullOrEmpty(fields))
pa.IncludeFields.AddRange(fields.Split(',', StringSplitOptions.RemoveEmptyEntries));

fields = GetNamedQueryString(controller, ExcludeFieldsQueryStringNames);
if (!string.IsNullOrEmpty(fields))
pa.ExcludeFields.AddRange(fields.Split(',', StringSplitOptions.RemoveEmptyEntries));
}

if (ExecutionContext.HasCurrent && ExecutionContext.Current.PagingArgs == null)
Expand All @@ -101,6 +93,27 @@ public static PagingArgs CreatePagingArgs(this ControllerBase controller)
return pa;
}

/// <summary>
/// Gets the other known request options.
/// </summary>
/// <param name="controller">The <see cref="ControllerBase"/> that has the request url.</param>
/// <returns>The other known request options.</returns>
internal static (List<string> includeFields, List<string> excludeFields) GetOtherRequestOptions(this ControllerBase controller)
{
var includeFields = new List<string>();
var excludeFields = new List<string>();

var fields = GetNamedQueryString(controller, IncludeFieldsQueryStringNames);
if (!string.IsNullOrEmpty(fields))
includeFields.AddRange(fields.Split(',', StringSplitOptions.RemoveEmptyEntries));

fields = GetNamedQueryString(controller, ExcludeFieldsQueryStringNames);
if (!string.IsNullOrEmpty(fields))
excludeFields.AddRange(fields.Split(',', StringSplitOptions.RemoveEmptyEntries));

return (includeFields, excludeFields);
}

/// <summary>
/// Gets the value for the named query string.
/// </summary>
Expand Down Expand Up @@ -175,10 +188,10 @@ public static bool IncludeRefDataText(this ControllerBase controller)

var dict = new Dictionary<string, KeyValuePair<string, StringValues>>();
#pragma warning disable CA1062 // Validate arguments of public methods; see Check above.
if (controller.HttpContext.Request.Query.Count() == 0)
if (!controller.HttpContext.Request.Query.Any())
#pragma warning restore CA1062
{
ExecutionContext.Current.Messages.AddInfo("Query string is required to filter selection; e.g. api/v1/demo/ref?entity=codeX,codeY&entity2=codeZ&entity3");
ExecutionContext.Current.Messages.AddInfo("Query string is required to filter selection; e.g. /ref?entity=codeX,codeY&entity2=codeZ&entity3");
return dict.Values;
}

Expand Down
8 changes: 4 additions & 4 deletions src/Beef.Core/Beef.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>Beef</RootNamespace>
<AssemblyVersion>2.1.27</AssemblyVersion>
<FileVersion>2.1.27</FileVersion>
<Version>2.1.27</Version>
<AssemblyVersion>2.1.28</AssemblyVersion>
<FileVersion>2.1.28</FileVersion>
<Version>2.1.28</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>Beef Developers</Authors>
<Company>Avanade</Company>
Expand Down Expand Up @@ -36,7 +36,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7">
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
3 changes: 3 additions & 0 deletions src/Beef.Core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

Represents the **NuGet** versions.

## v2.1.28
- *Fixed:* Decoupled (removed) the `IncludeFields` and `ExcludeFields` from the `PagingArgs` are these relate to any request not those that just include paging; these now exist as properties on the `WebApiRequestOptions`. Apologies, if used this will result in a breaking change.

## v2.1.27
- *Enhancement:* Sprinkled `Task.ConfigureAwait(false)` as per https://devblogs.microsoft.com/dotnet/configureawait-faq/.

Expand Down
16 changes: 1 addition & 15 deletions src/Beef.Core/Entities/PagingArgs.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
// Copyright (c) Avanade. Licensed under the MIT License. See https://github.com/Avanade/Beef

using System;
using System.Collections.Generic;

namespace Beef.Entities
{
/// <summary>
/// Represents either position-based paging being (<see cref="Page"/> and <see cref="Size"/>), or <see cref="Skip"/> and <see cref="Take"/>. The <see cref="DefaultTake"/>
/// and <see cref="MaxTake"/> (and <see cref="DefaultIsGetCount"/>) are system-wide settings to encourage page-size consistency, as well as limit the maximum value possible.
/// Selection of <see cref="IncludeFields"/> and <see cref="ExcludeFields"/> is also supported to limit the data payload where serializing.
/// </summary>
public class PagingArgs
{
Expand Down Expand Up @@ -108,8 +106,6 @@ public PagingArgs(PagingArgs pagingArgs)
Take = pagingArgs.Take;
Page = pagingArgs.Page;
IsGetCount = pagingArgs.IsGetCount;
IncludeFields = pagingArgs.IncludeFields;
ExcludeFields = pagingArgs.ExcludeFields;
}

/// <summary>
Expand Down Expand Up @@ -162,15 +158,5 @@ public void OverrideTake(long take)
/// Indicates whether to get the total count (see <see cref="PagingResult.TotalCount"/>) when performing the underlying query (defaults to <c>false</c>).
/// </summary>
public bool IsGetCount { get; set; } = false;

/// <summary>
/// Gets or sets the list of <b>included</b> fields (JSON property names) to limit serialization data payload.
/// </summary>
public List<string> IncludeFields { get; } = new List<string>();

/// <summary>
/// Gets or sets the list of <b>excluded</b> fields (JSON property names) to limit serialization data payload.
/// </summary>
public List<string> ExcludeFields { get; } = new List<string>();
}
}
}
6 changes: 1 addition & 5 deletions src/Beef.Core/Entities/PagingResult.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
// Copyright (c) Avanade. Licensed under the MIT License. See https://github.com/Avanade/Beef

using System;

namespace Beef.Entities
{
/// <summary>
Expand All @@ -24,8 +22,6 @@ public PagingResult(PagingArgs pagingArgs, long? totalCount = null)
Page = pagingArgs.Page;
IsGetCount = pagingArgs.IsGetCount;
TotalCount = (totalCount.HasValue && totalCount.Value < 0) ? null : totalCount;
IncludeFields.AddRange(pagingArgs.IncludeFields);
ExcludeFields.AddRange(pagingArgs.ExcludeFields);
}

/// <summary>
Expand All @@ -44,4 +40,4 @@ public PagingResult(PagingArgs pagingArgs, long? totalCount = null)
/// </summary>
public long? TotalPages => !IsSkipTake && TotalCount.HasValue ? (long)System.Math.Ceiling(TotalCount.Value / (double)Take) : (long?)null;
}
}
}
4 changes: 2 additions & 2 deletions src/Beef.Core/Executors/ExecutionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ public static ExecutionManager Create<TArgs>(Func<ExecutorBase<TArgs>> executorC
var exe = executor as CollectionExecutorBase<TColl, TItem>;
await exe.RunWrapperAsync(ExceptionHandling.Stop, async () =>
{
await exe.CompletionRunAsync(new ExecutorCompletionRunArgs(exe, await exe.RunItemsAsync(exe, await exe.RunCollectionAsync(new ExecutorCollectionRunArgs(exe)).ConfigureAwait(false)))).ConfigureAwait(false);
await exe.CompletionRunAsync(new ExecutorCompletionRunArgs(exe, await exe.RunItemsAsync(exe, await exe.RunCollectionAsync(new ExecutorCollectionRunArgs(exe)).ConfigureAwait(false)).ConfigureAwait(false))).ConfigureAwait(false);
}, exe).ConfigureAwait(false);
});
}
Expand Down Expand Up @@ -227,7 +227,7 @@ public static ExecutionManager Create<TArgs>(Func<ExecutorBase<TArgs>> executorC
exe.ExecutorArgs = ((TriggerEventArgs)args).Args;
await exe.RunWrapperAsync(ExceptionHandling.Stop, async () =>
{
await exe.CompletionRunAsync(new ExecutorCompletionRunArgs(exe, await exe.RunItemsAsync(exe, await exe.RunCollectionAsync(new ExecutorCollectionRunArgs<TArgs>(exe)).ConfigureAwait(false)))).ConfigureAwait(false);
await exe.CompletionRunAsync(new ExecutorCompletionRunArgs(exe, await exe.RunItemsAsync(exe, await exe.RunCollectionAsync(new ExecutorCollectionRunArgs<TArgs>(exe)).ConfigureAwait(false)).ConfigureAwait(false))).ConfigureAwait(false);
}, exe).ConfigureAwait(false);
});
}
Expand Down
Loading

0 comments on commit 3b8c7d9

Please sign in to comment.