From a8f625e5f7c413b5dd47e5ac362492c273516942 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 15 May 2026 19:12:45 -0700 Subject: [PATCH 1/7] Fix default dab-config --- dab-config.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dab-config.json b/dab-config.json index 6c0acfebd3..93e52ef406 100644 --- a/dab-config.json +++ b/dab-config.json @@ -24,7 +24,7 @@ }, "host": { "cors": { - "origins": [], + "origins": ["*"], "allow-credentials": false }, "authentication": { @@ -33,7 +33,6 @@ "mode": "development" } }, - "entities": {}, "autoentities": { "default": { "template": { @@ -49,7 +48,7 @@ { "role": "anonymous", "actions": [ - "create", "read", "update", "delete" + "*" ] } ] From 8019c706a6d947b14d44119e150651d3aac53bbb Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 15 May 2026 19:17:08 -0700 Subject: [PATCH 2/7] Add entityname in logs for easier debuggability --- src/Config/Converters/EntityCacheOptionsConverterFactory.cs | 2 +- src/Core/Services/MetadataProviders/SqlMetadataProvider.cs | 2 +- src/Core/Services/RequestValidator.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Config/Converters/EntityCacheOptionsConverterFactory.cs b/src/Config/Converters/EntityCacheOptionsConverterFactory.cs index 30f1241131..cdb93a8602 100644 --- a/src/Config/Converters/EntityCacheOptionsConverterFactory.cs +++ b/src/Config/Converters/EntityCacheOptionsConverterFactory.cs @@ -125,7 +125,7 @@ public EntityCacheOptionsConverter(DeserializationVariableReplacementSettings? r /// when its corresponding UserProvided* flag is true. This avoids polluting the written /// JSON file with properties the user omitted (defaults or inherited values). /// If the user provided a cache object (Entity.Cache is non-null), we always write the - /// object � even if it ends up empty ("cache": {}) � because the user explicitly included it. + /// object — even if it ends up empty ("cache": {}) — because the user explicitly included it. /// Entity.Cache being null means the user never wrote a cache property, and the serializer's /// DefaultIgnoreCondition.WhenWritingNull suppresses the "cache" key entirely. /// diff --git a/src/Core/Services/MetadataProviders/SqlMetadataProvider.cs b/src/Core/Services/MetadataProviders/SqlMetadataProvider.cs index 951b5984e4..c0b745b913 100644 --- a/src/Core/Services/MetadataProviders/SqlMetadataProvider.cs +++ b/src/Core/Services/MetadataProviders/SqlMetadataProvider.cs @@ -1474,7 +1474,7 @@ private async Task PopulateSourceDefinitionAsync( && IsGraphQLReservedName(entity, columnName, graphQLEnabledGlobally: runtimeConfig.IsGraphQLEnabled)) { throw new DataApiBuilderException( - message: $"The column '{columnName}' violates GraphQL name restrictions.", + message: $"The column '{columnName}' from {entityName} violates GraphQL name restrictions.", statusCode: HttpStatusCode.ServiceUnavailable, subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization); } diff --git a/src/Core/Services/RequestValidator.cs b/src/Core/Services/RequestValidator.cs index aef6ca9ab3..0b6b0734ad 100644 --- a/src/Core/Services/RequestValidator.cs +++ b/src/Core/Services/RequestValidator.cs @@ -401,7 +401,7 @@ public void ValidateUpsertRequestContext(UpsertRequestContext upsertRequestCtx, else { // Body-based PK: non-auto-generated PK columns MUST be present. - // Auto-generated PK columns are skipped � they cannot be supplied by the caller. + // Auto-generated PK columns are skipped — they cannot be supplied by the caller. if (column.Value.IsAutoGenerated) { continue; From 2e6ce80c5f3f685fc8e3e2c6359d837329bbd1f9 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 15 May 2026 20:08:45 -0700 Subject: [PATCH 3/7] Add default auto entity patterns --- dab-config.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dab-config.json b/dab-config.json index 93e52ef406..707fcb380f 100644 --- a/dab-config.json +++ b/dab-config.json @@ -35,6 +35,10 @@ }, "autoentities": { "default": { + "patterns": { + "include": ["%.%"], + "name": "{schema}_{object}" + }, "template": { "mcp": { "dml-tools": true }, "rest": { "enabled": true }, From 94a55035cccf88cfde762e97f906e143404f34f9 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 15 May 2026 20:16:35 -0700 Subject: [PATCH 4/7] Fix the default config shipped in docker image --- src/Aspire.AppHost/AppHost.cs | 8 +- src/Service/dab-config.json | 264 ++++++---------------------------- 2 files changed, 51 insertions(+), 221 deletions(-) diff --git a/src/Aspire.AppHost/AppHost.cs b/src/Aspire.AppHost/AppHost.cs index 5477c5c81b..3e4e3f597c 100644 --- a/src/Aspire.AppHost/AppHost.cs +++ b/src/Aspire.AppHost/AppHost.cs @@ -39,11 +39,11 @@ if (sqlDbContainer is null) { - mssqlService.WithEnvironment("ConnectionStrings__Database", databaseConnectionString); + mssqlService.WithEnvironment("DAB_CONNSTRING", databaseConnectionString); } else { - mssqlService.WithEnvironment("ConnectionStrings__Database", sqlDbContainer) + mssqlService.WithEnvironment("DAB_CONNSTRING", sqlDbContainer) .WaitFor(sqlDbContainer); } @@ -79,11 +79,11 @@ if (postgresDB is null) { - pgService.WithEnvironment("ConnectionStrings__Database", databaseConnectionString); + pgService.WithEnvironment("DAB_CONNSTRING", databaseConnectionString); } else { - pgService.WithEnvironment("ConnectionStrings__Database", postgresDB) + pgService.WithEnvironment("DAB_CONNSTRING", postgresDB) .WaitFor(postgresDB); } diff --git a/src/Service/dab-config.json b/src/Service/dab-config.json index 859267100e..707fcb380f 100644 --- a/src/Service/dab-config.json +++ b/src/Service/dab-config.json @@ -1,231 +1,61 @@ { + "$schema": "https://github.com/Azure/data-api-builder/releases/latest/download/dab.draft.schema.json", "data-source": { - "database-type": "@env('db-type')", - "connection-string": "@env('ConnectionStrings__Database')", + "database-type": "mssql", + "connection-string": "@env('DAB_CONNSTRING')", "options": { "set-session-context": false } }, - "runtime": { - "rest": { - "enabled": true, - "path": "/api", - "request-body-strict": true - }, - "graphql": { - "enabled": true, - "path": "/graphql", - "allow-introspection": true - }, - "host": { - "authentication": { - "provider": "StaticWebApps" - }, - "cors": { - "origins": [], - "allow-credentials": false - }, - "mode": "development" - }, - "telemetry": { - "open-telemetry": { - "enabled": true, - "endpoint": "@env('OTEL_EXPORTER_OTLP_ENDPOINT')", - "headers": "@env('OTEL_EXPORTER_OTLP_HEADERS')", - "exporter-protocol": "@env('OTEL_EXPORTER_OTLP_PROTOCOL')", - "service-name": "@env('OTEL_SERVICE_NAME')" - } - }, - "cache": { - "enabled": true, - "ttl-seconds": 60 - } + "runtime": { + "rest": { + "enabled": true, + "path": "/api", + "request-body-strict": false }, - "entities": { - "Actor": { - "source": { - "object": "Actor", - "type": "table" - }, - "graphql": { - "enabled": true, - "type": { - "singular": "Actor", - "plural": "Actors" - } - }, - "rest": { - "enabled": true - }, - "permissions": [ - { - "role": "anonymous", - "actions": [ - "*" - ] - } - ], - "relationships": { - "character": { - "cardinality": "many", - "target.entity": "Character", - "source.fields": [ - "Id" - ], - "target.fields": [ - "ActorId" - ], - "linking.source.fields": [], - "linking.target.fields": [] - } - } + "graphql": { + "enabled": true, + "path": "/graphql", + "allow-introspection": true + }, + "mcp": { + "enabled": true, + "path": "/mcp" + }, + "host": { + "cors": { + "origins": ["*"], + "allow-credentials": false }, - "Character": { - "source": { - "object": "Character", - "type": "table" - }, - "graphql": { - "enabled": true, - "type": { - "singular": "Character", - "plural": "Characters" - } - }, - "rest": { - "enabled": true - }, - "permissions": [ - { - "role": "anonymous", - "actions": [ - { - "action": "*" - } - ] - } - ], - "relationships": { - "actor": { - "cardinality": "one", - "target.entity": "Actor", - "source.fields": [ - "ActorId" - ], - "target.fields": [ - "Id" - ], - "linking.source.fields": [], - "linking.target.fields": [] - }, - "series": { - "cardinality": "many", - "target.entity": "Series", - "source.fields": [ - "Id" - ], - "target.fields": [ - "Id" - ], - "linking.object": "series_character", - "linking.source.fields": [ - "CharacterId" - ], - "linking.target.fields": [ - "SeriesId" - ] - } - } + "authentication": { + "provider": "Unauthenticated" + }, + "mode": "development" + } + }, + "autoentities": { + "default": { + "patterns": { + "include": ["%.%"], + "name": "{schema}_{object}" }, - "Series": { - "source": { - "object": "Series", - "type": "table" - }, - "graphql": { - "enabled": true, - "type": { - "singular": "Series", - "plural": "Series" - } - }, - "rest": { - "enabled": true - }, - "permissions": [ - { - "role": "anonymous", - "actions": [ - { - "action": "*" - } - ] - } - ], - "relationships": { - "character": { - "cardinality": "many", - "target.entity": "Character", - "source.fields": [ - "Id" - ], - "target.fields": [ - "Id" - ], - "linking.object": "series_character", - "linking.source.fields": [ - "SeriesId" - ], - "linking.target.fields": [ - "CharacterId" - ] - } + "template": { + "mcp": { "dml-tools": true }, + "rest": { "enabled": true }, + "graphql": { "enabled": true }, + "health": { "enabled": true }, + "cache": { + "enabled": false } }, - "Species": { - "source": { - "object": "Species", - "type": "table" - }, - "graphql": { - "enabled": true, - "type": { - "singular": "Species", - "plural": "Species" - } - }, - "rest": { - "enabled": true - }, - "permissions": [ - { - "role": "anonymous", - "actions": [ - { - "action": "*" - } - ] - } - ], - "relationships": { - "character": { - "cardinality": "many", - "target.entity": "Character", - "source.fields": [ - "Id" - ], - "target.fields": [ - "Id" - ], - "linking.object": "character_species", - "linking.source.fields": [ - "SpeciesId" - ], - "linking.target.fields": [ - "CharacterId" - ] - } + "permissions": [ + { + "role": "anonymous", + "actions": [ + "*" + ] } - } + ] } } +} From a53880b9dff2d9f4056372e254877de55ccc5e3a Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 15 May 2026 21:14:34 -0700 Subject: [PATCH 5/7] Fix the path of dab-config for test Dockerfile --- Dockerfile | 4 ++-- dab-config.json | 61 ------------------------------------------------- 2 files changed, 2 insertions(+), 63 deletions(-) delete mode 100644 dab-config.json diff --git a/Dockerfile b/Dockerfile index 59190b6374..21dfece640 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # Version values referenced from https://hub.docker.com/_/microsoft-dotnet-aspnet -FROM mcr.microsoft.com/dotnet/sdk:8.0-cbl-mariner2.0. AS build +FROM mcr.microsoft.com/dotnet/sdk:8.0-cbl-mariner2.0 AS build WORKDIR /src @@ -11,7 +11,7 @@ FROM mcr.microsoft.com/dotnet/aspnet:8.0-cbl-mariner2.0 AS runtime COPY --from=build /out /App # Add default dab-config.json to /App in the image -COPY dab-config.json /App/dab-config.json +COPY --from=build /out/dab-config.json /App/dab-config.json WORKDIR /App ENV ASPNETCORE_URLS=http://+:5000 ENTRYPOINT ["dotnet", "Azure.DataApiBuilder.Service.dll"] diff --git a/dab-config.json b/dab-config.json deleted file mode 100644 index 707fcb380f..0000000000 --- a/dab-config.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "$schema": "https://github.com/Azure/data-api-builder/releases/latest/download/dab.draft.schema.json", - "data-source": { - "database-type": "mssql", - "connection-string": "@env('DAB_CONNSTRING')", - "options": { - "set-session-context": false - } - }, - "runtime": { - "rest": { - "enabled": true, - "path": "/api", - "request-body-strict": false - }, - "graphql": { - "enabled": true, - "path": "/graphql", - "allow-introspection": true - }, - "mcp": { - "enabled": true, - "path": "/mcp" - }, - "host": { - "cors": { - "origins": ["*"], - "allow-credentials": false - }, - "authentication": { - "provider": "Unauthenticated" - }, - "mode": "development" - } - }, - "autoentities": { - "default": { - "patterns": { - "include": ["%.%"], - "name": "{schema}_{object}" - }, - "template": { - "mcp": { "dml-tools": true }, - "rest": { "enabled": true }, - "graphql": { "enabled": true }, - "health": { "enabled": true }, - "cache": { - "enabled": false - } - }, - "permissions": [ - { - "role": "anonymous", - "actions": [ - "*" - ] - } - ] - } - } -} From 0b83014a38d24ceff17c0c358a95495ef6b933c8 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Mon, 18 May 2026 10:54:55 -0700 Subject: [PATCH 6/7] always CopyToOutputDirectory --- src/Service/Azure.DataApiBuilder.Service.csproj | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Service/Azure.DataApiBuilder.Service.csproj b/src/Service/Azure.DataApiBuilder.Service.csproj index d0478b83ed..2ba352c02f 100644 --- a/src/Service/Azure.DataApiBuilder.Service.csproj +++ b/src/Service/Azure.DataApiBuilder.Service.csproj @@ -22,13 +22,11 @@ - Always - Always - Never + Always LICENSE.txt From d58ba94f136115738fb0d903d43e614ba572843c Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Mon, 18 May 2026 10:59:36 -0700 Subject: [PATCH 7/7] Apply suggestions from code review Enclose in single quotes Co-authored-by: Aniruddh Munde --- src/Core/Services/MetadataProviders/SqlMetadataProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Services/MetadataProviders/SqlMetadataProvider.cs b/src/Core/Services/MetadataProviders/SqlMetadataProvider.cs index 9394ee6f8a..d93b4edbcf 100644 --- a/src/Core/Services/MetadataProviders/SqlMetadataProvider.cs +++ b/src/Core/Services/MetadataProviders/SqlMetadataProvider.cs @@ -1478,7 +1478,7 @@ private async Task PopulateSourceDefinitionAsync( && IsGraphQLReservedName(entity, columnName, graphQLEnabledGlobally: runtimeConfig.IsGraphQLEnabled)) { throw new DataApiBuilderException( - message: $"The column '{columnName}' from {entityName} violates GraphQL name restrictions.", + message: $"The column '{columnName}' from '{entityName}' violates GraphQL name restrictions.", statusCode: HttpStatusCode.ServiceUnavailable, subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization); }