Skip to content

Commit

Permalink
v5.8.0 (#234)
Browse files Browse the repository at this point in the history
* New OnRamp with deprecated Newtonsoft.Json.

* IActionResult support.

* Fix RefData.yaml.

* Integrate CoreEx fix.

* Template version bump.
  • Loading branch information
chullybun authored Jan 7, 2024
1 parent add6bd9 commit 9cb3491
Show file tree
Hide file tree
Showing 89 changed files with 1,515 additions and 1,293 deletions.
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.8.0
- *Fixed:* Upgraded `CoreEx` (`v3.8.0`) to include all related fixes and improvements; `WebApi` class supports returning value of `IActionResult` as-is.
- *Enhancement:* Updated code-generation to support `IActionResult` return type for `WebApi` operations. The following `operation` YAML properties enable:
- New `webApiProduces: [ 'text/plain' ]` where the value is a `Produces` content type array (supports multiple) to override the default; for example `[Produces("text/plain")]`.
- New `webApiProducesResponseType: none` indicates that the resulting generated code does _not_ include the response type; for example `[ProducesResponseType((int)HttpStatusCode.OK)]`.

## v5.7.4
- *Fixed:* Upgraded `CoreEx` (`v3.7.2`) to include all related fixes and improvements; updated reference data code-generation template and samples as a result.

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.7.4</Version>
<Version>5.8.0</Version>
<LangVersion>preview</LangVersion>
<Authors>Avanade</Authors>
<Company>Avanade</Company>
Expand Down
4 changes: 3 additions & 1 deletion docs/Entity-Operation-Config.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Property | Description
**`name`** | The unique operation name. [Mandatory]
**`type`** | The type of operation that is to be code-generated. Valid options are: `Get`, `GetColl`, `Create`, `Update`, `Patch`, `Delete`, `Custom`.<br/>&dagger; Defaults to `Custom`.
`text` | The text for use in comments.<br/>&dagger; The `Text` will be defaulted for all the `Operation.Type` options with the exception of `Custom`. To create a `<see cref="XXX"/>` within use moustache shorthand (e.g. {{Xxx}}).
**`primaryKey`** | Indicates whether the properties marked as a primary key (`Property.PrimaryKey`) are to be used as the parameters.<br/>&dagger; This simplifies the specification of these properties versus having to declare each specifically.
**`primaryKey`** | Indicates whether the properties marked as a primary key (`Property.PrimaryKey`) are to be used as the parameters.<br/>&dagger; This simplifies the specification of these properties as parameters versus having to declare each specifically. Each of the parameters will also be set to be mandatory.
**`paging`** | Indicates whether a `PagingArgs` argument is to be added to the operation to enable (standardized) paging related logic.
`valueType` | The .NET value parameter `Type` for the operation.<br/>&dagger; Defaults to the parent `Entity.Name` where the `Operation.Type` options are `Create` or `Update`.
`returnType` | The .NET return `Type` for the operation.<br/>&dagger; Defaults to the parent `Entity.Name` where the `Operation.Type` options are `Get`, `GetColl`, `Create` or `Update`; otherwise, defaults to `void`.
Expand Down Expand Up @@ -112,6 +112,8 @@ Property | Description
`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. Defaults to `Entity.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`.
`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.

<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.7.2" />
<PackageReference Include="CoreEx.AspNetCore" Version="3.8.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 @@ -61,4 +61,16 @@ public Task<IActionResult> GetDetail(string? accountId)
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public Task<IActionResult> GetBalance(string? accountId)
=> _webApi.GetWithResultAsync<Balance?>(Request, p => _manager.GetBalanceAsync(accountId));

/// <summary>
/// Get <see cref="Account"/> statement (file).
/// </summary>
/// <param name="accountId">The <see cref="Account"/> identifier.</param>
/// <returns>A resultant <see cref="FileContentResult"/>.</returns>
[HttpGet("api/v1/banking/accounts/{accountId}/statement")]
[Produces("text/plain")]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.NoContent)]
public Task<IActionResult> GetStatement(string? accountId)
=> _webApi.GetWithResultAsync<FileContentResult?>(Request, p => _manager.GetStatementAsync(accountId), alternateStatusCode: HttpStatusCode.NoContent, operationType: CoreEx.OperationType.Unspecified);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
<Folder Include="DataSvc\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CoreEx.Cosmos" Version="3.7.2" />
<PackageReference Include="CoreEx.Validation" Version="3.7.2" />
<PackageReference Include="CoreEx.AspNetCore" Version="3.8.1" />
<PackageReference Include="CoreEx.Cosmos" Version="3.8.1" />
<PackageReference Include="CoreEx.Validation" Version="3.8.1" />
</ItemGroup>
</Project>
8 changes: 8 additions & 0 deletions samples/Cdr.Banking/Cdr.Banking.Business/Data/AccountData.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Azure.Cosmos.Linq;
using System.Text;

