Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v5.12.0 #238

Merged
merged 5 commits into from
Mar 19, 2024
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

Represents the **NuGet** versions.

## v5.12.0
- *Enhancement:* Added `WebApiTags` code-generation property to enable the specification of `Tags` for the Web API Controller class.
- *Enhancement:* Added `dotnet run endpoints` option to report all configured endpoints providing a means to audit the generated API surface.
- *Enhancement:* Secondary (additional) configuration files `*.entity.beef-5.yaml`, `*.refdata.beef-5.yaml`, `*.datamodel.beef-5.yaml` can be added to the project (including within subfolders) that will be automatically merged into the corresponding primary `entity.beef-5.yaml`, `refdata.beef-5.yaml`, `datamodel.beef-5.yaml` files respectively. The secondary files only support a single root `entities` property/node that merges into the primary's equivalent. This allows the configuration to be broken up logically to minimize challenges related to overall file size and complexity, and minimize potential developer merge conflicts, etc.
- *Fixed:* The `Operation.ReturnType` was incorrectly determining and overridding nullability (`Operation.ReturnTypeNullability`) which has been corrected.

## v5.11.0
- *Enhancement:* Added `dotnet new beef ... --services AzFunction` to enable the templating of a corresponding `Company.AppName.Services` project as an Azure Functions project. This will provide an example of leveraging the shared `Company.AppName.Business` logic and consuming the published events using an `EventSubscriberOrchestrator`.
- *Enhancement:* The `DatabaseMapper` (stored procedures) code-generation logic has been updated to leverage the new extended `DatabaseMapperEx`. This avoids the existing reflection and expression compilation, using explicit code to perform the mapping. Can offer up to 40%+ improvement in some scenarios. Where existing behavior is required then set YAML `databaseMapperEx: false` in the `entity.beef-5.yaml` file (root and/or entity within hierarchy).
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>5.11.0</Version>
<Version>5.12.0</Version>
<LangVersion>preview</LangVersion>
<Authors>Avanade</Authors>
<Company>Avanade</Company>
Expand Down
1 change: 1 addition & 0 deletions docs/Entity-CodeGeneration-Config.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ Property | Description
`webApiAuthorize` | The authorize attribute value to be used for the corresponding entity Web API controller; generally either `Authorize` or `AllowAnonymous`.<br/>&dagger; This can be overridden within the `Entity`(s) and/or their corresponding `Operation`(s).
`webApiAutoLocation` | Indicates whether the HTTP Response Location Header route (`Operation.WebApiLocation`) is automatically inferred.<br/>&dagger; This will automatically set the `Operation.WebApiLocation` for an `Operation` named `Create` where there is a corresponding named `Get`. This can be overridden within the `Entity`(s).
**`webApiRoutePrefix`** | The base (prefix) `URI` prepended to all `Operation.WebApiRoute` values.
`webApiTags` | The list of tags to add for the generated `WebApi`.<br/>&dagger; This can be overridden within the `Entity`(s) and/or their corresponding `Operation`(s).

<br/>

Expand Down
1 change: 1 addition & 0 deletions docs/Entity-Entity-Config.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ Property | Description
`webApiAutoLocation` | Indicates whether the HTTP Response Location Header route (`Operation.WebApiLocation`) is automatically inferred.<br/>&dagger; This will automatically set the `Operation.WebApiLocation` for an `Operation` named `Create` where there is a corresponding named `Get`. This is defaulted from the `CodeGen.WebApiAutoLocation`.
`webApiConcurrency` | Indicates whether the Web API is responsible for managing (simulating) concurrency via auto-generated ETag.<br/>&dagger; This provides an alternative where the underlying data source does not natively support optimistic concurrency (native support should always be leveraged as a priority). Where the `Operation.Type` is `Update` or `Patch`, the request ETag will be matched against the response for a corresponding `Get` operation to verify no changes have been made prior to updating. For this to function correctly the .NET response Type for the `Get` must be the same as that returned from the corresponding `Create`, `Update` and `Patch` (where applicable) as the generated ETag is a SHA256 hash of the resulting JSON. This defaults the `Operation.WebApiConcurrency`.
`webApiGetOperation` | The corresponding `Get` method name (in the `XxxManager`) where the `Operation.Type` is `Update` and `SimulateConcurrency` is `true`.<br/>&dagger; Defaults to `Get`. Specify either just the method name (e.g. `OperationName`) or, interface and method name (e.g. `IXxxManager.OperationName`) to be invoked where in a different `YyyManager.OperationName`.
`webApiTags` | The list of tags to add for the generated `WebApi` controller.

