Closed rasert closed 2 years ago
Based on the stack trace, I think the swagger thing is a red herring.
Are you able to remove/comment-out the swagger middleware and confirm the issue still happens? This will help me to diagnose the issue. Thanks :)
Maybe it is not Swashbuckle. I removed it and I am still getting errors:
{"error":".ctor","stack":" at System.RuntimeMethodHandle.IsCAVisibleFromDecoratedType(QCallTypeHandle attrTypeHandle, RuntimeMethodHandleInternal attrCtor, QCallTypeHandle sourceTypeHandle, QCallModule sourceModule)\r\n at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(MetadataToken caCtorToken, MetadataImport& scope, RuntimeModule decoratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder
1& derivedAttributes, RuntimeType& attributeType, IRuntimeMethodInfo& ctorWithParameters, Boolean& isVarArg)\r\n at System.Reflection.CustomAttribute.AddCustomAttributes(ListBuilder
1& attributes, RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder1 derivedAttributes)\r\n at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeType type, RuntimeType caType, Boolean inherit)\r\n at System.Attribute.GetCustomAttributes(MemberInfo element, Type type, Boolean inherit)\r\n at System.Attribute.GetCustomAttribute(MemberInfo element, Type attributeType, Boolean inherit)\r\n at System.Reflection.CustomAttributeExtensions.GetCustomAttribute[T](MemberInfo element)\r\n at Saunter.Generation.AsyncApiDocumentProvider.<>c__DisplayClass3_0.<GetAsyncApiTypes>b__2(TypeInfo t)\r\n at System.Linq.Enumerable.WhereArrayIterator
1.MoveNext()\r\n at System.Collections.Generic.LargeArrayBuilder1.AddRange(IEnumerable
1 items)\r\n at System.Collections.Generic.SparseArrayBuilder1.ReserveOrAdd(IEnumerable
1 items)\r\n at System.Linq.Enumerable.SelectManySingleSelectorIterator`2.ToArray()\r\n at Saunter.Generation.AsyncApiDocumentProvider.GetAsyncApiTypes(AsyncApiOptions options, AsyncApiDocument prototype)\r\n at Saunter.Generation.AsyncApiDocumentProvider.GetDocument(AsyncApiOptions options, AsyncApiDocument prototype)\r\n at Saunter.AsyncApiMiddleware.Invoke(HttpContext context)\r\n at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)\r\n at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)\r\n at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)\r\n at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)\r\n at Integration.ProductsPrice.Middlewares.ExceptionHandlerMiddleware.Invoke(HttpContext context, IWebHostEnvironment environment) in C:\Users\jmourao\workspace\MotorPromocao\poc-eks-motor\src\Integration.ProductsPrice\Middlewares\ExceptionHandlerMiddleware.cs:line 56","innerError":null,"innerException":null}
My message-bus class, that has the Attributes (AsyncApi, Channel, PublishOperation), is in a different assembly that is referenced by the asp.net web api. Is it a problem?
Nope not a problem, you need to specify one of the types in The options.AssemblyMarkerTypes so the assembly is loaded though. What do you have in your startup.cs?
/// <summary>
/// This method gets called by the runtime. Use this method to add services to the container.
/// </summary>
/// <param name="services"></param>
public void ConfigureServices(IServiceCollection services)
{
services.AddRouting()
.AddLocalization()
.AddCors();
services.AddControllers()
.AddControllersAsServices()
.AddFluentValidation(options =>
{
options.RegisterValidatorsFromAssemblyContaining<DeltaValidator>();
options.RegisterValidatorsFromAssemblyContaining<NewPriceEventValidator>();
options.ImplicitlyValidateChildProperties = true;
})
.AddDapr(); // Register DaprClient on DI
services.ConfigureApplicationServices(Configuration);
services
.AddHealthChecks()
.AddCheck<GcamApiHealthCheck>("gcam", HealthStatus.Unhealthy)
.AddCheck<LinxDbHealthCheck>("linxdb", HealthStatus.Unhealthy);
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardLimit = 2;
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = "PriceBible",
Version = "v1"
});
});
// Add Saunter to the application services.
services.AddAsyncApiSchemaGeneration(options =>
{
// Specify example type(s) from assemblies to scan.
options.AssemblyMarkerTypes = new[] { typeof(NewPriceMessageBus) };
// Build as much (or as little) of the AsyncApi document as you like.
// Saunter will generate Channels, Operations, Messages, etc, but you
// may want to specify Info here.
options.AsyncApi = new AsyncApiDocument
{
Info = new Info("NewPrice API", "1.0.0")
{
Description = "NewPrice API - Tells when products received new prices.",
License = new License("Apache 2.0")
{
Url = "https://www.apache.org/licenses/LICENSE-2.0"
}
},
Servers =
{
{ "my-rabbit-server", new Server("rabbitmq.local.com", "amqp") }
}
};
});
}
/// <summary>
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
/// </summary>
/// <param name="builder"></param>
public void Configure(IApplicationBuilder builder)
{
builder.UseForwardedHeaders();
builder.UseMiddleware<ExceptionHandlerMiddleware>();
builder.UseRouting();
builder.UseCloudEvents(); // For Dapr Pub/Sub
builder.UseRequestLocalization();
builder.UseCors();
builder.UseAuthentication();
builder.UseAuthorization();
builder.UseSwagger();
builder.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("v1/swagger.json", "PriceBible");
});
builder.UseEndpoints(endpoint =>
{
endpoint.MapHealthChecks("api/health", new HealthCheckOptions
{
ResponseWriter = WriteHealthCheckResponse
});
endpoint.MapControllers();
endpoint.MapSubscribeHandler(); // For Dapr Pub/Sub
endpoint.MapAsyncApiDocuments();
endpoint.MapAsyncApiUi();
});
}
That looks fine. Still trying to understand what has happened...
NewPriceMessageBus
assembly? Maybe using record types or something...?The code that is failing from Saunter's side is this
private static TypeInfo[] GetAsyncApiTypes(AsyncApiOptions options, AsyncApiDocument prototype)
{
var assembliesToScan = options.AssemblyMarkerTypes.Select(t => t.Assembly);
var asyncApiTypes = assembliesToScan
.SelectMany(a => a.DefinedTypes.Where(t => t.GetCustomAttribute<AsyncApiAttribute>()?.DocumentName == prototype.DocumentName))
.ToArray();
return asyncApiTypes;
}
Which is really not doing anything special... We're listing all the types in that Assembly, then calling Type.GetCustomAttribute<AsyncApiAttribute>()
which I can't see why that would fail. That's why I'm guessing there is something strange about that assembly.
Hi just checking in if you managed to resolve your issue, or if there is anything else I can do to help? Thanks
Closing due to inactivity. Feel free to re-open this issue if required.
When getting the "/asyncapi/asyncapi.json" endpoint, I am getting an error. It seems some kind of conflict with Swashbuckle that is installed too.
Saunter v0.7.1 .Net 5 Swashbuckle v6.1.4
This is the response: