facilityapi / facilitycsharp Goto Github PK
View Code? Open in Web Editor NEWC# support for the Facility API Framework.
Home Page: https://facilityapi.github.io/generate/csharp
License: MIT License
C# support for the Facility API Framework.
Home Page: https://facilityapi.github.io/generate/csharp
License: MIT License
Newtonsoft.Json doesn't support async serialization, but System.Text.Json does.
We should probably try to support some/all of what OpenAPI supports. But it's hard for me to get excited about adding that level of complexity to all code generators. Even "simple" CSV gets complicated when deciding how to encode a comma.
Public const string values for enums would enable the use of switch expressions when mapping or doing other handling.
Current mapping code is one of:
if (source == ApiTaskStatus.Unclaimed)
return TaskStatus.Unclaimed;
if (source == ApiTaskStatus.Pending)
return TaskStatus.Pending;
if (source == ApiTaskStatus.Completed)
return TaskStatus.Completed;
if (source == ApiTaskStatus.Rejected)
return TaskStatus.Rejected;
throw new InvalidOperationException($"Unhandled task status: {source}");
or:
source switch
{
_ when source == ApiTaskStatus.Unclaimed => TaskStatus.Unclaimed,
_ when source == ApiTaskStatus.Pending => TaskStatus.Pending,
_ when source == ApiTaskStatus.Completed => TaskStatus.Completed,
_ when source == ApiTaskStatus.Rejected => TaskStatus.Rejected,
_ => throw new InvalidOperationException($"Unhandled task status: {source}"),
}
Desired mapping code:
source switch
{
ApiTaskStatus.Unclaimed => TaskStatus.Unclaimed,
ApiTaskStatus.Pending => TaskStatus.Pending,
ApiTaskStatus.Completed => TaskStatus.Completed,
ApiTaskStatus.Rejected => TaskStatus.Rejected,
_ => throw new InvalidOperationException($"Unhandled task status: {source}"),
}
We should have a standard way to validate DTO properties, e.g. via a Validate
method that returns a ServiceResult
, perhaps. To start with, it would respect the required
attribute, but it could potentially support more advanced validation in the future.
FacilityApi/Facility#27 adds [validate(...)]
as a mechanism for specifying validation criteria for use in code generation. Generated code should include this validation criteria.
The implementation of server-sent events should use the SSE standard, at least for the JSON serializers, returning IAsyncEnumerable<T>
from the corresponding interface method. SSE doesn't support binary, but we could come up with something similar for MessagePack, e.g. a sequence of length-prefixed binary blobs.
Given the following example, two files called CreateWidgetRequestDto.g.cs
are created. I observed this using the web editor. Fsdgencsharp just creates one of the files, and the resulting code does not function.
There should be an error when a data object has the suffix Request
(or Response
).
/// Example service for widgets.
[http(url: "http://local.example.com/v1")]
[csharp(namespace: Facility.ExampleApi)]
service ExampleApi
{
/// Creates a new widget.
[http(method: POST, path: "/widgets/", code: 201)]
method createWidget
{
/// The widget to create.
[http(from: body)]
widget: CreateWidgetRequest;
}:
{
/// The created widget.
[http(from: body)]
widget: Widget;
}
/// A widget creation request.
data CreateWidgetRequest
{
/// The weight of the widget.
name: string;
}
/// A widget.
data Widget
{
/// A unique identifier for the widget.
id: string;
/// The name of the widget.
name: string;
/// The weight of the widget.
[obsolete]
weight: double;
}
}
Adding a comment tag to the beginning of *.g.cs files should make StyleCop ignore them.
// <auto-generated />
One user experienced an AggregateException
wrapping an ObjectDisposedException
on Mono.
We're trying to only catch exceptions that could be caused by I/O failure, but that's not easy to predict.
Rather than having a bunch of concrete aspect types, we should hide those types (or obsolete the ones we already have) and use Create
methods on CommonXyzAspects
static classes.
Testing validation is more difficult than it should be. The service interface (e.g. IMyApi
) is designed to be testable without transport concerns, but validation happens in the transport layer mapping—a step before the service, like IMyApi
is invoked.
Providing a standard delegator that does validation will make testing generated validation code easier by avoiding transport layer mapping.
A common recurring issue I've run into when writing unit tests for generated services
public async Task GetUserSucceeds()
{
var service = await Service.GetUser();
// ... verify the result is as expected ...
}
[Required]
and other properties consumers can add.Writing n
integration tests does not scale well, as integration tests are generally slow and costly. It would be nice to be able to have these checks done in unit tests, if wanted.
Unrelated aside: FacilityApi is an impressive piece of engineering, and has greatly improved velocity for many projects I've worked on.
FsdGenCSharp(File, Directory, FsdGenCSharpSettings);
Synchronous I/O has been disabled by default since netcore 3.0. Apparently it has been a source of thread starvation. dotnet/docs#14835
Ultimately, I'd like to remove the following code from my project:
services.Configure<KestrelServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
services.Configure<IISServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
This could be a breaking change to older client code for the same API, so it might need to be opt-in.
See internal FacilityActionFilter class (based on Microsoft.AspNetCore.Mvc.WebApiCompatShim) for details.
A related issue on the core project: FacilityApi/Facility#24
The Faithlife app employs the Kotlin and Swift programming languages on Android and iOS respectively. The code generator used to generate client code respects the [required]
attribute to make use of the languages' type systems that model nullability. Currently, the C# code generator used to generate BFF code for the apps still outputs nullable value types (pre C# 8) even if the [required]
attribute is specified, weakening the contract between client and server by making it more of a convention in this case.
With C# 8's more extensive null modeling in its type system, it could be even more useful.
It could be used with https://github.com/FacilityApi/FacilityLanguageServer to report misuse.
Path, query, and header fields should support all string-like types, including comma-delimited arrays of string-like types.
We could define a struct DtoField<T>
with a Boolean HasValue
(false if missing) and a nullable Value
(null if explicitly null).
We should look into whether we can/should replace Json.NET with System.Text.Json.
So that generated enum
code doesn't give a warning/error for missing XML docs in StyleCop.
Currently [http(method: PATCH, path: "/foo")]
generates a mapping like:
public static readonly HttpMethodMapping<FooRequestDto, FooResponseDto> FooMapping =
new HttpMethodMapping<FooRequestDto, FooResponseDto>.Builder
{
HttpMethod = HttpMethod.Patch,
Path = "/foo",
ResponseMappings =
{
new HttpResponseMapping<FooResponseDto>.Builder
{
StatusCode = (HttpStatusCode) 200,
}.Build(),
},
}.Build();
HttpMethod.Patch
isn't available in netstandard as of netstandard 2.0. So this code breaks in that environment.
An alternative would be to use the constructor that accepts a string parameter instead of the static constants. i.e. new HttpMethod("PATCH")
here.
To avoid Synchronous operations are disallowed.
from ASP.NET Core.
Specifying the --csproj
option with an SDK-style csproj succeeds, but corrupts the file by adding <Compile />
elements at the end of the file.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Facility.Core" Version="1.3.6" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
</ItemGroup>
</Project>
<Compile Include="MyDto.g.cs" />
<Compile Include="IServiceApi.g.cs" />
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.