neuroglia-io / asyncapi Goto Github PK
View Code? Open in Web Editor NEWA .NET SDK for the Async API specification
Home Page: https://www.asyncapi.com/
License: Apache License 2.0
A .NET SDK for the Async API specification
Home Page: https://www.asyncapi.com/
License: Apache License 2.0
Serialization of List / Arrays not working
Steps to reproduce the behavior:
i try to serialize next model
public class ActivityCreateModel
{
public Guid Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string ActivityType { get; set; }
public DateTime ActivityTime { get; set; }
public Guid? CompanyId { get; set; }
public string Shortcut { get; set; }
public Guid UserInformationId { get; set; }
public Guid? CreatorId { get; set; }
public IList< ActivityPropertyViewModel > Properties { get; set; }
}
Prepared AsyncApi document
Unhandled exception. System.InvalidOperationException: Sequence contains no elements at System.Linq.ThrowHelper.ThrowNoElementsException() at Neuroglia.AsyncApi.JsonSchemaExtensions.GenerateExampleArrayFor(JsonSchema schema, Boolean requiredPropertiesOnly) at Neuroglia.AsyncApi.JsonSchemaExtensions.GenerateExample(JsonSchema schema, String name, Boolean requiredPropertiesOnly) at Neuroglia.AsyncApi.JsonSchemaExtensions.GenerateExampleObjectFor(JsonSchema schema, Boolean requiredPropertiesOnly) at Neuroglia.AsyncApi.JsonSchemaExtensions.GenerateExample(JsonSchema schema, String name, Boolean requiredPropertiesOnly) at Neuroglia.AsyncApi.JsonSchemaExtensions.GenerateExamples(JsonSchema schema) at Neuroglia.AsyncApi.Services.Generators.AsyncApiDocumentGenerator.ConfigureOperationMessageFor(IMessageDefinitionBuilder messageBuilder, OperationAttribute operation, MethodInfo operationMethod, AsyncApiDocumentGenerationOptions options) at Neuroglia.AsyncApi.Services.Generators.AsyncApiDocumentGenerator.<>c__DisplayClass7_1.<ConfigureChannelForAsync>b__2(IMessageDefinitionBuilder messageBuilder) at Neuroglia.AsyncApi.Services.FluentBuilders.OperationDefinitionBuilder.UseMessage(Action
1 setup)
at Neuroglia.AsyncApi.Services.Generators.AsyncApiDocumentGenerator.<>c__DisplayClass7_1.b__1(IOperationDefinitionBuilder operationBuilder)
at Neuroglia.AsyncApi.Services.FluentBuilders.ChannelDefinitionBuilder.DefineOperation(OperationType type, Action1 setup) at Neuroglia.AsyncApi.Services.Generators.AsyncApiDocumentGenerator.<>c__DisplayClass7_0.<ConfigureChannelForAsync>b__0(IChannelDefinitionBuilder channelBuilder) at Neuroglia.AsyncApi.Services.FluentBuilders.AsyncApiDocumentBuilder.UseChannel(String name, Action
1 setup)
at Neuroglia.AsyncApi.Services.Generators.AsyncApiDocumentGenerator.ConfigureChannelForAsync(IAsyncApiDocumentBuilder builder, ChannelAttribute channel, List1 methods, AsyncApiDocumentGenerationOptions options, CancellationToken cancellationToken) at Neuroglia.AsyncApi.Services.Generators.AsyncApiDocumentGenerator.GenerateDocumentForAsync(Type type, AsyncApiDocumentGenerationOptions options, CancellationToken cancellationToken) at Neuroglia.AsyncApi.Services.Generators.AsyncApiDocumentGenerator.GenerateAsync(IEnumerable
1 markupTypes, AsyncApiDocumentGenerationOptions options)
at Neuroglia.AsyncApi.Services.AsyncApiDocumentProvider.ExecuteAsync(CancellationToken stoppingToken)
at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host)
`
Hi, I'm trying to use the package to render UI for my service, but I'm having troubles with code-first document generation. Some of the issues I'm facing are:
PublishOperation
and SubscribeOperation
(this makes sense for example for WS service, where you use same websocket connection for messaging in both directions).But I really like the UI that Neuroglia.AsyncApi provides!
So I'd like to be able to provide the documents for UI manually, e.g. using Building an AsyncAPI Document API.
Is it possible? Does it make sense at all?
Set the PathPrefix
when configuring AsyncAPI document generation, like so:
...
services.AddAsyncApiGeneration(options =>
{
options
.WithMarkupType<WeatherForecastController>()
//.UsePathPrefix("/") Unquoting this line break the middleware
.UseDefaultConfiguration(asyncapi =>
{
asyncapi.UseServer("WebSocket", server => server
.WithUrl(new Uri("http://127.0.0.1:8081/ws/weather"))
.WithProtocol(AsyncApiProtocols.Ws)
.UseBinding(new WsServerBinding())
);
});
});
...
Documents are served with the configured path prefix
Fix the way the PathPrefix
is used to allow both url document discovery and customized document urls
Create a new service with a method, with a single value type parameter, decorated with the operation attribute.
The generator either skips the generation of examples for value type arguments, thus failing silently, or, better, generates examples for value types, too
Hey @cdavernas , I finally pinpointed the issue I was struggling in my other project, which was the reason behind #3
I've managed to reproduce, with the same project you've already seen, i've just removed swagger and the PathPrefix that will get addressed in #5 but changing the target SDK
See latest commit smarek/signalr-asyncapi-example@975c64e#diff-baf4e63ed3f9283edfde3518c8b1f4acb9ada87dd874db4e67fb1071a2239fd2R1
With this SDK target routes for individual spec documents work, but the default route for UI does not.
Could you please take a look, and let me know, if you can/will support this SDK target or mention in documentation that Microsoft.NET.Sdk.Web is required? Thank you!
The current version of Neuroglia.AsyncApi.Generation creates an asyncApi specification with 'asyncApi' field name in camelCase.
Specification says:
All field names in the specification are case sensitive.
Also in the specification 'asyncapi' field name is specified in lower-case.
This issue causes plug-ins and asyncApi viewers to be unable to open the specification file generated by the current solution.
Just generate an asyncApi by using Neuroglia.AsyncApi.Generation.
asyncapi field name specified in lower-case
asyncApi field name specified in camel-case
I'm not 100% if this is a bug, but when building a document, I found that when registering more than one Publisher in the same channel, it only renders the last one.
Knowing Kafka works on that pattern, where publishers publish different messages on the same topic, and consumers must identify the message type, this support was an assumption for me.
Steps to reproduce the behavior:
Add a Channel attribute named Test
and a PublishOperation attribute named Publish1
to a method.
On a second method, add a Channel named Test
and a PublishOperation named Publish2
to a second method.
It is expected to see two Pub methods, Publish1
and Publish2
, for the channel Test
.
Only the last method is rendered, Publish2
.
Support for code-first generation in Azure Function Apps. The implementation seems to rely on MVC middleware, which is not available in Azure Functions. Need a way to generate AsyncApi documents using the attributes in code and view in running app. I use event-driven architecture with Azure Functions, and I'm sure many others do the same. So is this possible in the package today? Or has it been thought of as an addition?
Tried Saunter and opened relevant ticket 152 and KsntServiceBus and opened relevant ticket 12
Opened question on StackOverflow for alternate suggestions
Hi, not sure, if it should be possible, but i've tried to use this project for documenting SignalR AspNet.Core WebSocket endpoints
in my existing net5.0 app, and looks like not everything necessary to test it is already published or finished?
Please let me know, if I should try harder or if my idea is completely incorrect. Thank you!
(1) Trying to run the sample app, i've had to add additional package dependency, otherwise it fails to run
cd src/Neuroglia.AsyncApi.Sdk
dotnet add package Neuroglia.Serialization.Abstractions
cd ../../samples/StreetLightsApi/Server
dotnet run
Otherwise you'll hit this issue
> dotnet run
Building...
Unhandled exception. System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Neuroglia.Serialization.ISerializerProvider Lifetime: Singleton ImplementationInstance: Neuroglia.Serialization.SerializerProvider': Constant value of type 'System.RuntimeType' can't be converted to service type 'Neuroglia.Serialization.ISerializerProvider')
---> System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: Neuroglia.Serialization.ISerializerProvider Lifetime: Singleton ImplementationInstance: Neuroglia.Serialization.SerializerProvider': Constant value of type 'System.RuntimeType' can't be converted to service type 'Neuroglia.Serialization.ISerializerProvider'
---> System.ArgumentException: Constant value of type 'System.RuntimeType' can't be converted to service type 'Neuroglia.Serialization.ISerializerProvider'
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ConstantCallSite..ctor(Type serviceType, Object defaultValue)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(ServiceDescriptor serviceDescriptor, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.ValidateService(ServiceDescriptor descriptor)
--- End of inner exception stack trace ---
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.ValidateService(ServiceDescriptor descriptor)
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable`1 serviceDescriptors, IServiceProviderEngine engine, ServiceProviderOptions options)
--- End of inner exception stack trace ---
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable`1 serviceDescriptors, IServiceProviderEngine engine, ServiceProviderOptions options)
at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
at Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory.CreateServiceProvider(IServiceCollection containerBuilder)
at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter`1.CreateServiceProvider(Object containerBuilder)
at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
at Microsoft.Extensions.Hosting.HostBuilder.Build()
at StreetLightsApi.Server.Program.Main(String[] args) in /home/user/Downloads/AsyncApi/samples/StreetLightsApi/Server/Program.cs:line 12
(2) I've tried to add the dependencies as listed to existing net5.0 application, and that seems quite impossible currently to me, because the necessary Neuroglia.AsyncApi.Sdk is not published on nuget yet and adding it as project reference, i'll hit hard-coded paths (assets, LICENSE) and even after fixing those, i'll hit this on access to /asyncapi
endpoint
IndexOutOfRangeException: Index was outside the bounds of the array.
Neuroglia.AsyncApi.Middlewares.AsyncApiGenerationMiddleware.InvokeAsync(HttpContext context)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
(3) I've also tried to reproduce the issue, and it seems quite easy with current GIT HEAD (431de7d) see:
> dotnet --info
.NET SDK (reflecting any global.json):
Version: 5.0.302
Commit: c005824e35
Runtime Environment:
OS Name: debian
OS Version: 11
OS Platform: Linux
RID: linux-x64
Base Path: /usr/share/dotnet/sdk/5.0.302/
Host (useful for support):
Version: 5.0.8
Commit: 35964c9215
.NET SDKs installed:
5.0.302 [/usr/share/dotnet/sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 5.0.8 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.28 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.8 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
To install additional .NET runtimes or SDKs:
https://aka.ms/dotnet-download
> pwd
/home/user/Downloads/AsyncApi/samples/StreetLightsApi/Server
> dotnet list package
Project 'StreetLightsApi.Server' has the following package references
[net5.0]:
Top-level Package Requested Resolved
> Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation 5.0.7 5.0.7
> MQTTnet 3.0.16 3.0.16
> Neuroglia.AspNetCore 2.0.0.7 2.0.0.7
> Neuroglia.AsyncApi.AspNetCore 2.1.0 2.1.0
> Neuroglia.AsyncApi.AspNetCore.UI 2.1.0.1 2.1.0.1
> Neuroglia.AsyncApi.Core 2.1.0.1 2.1.0.1
> Neuroglia.Core 2.0.0.7 2.0.0.7
> Neuroglia.Serialization.Abstractions 2.0.0.7 2.0.0.7
> dotnet list reference
There are no Project to Project references in project /home/user/Downloads/AsyncApi/samples/StreetLightsApi/Server
> dotnet run
Building...
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: /home/user/Downloads/AsyncApi/samples/StreetLightsApi/Server
info: StreetLightsApi.Server.Services.MovementDetectorService[0]
Movement detected by sensor with id '634' at 7/17/2021 7:55:52 PM
info: StreetLightsApi.Server.Services.StreetLightsService[0]
Event received:
{"Id":415,"Lumens":5,"SentAt":"2021-07-17T19:55:52.3950402Z"}
// accessing https://localhost:5001/asyncapi
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
System.EntryPointNotFoundException: Entry point was not found.
at System.Collections.Generic.IEnumerable`1.GetEnumerator()
at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Boolean& found)
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
at Neuroglia.AsyncApi.AspNetCore.UI.Pages.AsyncApiModel.OnGet(String title, String version)
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ExecutorFactory.VoidHandlerMethod.Execute(Object receiver, Object[] arguments)
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeHandlerMethodAsync()
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeNextPageFilterAsync()
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Rethrow(PageHandlerExecutedContext context)
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeInnerFilterAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Neuroglia.AsyncApi.Middlewares.AsyncApiGenerationMiddleware.InvokeAsync(HttpContext context)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
// accessing https://localhost:5001/asyncapi/
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at Neuroglia.AsyncApi.Middlewares.AsyncApiGenerationMiddleware.InvokeAsync(HttpContext context)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
info: Microsoft.Hosting.Lifetime[0]
Application is shutting down...
Does not serialize nested reference properties
I tryed to serialize any model with nested reference properties
nested reference properties has description
nested referenece type has None description
I think this is trouble with MaxDepth setting of JsonSerializer
Allow marking methods with multiple operation attributes.
You can have services that declares operations used for both PUB and SUB.
It would be possible to choose which classes should be included in the YML/Json generated file via a selector rather than attributes?
Applying the SDK's custom attributes on existing code makes really difficult the adoption of this framework. It would help to keep your code base agnostics from any external framework.
Not applicable
Add any other context or screenshots about the feature request here.
From
[Message(..)]
public class Event
{
}
To:
..
.UseMessage(message => message..., "namespace/anything else")
In our implementations, we need to be able to pass a CancellationToken
to the underlying publish SDK call, which requires an additional parameter on the method that gets annotated with the PublishOperation
/ SubscribeOperation
attributes. This additional parameter has no value for the AsyncAPI specification, but we can't instruct the generator to ignore this parameter.
I've tried annotating the parameter with the JsonExcludeAttribute
from the JsonSchema.Generation
package, but that can't be applied to method parameters.
In the generated output, the unwanted parameter (in this case 'cancellationToken') shows up as follows:
channels:
item/created:
publish:
operationId: onItemCreated
message:
payload:
type: object
properties:
itemCreatedEvent:
type: object
properties:
id:
type: string
format: uuid
description: Unique identifier of the item
readOnly: True
required:
- id
cancellationToken:
type: object
properties:
isCancellationRequested:
type: boolean
readOnly: True
canBeCanceled:
type: boolean
readOnly: True
waitHandle:
type: object
properties:
handle:
type: object
deprecated: True
safeWaitHandle:
type: object
properties:
isClosed:
type: boolean
readOnly: True
isInvalid:
type: boolean
readOnly: True
readOnly: True
required:
- itemCreatedEvent
- cancellationToken
When the parsing hits the "properties" of the first "object" in a schema it hthrows an exception.
I used the yaml example I got from the AsyncApi website that I supply in "Additional Info" below.
I created code in C# .Net Core 5 to parse it using AsyncApiDocumentReader.ReadAsync(..)
It should not fail, this AsyncApi yaml example is valid.
It fails on line 36 at the first "properties". If I delete everything from the first "properties" then it succeeds.
This is the error returned:
"Error: (Line: 36, Col: 7, Idx: 809) - (Line: 36, Col: 7, Idx: 809): Exception during deserialization"
Get the example here: https://www.asyncapi.com/blog/understanding-asyncapis
Or this is it:
asyncapi: 2.0.0
info:
title: Email Service
version: '1.0.0'
description: |
Sends emails upon certain events
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0
servers:
production:
url: mqtt://test.mosquitto.org
protocol: mqtt
description: Test MQTT broker
channels:
user/signedup:
publish:
operationId: onUserSignUp
message:
$ref : '#/components/messages/UserSignedUp'
components:
messages:
UserSignedUp:
name: userSignedUp
title: User signed up event
summary: Inform about a new user registration in the system
contentType: application/json
payload:
$ref: '#/components/schemas/userSignedUpPayload'
schemas:
userSignedUpPayload:
type: object
properties:
firstName:
type: string
description: "foo"
lastName:
type: string
description: "bar"
email:
type: string
format: email
description: "baz"
createdAt:
type: string
format: date-time
description: "foo"
Add a new operation using a single value type parameter to an AsyncApiDocument, and try serializing it to Yaml.
The AsyncApiDocument is correctly serialized.
The YamlDotNetSerializer fails to serialize the AsyncApiDocument
, because of the automatically generated example for the added operation.
As a matter of fact, when using a single value type parameter, the generated example is a simple JToken
, as opposed to being a JObject
.
Here's the exception thrown in such cases (reproduced by visiting https://localhost:44326/asyncapi/TemperatureSensorApi/1.0.0 on the solution's sample app) :
YamlException: (Line: 1, Col: 1, Idx: 0) - (Line: 1, Col: 1, Idx: 0): Expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, got MappingEnd
The exception is doubtlessly caused by the JTokenSerializer
I'd like to call UseAsyncApiGeneration()
on an IApplicationBuilder
, just like the readme says. However, there is no such extension method.
It seems it's now called MapAsyncApiDocuments
Steps to reproduce the behavior:
UseAsyncApiDocuments()
can't be found.Either UseAsyncApiGeneration
can be found again or the readme is updated.
The compiler is quite unhappy with me.
Would be useful to see an azure function
I see currently ampq is supported using the rabbitmq driver.
Even if asb uses ampq as communication protocol, i doubt i can use that driver to target an asb instance.
I noticed the YAML output indicates the AsyncAPI version used is version 2.6.0. Are there any plans for supporting version 3.0.0?
N/A
N/A
The repo link on the nuget packages is wrong
Steps to reproduce the behavior:
When you click on the repository link you are taken to the correct github repo
The wrong url has been set in the csproj's
N/a
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.