namespace Cdr.Banking.Business.Data;

Expand Down Expand Up @@ -48,4 +49,11 @@ partial void AccountDataCtor()
return bal.Adjust(b => b.Id = a.Id);
});
}

/// <summary>
/// Gets the statement (file) for the specified account.
/// </summary>
private Task<Result<FileContentResult?>> GetStatementOnImplementationAsync(string? accountId)
=> Result.GoAsync(GetDetailAsync(accountId))
.WhenAs(d => d is not null, d => new FileContentResult(Encoding.UTF8.GetBytes($"Statement for Account '{d.AccountNumber}'."), "text/plain") { FileDownloadName = $"{accountId}.statement.txt" });
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ public Task<Result<AccountCollectionResult>> GetAccountsAsync(AccountArgs? args,
/// <inheritdoc/>
public Task<Result<Balance?>> GetBalanceAsync(string? accountId) => GetBalanceOnImplementationAsync(accountId);

/// <inheritdoc/>
public Task<Result<FileContentResult?>> GetStatementAsync(string? accountId) => GetStatementOnImplementationAsync(accountId);

/// <summary>
/// Provides the <see cref="Account"/> to Entity Framework <see cref="Model.Account"/> mapping.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,11 @@ public partial interface IAccountData
/// <param name="accountId">The <see cref="Account"/> identifier.</param>
/// <returns>The selected <see cref="Balance"/> where found.</returns>
Task<Result<Balance?>> GetBalanceAsync(string? accountId);

/// <summary>
/// Get <see cref="Account"/> statement (file).
/// </summary>
/// <param name="accountId">The <see cref="Account"/> identifier.</param>
/// <returns>A resultant <see cref="FileContentResult"/>.</returns>
Task<Result<FileContentResult?>> GetStatementAsync(string? accountId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,7 @@ public AccountDataSvc(IAccountData data, IRequestCache cache)

/// <inheritdoc/>
public Task<Result<Balance?>> GetBalanceAsync(string? accountId) => Result.Go().CacheGetOrAddAsync(_cache, accountId, () => _data.GetBalanceAsync(accountId));

/// <inheritdoc/>
public Task<Result<FileContentResult?>> GetStatementAsync(string? accountId) => _data.GetStatementAsync(accountId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,11 @@ public partial interface IAccountDataSvc
/// <param name="accountId">The <see cref="Account"/> identifier.</param>
/// <returns>The selected <see cref="Balance"/> where found.</returns>
Task<Result<Balance?>> GetBalanceAsync(string? accountId);

/// <summary>
/// Get <see cref="Account"/> statement (file).
/// </summary>
/// <param name="accountId">The <see cref="Account"/> identifier.</param>
/// <returns>A resultant <see cref="FileContentResult"/>.</returns>
Task<Result<FileContentResult?>> GetStatementAsync(string? accountId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,11 @@ public Task<Result<AccountCollectionResult>> GetAccountsAsync(AccountArgs? args,
return Result.Go().Requires(accountId)
.ThenAsAsync(() => _dataService.GetBalanceAsync(accountId));
}, InvokerArgs.Read);

/// <inheritdoc/>
public Task<Result<FileContentResult?>> GetStatementAsync(string? accountId) => ManagerInvoker.Current.InvokeAsync(this, (_, ct) =>
{
return Result.Go().Requires(accountId)
.ThenAsAsync(() => _dataService.GetStatementAsync(accountId));
}, InvokerArgs.Unspecified);
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,11 @@ public partial interface IAccountManager
/// <param name="accountId">The <see cref="Account"/> identifier.</param>
/// <returns>The selected <see cref="Balance"/> where found.</returns>
Task<Result<Balance?>> GetBalanceAsync(string? accountId);

/// <summary>
/// Get <see cref="Account"/> statement (file).
/// </summary>
/// <param name="accountId">The <see cref="Account"/> identifier.</param>
/// <returns>A resultant <see cref="FileContentResult"/>.</returns>
Task<Result<FileContentResult?>> GetStatementAsync(string? accountId);
}
1 change: 1 addition & 0 deletions samples/Cdr.Banking/Cdr.Banking.Business/GlobalUsings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
global using CoreEx.Results;
global using CoreEx.Validation;
global using CoreEx.Validation.Rules;
global using Microsoft.AspNetCore.Mvc;
global using Microsoft.Extensions.Configuration;
global using Microsoft.Extensions.Logging;
global using System;
Expand Down
10 changes: 9 additions & 1 deletion samples/Cdr.Banking/Cdr.Banking.CodeGen/entity.beef-5.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,15 @@ entities:
# Route requires accountId; e.g. api/v1/banking/accounts/{accountId}/balance
# Data access logic cannot be auto-implemented.
#
{ name: GetBalance, text: 'Get {{Account}} {{Balance}}', type: Get, returnType: Balance, webApiRoute: '{accountId}/balance', primaryKey: true, autoImplement: None }
{ name: GetBalance, text: 'Get {{Account}} {{Balance}}', type: Get, returnType: Balance, webApiRoute: '{accountId}/balance', primaryKey: true, autoImplement: None },
# Operation to get an Account statement _file_.
# Operation is 'Custom' to specifically override and manually implement data.
# ReturnType of FileContentResult (standard ASP.NET) is an IActionResult which will be returned as-is.
# PrimaryKey="true" indicates that all properties marked as PrimaryKey are to be used for parameters (avoids having to explicitly define again).
# WebApiProducesResponseType="none" indicates that the [ProducesResponseType()] attribute should not include the response type (also ensures that the Agent code does not include response type).
# WebApiProduces enables specification of the [Produces()] attribute and corresponding value(s) array.
#
{ name: GetStatement, text: 'Get {{Account}} statement (file)', type: Custom, primaryKey: true, returnType: FileContentResult?, webApiMethod: HttpGet, webApiRoute: '{accountId}/statement', webApiProducesResponseType: none, webApiProduces: [ text/plain ] }
]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,9 @@ public Task<HttpResult<AccountCollectionResult>> GetAccountsAsync(AccountArgs? a
/// <inheritdoc/>
public Task<HttpResult<Balance?>> GetBalanceAsync(string? accountId, HttpRequestOptions? requestOptions = null, CancellationToken cancellationToken = default)
=> GetAsync<Balance?>("api/v1/banking/accounts/{accountId}/balance", requestOptions: requestOptions, args: HttpArgs.Create(new HttpArg<string?>("accountId", accountId)), cancellationToken: cancellationToken);

/// <inheritdoc/>
public Task<HttpResult> GetStatementAsync(string? accountId, HttpRequestOptions? requestOptions = null, CancellationToken cancellationToken = default)
=> GetAsync("api/v1/banking/accounts/{accountId}/statement", requestOptions: requestOptions, args: HttpArgs.Create(new HttpArg<string?>("accountId", accountId)), cancellationToken: cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,14 @@ public partial interface IAccountAgent
/// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
/// <returns>A <see cref="HttpResult"/>.</returns>
Task<HttpResult<Balance?>> GetBalanceAsync(string? accountId, HttpRequestOptions? requestOptions = null, CancellationToken cancellationToken = default);

/// <summary>
/// Get <see cref="Account"/> statement (file).
/// </summary>
/// <param name="accountId">The <see cref="Account"/> identifier.</param>
/// <param name="requestOptions">The optional <see cref="HttpRequestOptions"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
/// <returns>A <see cref="HttpResult"/>.</returns>
Task<HttpResult> GetStatementAsync(string? accountId, HttpRequestOptions? requestOptions = null, CancellationToken cancellationToken = default);
}
}
Loading

0 comments on commit 9cb3491

Please sign in to comment.