<br/>

Expand Down
1 change: 1 addition & 0 deletions docs/Entity-Operation-Config.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ Property | Description
`webApiUpdateOperation` | The corresponding `Update` method name (in the `XxxManager`) where the `Operation.Type` is `Patch`.<br/>&dagger; Defaults to `Update`. Specify either just the method name (e.g. `OperationName`) or, interface and method name (e.g. `IXxxManager.OperationName`) to be invoked where in a different `YyyManager.OperationName`.
`webApiProduces` | The value(s) for the optional `[Produces()]` attribute for the operation within the Web Api Controller for the Swagger/OpenAPI documentation.
`webApiProducesResponseType` | The `[ProducesResponseType()]` attribute `typeof` for the operation within the Web Api Controller for the Swagger/OpenAPI documentation.<br/>&dagger; Defaults to the _Common_ type. A value of `None`, `none` or `` will ensure no type is emitted.
`webApiTags` | The list of tags to add for the generated `WebApi` operation.<br/>&dagger; Overrides the `Entity.WebApiTags`; unless, if the first tag value is a `^` then this indicates that the `Entity.WebApiTags` are to be included (inherited) as a replacement. Otherwise, defaults to `Entity.WebApiTags`.

<br/>

Expand Down
2 changes: 1 addition & 1 deletion samples/Cdr.Banking/Cdr.Banking.Api/Cdr.Banking.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<ImplicitUsings>true</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CoreEx.AspNetCore" Version="3.13.0" />
<PackageReference Include="CoreEx.AspNetCore" Version="3.14.1" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.5.0" />
</ItemGroup>
<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace Cdr.Banking.Api.Controllers;
/// <summary>
/// Provides the <see cref="Account"/> Web API functionality.
/// </summary>
[Tags("Banking")]
[Produces(System.Net.Mime.MediaTypeNames.Application.Json)]
public partial class AccountController : ControllerBase
{
Expand All @@ -30,6 +31,7 @@ public AccountController(WebApi webApi, IAccountManager manager)
/// <param name="openStatus">The Open Status (see <see cref="RefDataNamespace.OpenStatus"/>).</param>
/// <param name="isOwned">Indicates whether Is Owned.</param>
/// <returns>The <see cref="AccountCollection"/></returns>
[Tags("Banking", "Accounts")]
[HttpGet("api/v1/banking/accounts")]
[Paging]
[ProducesResponseType(typeof(Common.Entities.AccountCollection), (int)HttpStatusCode.OK)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
<Folder Include="DataSvc\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CoreEx.AspNetCore" Version="3.13.0" />
<PackageReference Include="CoreEx.Cosmos" Version="3.13.0" />
<PackageReference Include="CoreEx.Validation" Version="3.13.0" />
<PackageReference Include="CoreEx.AspNetCore" Version="3.14.1" />
<PackageReference Include="CoreEx.Cosmos" Version="3.14.1" />
<PackageReference Include="CoreEx.Validation" Version="3.14.1" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"profiles": {
"Cdr.Banking.CodeGen": {
"commandName": "Project",
"commandLineArgs": "all"
"commandLineArgs": "endpoints"
}
}
}
4 changes: 2 additions & 2 deletions samples/Cdr.Banking/Cdr.Banking.CodeGen/entity.beef-5.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ entities:
# API route prefixed defined.
# Auto-implementing data access using Cosmos with Container 'Account', leveraging auto-mapping to a 'Model.Account'.
#
- { name: Account, text: Account, collection: true, collectionResult: true, webApiRoutePrefix: api/v1/banking/accounts, autoImplement: Cosmos, cosmosModel: Model.Account, cosmosContainerId: Accounts,
- { name: Account, text: Account, collection: true, collectionResult: true, webApiRoutePrefix: api/v1/banking/accounts, autoImplement: Cosmos, cosmosModel: Model.Account, cosmosContainerId: Accounts, webApiTags: [ Banking ],
properties: [
# Convention of Id property within entity.
# Reference as accountId otherwise (ArgumentName and JsonName).
Expand Down Expand Up @@ -32,7 +32,7 @@ entities:
# Supports paging.
# Data access will be auto-implemented for Cosmos as defined for the entity.
#
{ name: GetAccounts, text: Get all accounts, type: GetColl, paging: true,
{ name: GetAccounts, text: Get all accounts, type: GetColl, paging: true, webApiTags: [ ^, Accounts ],
parameters: [
{ name: Args, type: AccountArgs, validator: AccountArgsValidator }
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
<Folder Include="Entities\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CoreEx" Version="3.13.0" />
<PackageReference Include="CoreEx" Version="3.14.1" />
</ItemGroup>
</Project>
4 changes: 2 additions & 2 deletions samples/Cdr.Banking/Cdr.Banking.Test/Cdr.Banking.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NUnit.Analyzers" Version="4.0.1">
<PackageReference Include="NUnit.Analyzers" Version="4.1.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageReference Include="CoreEx.UnitTesting.NUnit" Version="3.13.0" />
<PackageReference Include="CoreEx.UnitTesting.NUnit" Version="3.14.1" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion samples/Demo/Beef.Demo.Api/Beef.Demo.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="CoreEx.AspNetCore" Version="3.13.0" />
<PackageReference Include="CoreEx.AspNetCore" Version="3.14.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.5.0" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace Beef.Demo.Api.Controllers;
/// <summary>
/// Provides the <see cref="Person"/> Web API functionality.
/// </summary>
[Tags("person", "bananas")]
[AllowAnonymous]
[Produces(System.Net.Mime.MediaTypeNames.Application.Json)]
public partial class PersonController : ControllerBase
Expand Down Expand Up @@ -107,6 +108,7 @@ public Task<IActionResult> Patch(Guid id)
/// Gets the <see cref="PersonCollectionResult"/> that contains the items that match the selection criteria.
/// </summary>
/// <returns>The <see cref="PersonCollection"/></returns>
[Tags("apples", "oranges")]
[HttpGet("api/v1/persons/all")]
[Paging]
[ProducesResponseType(typeof(Common.Entities.PersonCollection), (int)HttpStatusCode.OK)]
Expand Down Expand Up @@ -311,7 +313,7 @@ public Task<IActionResult> ThrowError()
[ProducesResponseType(typeof(string), (int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.NoContent)]
public Task<IActionResult> InvokeApiViaAgent(Guid id)
=> _webApi.PostAsync<string?>(Request, p => _manager.InvokeApiViaAgentAsync(id), alternateStatusCode: HttpStatusCode.NoContent, operationType: CoreEx.OperationType.Unspecified);
=> _webApi.PostAsync<string>(Request, p => _manager.InvokeApiViaAgentAsync(id), alternateStatusCode: HttpStatusCode.NoContent, operationType: CoreEx.OperationType.Unspecified);

/// <summary>
/// Param Coll.
Expand Down
16 changes: 8 additions & 8 deletions samples/Demo/Beef.Demo.Business/Beef.Demo.Business.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="CoreEx" Version="3.13.0" />
<PackageReference Include="CoreEx.AspNetCore" Version="3.13.0" />
<PackageReference Include="CoreEx.Cosmos" Version="3.13.0" />
<PackageReference Include="CoreEx.Database" Version="3.13.0" />
<PackageReference Include="CoreEx.Database.SqlServer" Version="3.13.0" />
<PackageReference Include="CoreEx.EntityFrameworkCore" Version="3.13.0" />
<PackageReference Include="CoreEx.Validation" Version="3.13.0" />
<PackageReference Include="CoreEx.FluentValidation" Version="3.13.0" />
<PackageReference Include="CoreEx" Version="3.14.1" />
<PackageReference Include="CoreEx.AspNetCore" Version="3.14.1" />
<PackageReference Include="CoreEx.Cosmos" Version="3.14.1" />
<PackageReference Include="CoreEx.Database" Version="3.14.1" />
<PackageReference Include="CoreEx.Database.SqlServer" Version="3.14.1" />
<PackageReference Include="CoreEx.EntityFrameworkCore" Version="3.14.1" />
<PackageReference Include="CoreEx.Validation" Version="3.14.1" />
<PackageReference Include="CoreEx.FluentValidation" Version="3.14.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.20" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ public partial interface IPersonData
/// </summary>
/// <param name="id">The <see cref="Person"/> identifier.</param>
/// <returns>A resultant <see cref="string"/>.</returns>
Task<string?> InvokeApiViaAgentAsync(Guid id);
Task<string> InvokeApiViaAgentAsync(Guid id);

/// <summary>
/// Gets the specified <see cref="Person"/>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ public Task<Person> UpdateAsync(Person value)
public Task ThrowErrorAsync() => ThrowErrorOnImplementationAsync();

/// <inheritdoc/>
public Task<string?> InvokeApiViaAgentAsync(Guid id) => InvokeApiViaAgentOnImplementationAsync(id);
public Task<string> InvokeApiViaAgentAsync(Guid id) => InvokeApiViaAgentOnImplementationAsync(id);

/// <inheritdoc/>
public Task<Person?> GetWithEfAsync(Guid id) => DataInvoker.Current.InvokeAsync(this, async (_, __) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ public static IServiceCollection AddGeneratedDataServices(this IServiceCollectio
{
return services.AddScoped<IPersonData, PersonData>()
.AddScoped<IRobotData, RobotData>()
.AddScoped<IContactData, ContactData>()
.AddScoped<IPostalInfoData, PostalInfoData>();
.AddScoped<IPostalInfoData, PostalInfoData>()
.AddScoped<IContactData, ContactData>();
}
}

Expand Down
5 changes: 1 addition & 4 deletions samples/Demo/Beef.Demo.Business/Data/ZippoAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ namespace Beef.Demo.Business.Data
public class ZippoAgent : TypedMappedHttpClientCore<ZippoAgent>
{
public ZippoAgent(HttpClient client, IMapper mapper, IJsonSerializer jsonSerializer, CoreEx.ExecutionContext executionContext, SettingsBase settings, ILogger<ZippoAgent> logger)
: base(client, mapper, jsonSerializer, executionContext, settings, logger)
{
DefaultOptions.WithRetry();
}
: base(client, mapper, jsonSerializer, executionContext, settings, logger) { }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public partial interface IPersonDataSvc
/// </summary>
/// <param name="id">The <see cref="Person"/> identifier.</param>
/// <returns>A resultant <see cref="string"/>.</returns>
Task<string?> InvokeApiViaAgentAsync(Guid id);
Task<string> InvokeApiViaAgentAsync(Guid id);

/// <summary>
/// Param Coll.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public partial class PersonDataSvc : IPersonDataSvc
private Func<Person?, string?, List<string>?, Task>? _getNullOnAfterAsync;
private Func<PersonCollectionResult, PersonArgs?, PagingArgs?, Task>? _getByArgsWithEfOnAfterAsync;
private Func<Task>? _throwErrorOnAfterAsync;
private Func<string?, Guid, Task>? _invokeApiViaAgentOnAfterAsync;
private Func<string, Guid, Task>? _invokeApiViaAgentOnAfterAsync;
private Func<Person?, Guid, Task>? _getWithEfOnAfterAsync;
private Func<Person, Task>? _createWithEfOnAfterAsync;
private Func<Person, Task>? _updateWithEfOnAfterAsync;
Expand Down Expand Up @@ -225,7 +225,7 @@ public async Task ThrowErrorAsync()
}

/// <inheritdoc/>
public async Task<string?> InvokeApiViaAgentAsync(Guid id)
public async Task<string> InvokeApiViaAgentAsync(Guid id)
{
var r = await _data.InvokeApiViaAgentAsync(id).ConfigureAwait(false);
await Invoker.InvokeAsync(_invokeApiViaAgentOnAfterAsync?.Invoke(r, id)).ConfigureAwait(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ public static IServiceCollection AddGeneratedDataSvcServices(this IServiceCollec
{
return services.AddScoped<IPersonDataSvc, PersonDataSvc>()
.AddScoped<IRobotDataSvc, RobotDataSvc>()
.AddScoped<IContactDataSvc, ContactDataSvc>()
.AddScoped<IPostalInfoDataSvc, PostalInfoDataSvc>();
.AddScoped<IPostalInfoDataSvc, PostalInfoDataSvc>()
.AddScoped<IContactDataSvc, ContactDataSvc>();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ public partial interface IPersonManager
/// </summary>
/// <param name="id">The <see cref="Person"/> identifier.</param>
/// <returns>A resultant <see cref="string"/>.</returns>
Task<string?> InvokeApiViaAgentAsync(Guid id);
Task<string> InvokeApiViaAgentAsync(Guid id);

/// <summary>
/// Param Coll.
Expand Down
4 changes: 2 additions & 2 deletions samples/Demo/Beef.Demo.Business/Generated/PersonManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public partial class PersonManager : IPersonManager
private Func<Guid, Task>? _invokeApiViaAgentOnPreValidateAsync;
private Action<MultiValidator, Guid>? _invokeApiViaAgentOnValidate;
private Func<Guid, Task>? _invokeApiViaAgentOnBeforeAsync;
private Func<string?, Guid, Task>? _invokeApiViaAgentOnAfterAsync;
private Func<string, Guid, Task>? _invokeApiViaAgentOnAfterAsync;

private Func<AddressCollection?, Task>? _paramCollOnPreValidateAsync;
private Action<MultiValidator, AddressCollection?>? _paramCollOnValidate;
Expand Down Expand Up @@ -510,7 +510,7 @@ await MultiValidator.Create()
}, new InvokerArgs { IncludeTransactionScope = true, OperationType = OperationType.Unspecified });

/// <inheritdoc/>
public Task<string?> InvokeApiViaAgentAsync(Guid id) => ManagerInvoker.Current.InvokeAsync(this, async (_, ct) =>
public Task<string> InvokeApiViaAgentAsync(Guid id) => ManagerInvoker.Current.InvokeAsync(this, async (_, ct) =>
{
Cleaner.CleanUp(id);
await Invoker.InvokeAsync(_invokeApiViaAgentOnPreValidateAsync?.Invoke(id)).ConfigureAwait(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ public static IServiceCollection AddGeneratedManagerServices(this IServiceCollec
{
return services.AddScoped<IPersonManager, PersonManager>()
.AddScoped<IRobotManager, RobotManager>()
.AddScoped<IContactManager, ContactManager>()
.AddScoped<IConfigManager, ConfigManager>()
.AddScoped<IPostalInfoManager, PostalInfoManager>();
.AddScoped<IPostalInfoManager, PostalInfoManager>()
.AddScoped<IContactManager, ContactManager>();
}
}

Expand Down
Loading
Loading