data-api-builder icon indicating copy to clipboard operation
data-api-builder copied to clipboard

[Bug]: System.NotSupportedException: Specified method is not supported [GraphQL]

Open Kennedine opened this issue 1 year ago • 4 comments

What happened?

First I ran into that I could not have an entity named Query as that clashed with HotChocolate and was already registered. After changing Query to QueryEntity I run into this error when using GraphQL, REST works fine

When trying to use the GraphQL endpoint I get this error: DAB GraphQL error

I expected to get a 200 OK response.

Version

Happens on multiple versions, this is 0.13.0-rc

What database are you using?

Azure SQL

What hosting model are you using?

Container Apps

Which API approach are you accessing DAB through?

REST, GraphQL

Relevant log output

fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HN3EHLT5ACMT", Request id "0HN3EHLT5ACMT:00000002": An unhandled exception was thrown by the application.
      System.NotSupportedException: Specified method is not supported.
         at ResolverTypeInterceptor.OnBeforeCompleteType(ITypeCompletionContext completionContext, DefinitionBase definition, IDictionary`2 contextData) in /_/src/Core/Services/ResolverTypeInterceptor.cs:line 67
         at HotChocolate.Configuration.AggregateTypeInterceptor.OnBeforeCompleteType(ITypeCompletionContext completionContext, DefinitionBase definition, IDictionary`2 contextData)
         at HotChocolate.Types.TypeSystemObjectBase`1.OnBeforeCompleteType(ITypeCompletionContext context, DefinitionBase definition, IDictionary`2 contextData)
         at HotChocolate.Types.TypeSystemObjectBase`1.CompleteType(ITypeCompletionContext context)
         at HotChocolate.Configuration.TypeInitializer.<CompleteTypes>g__CompleteType|27_0(RegisteredType registeredType)
         at HotChocolate.Configuration.TypeInitializer.ProcessTypes(TypeDependencyKind kind, Func`2 action)
         at HotChocolate.Configuration.TypeInitializer.CompleteTypes()
         at HotChocolate.Configuration.TypeInitializer.Initialize()
         at HotChocolate.SchemaBuilder.Setup.InitializeTypes(SchemaBuilder builder, IDescriptorContext context, IReadOnlyList`1 types, LazySchema lazySchema)
         at HotChocolate.SchemaBuilder.Setup.Create(SchemaBuilder builder, LazySchema lazySchema, IDescriptorContext context)
         at HotChocolate.SchemaBuilder.Create(IDescriptorContext context)
         at HotChocolate.SchemaBuilder.HotChocolate.ISchemaBuilder.Create(IDescriptorContext context)
         at HotChocolate.Execution.RequestExecutorResolver.CreateSchemaAsync(NameString schemaName, RequestExecutorSetup options, RequestExecutorOptions executorOptions, IServiceProvider serviceProvider, TypeModuleChangeMonitor typeModuleChangeMonitor, CancellationToken cancellationToken)
         at HotChocolate.Execution.RequestExecutorResolver.CreateSchemaServicesAsync(NameString schemaName, RequestExecutorSetup options, CancellationToken cancellationToken)
         at HotChocolate.Execution.RequestExecutorResolver.GetRequestExecutorNoLockAsync(NameString schemaName, CancellationToken cancellationToken)
         at HotChocolate.Execution.RequestExecutorResolver.GetRequestExecutorAsync(NameString schemaName, CancellationToken cancellationToken)
         at HotChocolate.Execution.RequestExecutorProxy.GetRequestExecutorAsync(CancellationToken cancellationToken)
         at HotChocolate.AspNetCore.HttpPostMiddlewareBase.HandleRequestAsync(HttpContext context, AllowedContentType contentType)
         at HotChocolate.AspNetCore.HttpPostMiddlewareBase.InvokeAsync(HttpContext context)
         at Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions.<>c__DisplayClass12_0.<<UseCancellation>b__1>d.MoveNext()
      --- End of stack trace from previous location ---
         at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
         at Azure.DataApiBuilder.Core.Authorization.ClientRoleHeaderAuthorizationMiddleware.Invoke(HttpContext httpContext) in /_/src/Core/Authorization/ClientRoleHeaderAuthorizationMiddleware.cs:line 35
         at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
         at Azure.DataApiBuilder.Core.AuthenticationHelpers.ClientRoleHeaderAuthenticationMiddleware.InvokeAsync(HttpContext httpContext) in /_/src/Core/AuthenticationHelpers/ClientRoleHeaderAuthenticationMiddleware.cs:line 139
         at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
         at Azure.DataApiBuilder.Service.Startup.<>c__DisplayClass15_0.<<Configure>b__3>d.MoveNext() in /_/src/Service/Startup.cs:line 334
      --- End of stack trace from previous location ---
         at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
         at Azure.DataApiBuilder.Core.Services.PathRewriteMiddleware.InvokeAsync(HttpContext httpContext) in /_/src/Core/Services/PathRewriteMiddleware.cs:line 89
         at Azure.DataApiBuilder.Core.Services.CorrelationIdMiddleware.Invoke(HttpContext httpContext) in /_/src/Core/Services/CorrelationIdMiddleware.cs:line 53
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

Code of Conduct

  • [X] I agree to follow this project's Code of Conduct

Kennedine avatar May 07 '24 12:05 Kennedine

Hi @kennedine,

Because GraphQL defines the field Query by default, you can't define a DAB entity with the same name.

If you must have the entity name as Query to have DAB's REST endpoint work as you observe, you can define GraphQL field aliases for your entity in your dab-config.json:

,
  "entities": {
    "Query": {
      "source": "myTable",
      "permissions": [
        {
          "role": "anonymous",
          "actions": [
            "read"
          ]
        }
      ],
      "graphql": {
        "type": {
          "singular": "QueryEntity",
          "plural": "Queries"
        }
      }
    }
}

Your encountering this issue warrants an improved (and actually actionable) error message so in the future you and others don't waste valuable time trying to troubleshoot this.

seantleonard avatar May 07 '24 15:05 seantleonard

Hi @seantleonard thanks for the swift reply,

The error message when I had an entity named Query was clear enough I would say. The error message posted if after I changed my config to rename the "query" entity.

After the changes my config for the entity looks like this: "QueryEntity": { "source": { "object": "srv.Queries", "type": "table" }, "graphql": { "enabled": true, "type": { "singular": "QueryEntity", "plural": "Queries" } }, "rest": { "enabled": true }

I do not have any references to the Query entity other places in the config, so I am quite puzzled by what is now wrong. 

Kennedine avatar May 08 '24 08:05 Kennedine

So now that you have your entity named "QueryEntity" you're still seeing the following error you originally reported?

Connection id "0HN3EHLT5ACMT", Request id "0HN3EHLT5ACMT:00000002": An unhandled exception was thrown by the application. System.NotSupportedException: Specified method is not supported.

Can you provide your db table schema for srv.Queries + DAB config for that entity (entity + permissions) so I can ensure I'm getting exact repro of what you're experiencing?

seantleonard avatar May 08 '24 15:05 seantleonard

Sorry for the slow reply. I semi forgot about this and was then sick for 1½ week.

I assume this is what you want for the table? (Its system versioned, if that matter anything)

CREATE TABLE [srv].[Queries]( [QueryId] [int] IDENTITY(1,1) NOT NULL, [QueryName] varchar NOT NULL, [ApplicationReference] [int] NOT NULL, [DatasetReference] [int] NOT NULL, [QueryDescription] varchar NULL, [QueryType] varchar NOT NULL, [QueryDefinition] varchar NULL, [QueryParameters] varchar NULL, [QueryGroup] varchar NULL, [QueryEnabled] [bit] NOT NULL, [Tag] varchar NULL, [ValidFrom] datetime2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, [ValidTo] datetime2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, CONSTRAINT [PK_srv_Queries] PRIMARY KEY CLUSTERED ( [QueryId] ASC )WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY], PERIOD FOR SYSTEM_TIME ([ValidFrom], [ValidTo]) ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] WITH ( SYSTEM_VERSIONING = ON (HISTORY_TABLE = [srv].[QueriesHistory]) ) GO

ALTER TABLE [srv].[Queries] WITH CHECK ADD CONSTRAINT [FK_srv_Queries_srv_Applications] FOREIGN KEY([ApplicationReference]) REFERENCES [srv].[Applications] ([ApplicationId]) GO

ALTER TABLE [srv].[Queries] CHECK CONSTRAINT [FK_srv_Queries_srv_Applications] GO

ALTER TABLE [srv].[Queries] WITH CHECK ADD CONSTRAINT [FK_srv_Queries_srv_Datasets] FOREIGN KEY([DatasetReference]) REFERENCES [srv].[Datasets] ([DatasetId]) GO

ALTER TABLE [srv].[Queries] CHECK CONSTRAINT [FK_srv_Queries_srv_Datasets] GO

config part for the entity looks like this:

"QueryEntity": { "source": { "object": "srv.Queries", "type": "table" }, "graphql": { "enabled": true, "type": { "singular": "QueryEntity", "plural": "Queries" } }, "rest": { "enabled": true }, "permissions": [ { "role": "PlatformEngineer", "actions": [ { "action": "*" } ] }, { "role": "PlatformOperator", "actions": [ { "action": "read" } ] }, { "role": "DataAnalyst", "actions": [ { "action": "read" } ] }, { "role": "PlatformEngineer", "actions": [ { "action": "read" } ] } ], "relationships": { "applications": { "cardinality": "one", "target.entity": "Application", "source.fields": [ "ApplicationReference" ], "target.fields": [ "ApplicationId" ] }, "datasets": { "cardinality": "one", "target.entity": "Dataset", "source.fields": [ "DatasetReference" ], "target.fields": [ "DatasetId" ] } } }

Let me know if you need anything else :)

Kennedine avatar May 22 '24 13:05 Kennedine