diff --git a/sdk/dotnet/src/Microsoft.AspNetCore.Datasync.Swashbuckle/DatasyncDocumentFilter.cs b/sdk/dotnet/src/Microsoft.AspNetCore.Datasync.Swashbuckle/DatasyncDocumentFilter.cs
index 0e64ef71f..5dfadbc82 100644
--- a/sdk/dotnet/src/Microsoft.AspNetCore.Datasync.Swashbuckle/DatasyncDocumentFilter.cs
+++ b/sdk/dotnet/src/Microsoft.AspNetCore.Datasync.Swashbuckle/DatasyncDocumentFilter.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT License.
using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
@@ -39,7 +40,7 @@ private enum OpType
///
/// The assembly to query for TableController instances, if any. If none is provided, the calling assembly is queried.
///
- private Assembly assemblyToQuery = null;
+ private readonly Assembly assemblyToQuery = null;
///
/// Creates a new .
@@ -68,11 +69,11 @@ public void Apply(OpenApiDocument document, DocumentFilterContext context)
if (entityType == null)
continue;
- var routeAttribute = controller.GetCustomAttribute();
- if (routeAttribute == null)
+ var routePath = context.ApiDescriptions.FirstOrDefault(m => IsApiDescriptionForController(m, controller))?.RelativePath;
+ if (routePath == null)
continue;
- var allEntitiesPath = $"/{routeAttribute.Template}";
- var singleEntityPath = $"/{routeAttribute.Template}/{{id}}";
+ var allEntitiesPath = $"/{routePath}";
+ var singleEntityPath = $"/{routePath}/{{id}}";
// Get the various operations
Dictionary operations = new()
@@ -176,6 +177,21 @@ public void Apply(OpenApiDocument document, DocumentFilterContext context)
}
}
}
+
+ ///
+ /// Determines if the controller type is represented by the API Description.
+ ///
+ /// The being handled.
+ /// The type of the controller being used.
+ /// true if the Api description represents the controller.
+ internal static bool IsApiDescriptionForController(ApiDescription description, Type controllerType)
+ {
+ if (description.TryGetMethodInfo(out MethodInfo methodInfo))
+ {
+ return methodInfo.ReflectedType == controllerType && (methodInfo.Name.Equals("GetAsync") || methodInfo.Name.Equals("CreateAsync"));
+ }
+ return false;
+ }
///
/// Returns a list of all table controllers in the provided assembly.
diff --git a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.NSwag.Test/Service/KitchenSink.cs b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.NSwag.Test/Service/Models.cs
similarity index 85%
rename from sdk/dotnet/test/Microsoft.AspNetCore.Datasync.NSwag.Test/Service/KitchenSink.cs
rename to sdk/dotnet/test/Microsoft.AspNetCore.Datasync.NSwag.Test/Service/Models.cs
index 5c794436a..4a3b9d078 100644
--- a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.NSwag.Test/Service/KitchenSink.cs
+++ b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.NSwag.Test/Service/Models.cs
@@ -5,10 +5,12 @@
namespace Microsoft.AspNetCore.Datasync.NSwag.Test.Service
{
- ///
- /// A model used for validation tests. It contains one of
- /// every single supported type in a nullable form.
- ///
+ [ExcludeFromCodeCoverage]
+ public class TodoItem : EntityTableData
+ {
+ public string? Title { get; set; }
+ }
+
[ExcludeFromCodeCoverage]
public class KitchenSink : EntityTableData
{
diff --git a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.NSwag.Test/Service/ServiceDbContext.cs b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.NSwag.Test/Service/ServiceDbContext.cs
index de69814cb..6b7fb85c7 100644
--- a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.NSwag.Test/Service/ServiceDbContext.cs
+++ b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.NSwag.Test/Service/ServiceDbContext.cs
@@ -22,6 +22,11 @@ public ServiceDbContext(DbContextOptions options) : base(optio
///
public DbSet KitchenSinks => Set();
+ ///
+ /// The set of TodoItem values
+ ///
+ public DbSet TodoItems => Set();
+
///
/// Initializes the current database
///
diff --git a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.NSwag.Test/Service/TodoItemController.cs b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.NSwag.Test/Service/TodoItemController.cs
new file mode 100644
index 000000000..ba4d30e84
--- /dev/null
+++ b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.NSwag.Test/Service/TodoItemController.cs
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved.
+// Licensed under the MIT License.
+
+using Microsoft.AspNetCore.Datasync.EFCore;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.AspNetCore.Datasync.NSwag.Test.Service
+{
+ [Route("tables/[controller]")]
+ [ExcludeFromCodeCoverage]
+ public class TodoItemController : TableController
+ {
+ public TodoItemController(ServiceDbContext context, ILogger logger) : base()
+ {
+ Repository = new EntityTableRepository(context);
+ Logger = logger;
+ }
+ }
+}
diff --git a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.NSwag.Test/swagger.json b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.NSwag.Test/swagger.json
index 489352a4b..673c20925 100644
--- a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.NSwag.Test/swagger.json
+++ b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.NSwag.Test/swagger.json
@@ -635,6 +635,631 @@
}
}
}
+ },
+ "/tables/TodoItem": {
+ "post": {
+ "tags": [
+ "TodoItem"
+ ],
+ "operationId": "TodoItem_Create",
+ "parameters": [
+ {
+ "name": "ZUMO-API-VERSION",
+ "in": "header",
+ "required": true,
+ "description": "Sets the Datasync API version to use.",
+ "schema": {
+ "type": "string",
+ "enum": [
+ "3.0.0",
+ "2.0.0"
+ ]
+ }
+ },
+ {
+ "name": "If-None-Match",
+ "in": "header",
+ "description": "Conditionally execute only if the entity version does not match the provided string (RFC 9110 13.1.2).",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "x-name": "item",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ },
+ "required": true,
+ "x-position": 1
+ },
+ "responses": {
+ "201": {
+ "description": "Created",
+ "headers": {
+ "ETag": {
+ "description": "The version string of the server entity, per RFC 9110",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "409": {
+ "description": "Conflict",
+ "headers": {
+ "ETag": {
+ "description": "The version string of the server entity, per RFC 9110",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "412": {
+ "description": "Precondition Failed",
+ "headers": {
+ "ETag": {
+ "description": "The version string of the server entity, per RFC 9110",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request"
+ }
+ }
+ },
+ "get": {
+ "tags": [
+ "TodoItem"
+ ],
+ "operationId": "TodoItem_Query",
+ "parameters": [
+ {
+ "name": "ZUMO-API-VERSION",
+ "in": "header",
+ "required": true,
+ "description": "Sets the Datasync API version to use.",
+ "schema": {
+ "type": "string",
+ "enum": [
+ "3.0.0",
+ "2.0.0"
+ ]
+ }
+ },
+ {
+ "name": "$count",
+ "in": "query",
+ "description": "If true, return the total number of items matched by the filter",
+ "schema": {
+ "type": "boolean"
+ }
+ },
+ {
+ "name": "$filter",
+ "in": "query",
+ "description": "An OData filter describing the entities to be returned",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "$orderby",
+ "in": "query",
+ "description": "A comma-separated list of ordering instructions. Each ordering instruction is a field name with an optional direction (asc or desc).",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "$select",
+ "in": "query",
+ "description": "A comma-separated list of fields to be returned in the result set.",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "$skip",
+ "in": "query",
+ "description": "The number of items in the list to skip for paging support.",
+ "schema": {
+ "type": "integer"
+ }
+ },
+ {
+ "name": "$top",
+ "in": "query",
+ "description": "The number of items in the list to return for paging support.",
+ "schema": {
+ "type": "integer"
+ }
+ },
+ {
+ "name": "__includedeleted",
+ "in": "query",
+ "description": "If true, soft-deleted items are returned as well as non-deleted items.",
+ "schema": {
+ "type": "boolean"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "description": "A page of TodoItem entities",
+ "properties": {
+ "items": {
+ "type": "array",
+ "readOnly": true,
+ "description": "The entities in this page of results",
+ "nullable": true,
+ "items": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ },
+ "count": {
+ "type": "integer",
+ "readOnly": true,
+ "description": "The count of all entities in the result set",
+ "nullable": true
+ },
+ "nextLink": {
+ "type": "string",
+ "readOnly": true,
+ "description": "The URI to the next page of entities",
+ "format": "uri",
+ "nullable": true
+ }
+ }
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request"
+ }
+ }
+ }
+ },
+ "/tables/TodoItem/{id}": {
+ "delete": {
+ "tags": [
+ "TodoItem"
+ ],
+ "operationId": "TodoItem_Delete",
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string",
+ "nullable": true
+ },
+ "x-position": 1
+ },
+ {
+ "name": "ZUMO-API-VERSION",
+ "in": "header",
+ "required": true,
+ "description": "Sets the Datasync API version to use.",
+ "schema": {
+ "type": "string",
+ "enum": [
+ "3.0.0",
+ "2.0.0"
+ ]
+ }
+ },
+ {
+ "name": "If-Match",
+ "in": "header",
+ "description": "Conditionally execute only if the entity version matches the provided string (RFC 9110 13.1.1).",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "No Content"
+ },
+ "409": {
+ "description": "Conflict",
+ "headers": {
+ "ETag": {
+ "description": "The version string of the server entity, per RFC 9110",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "412": {
+ "description": "Precondition Failed",
+ "headers": {
+ "ETag": {
+ "description": "The version string of the server entity, per RFC 9110",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Not Found"
+ },
+ "410": {
+ "description": "Gone"
+ }
+ }
+ },
+ "patch": {
+ "tags": [
+ "TodoItem"
+ ],
+ "operationId": "TodoItem_Patch",
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string",
+ "nullable": true
+ },
+ "x-position": 1
+ },
+ {
+ "name": "ZUMO-API-VERSION",
+ "in": "header",
+ "required": true,
+ "description": "Sets the Datasync API version to use.",
+ "schema": {
+ "type": "string",
+ "enum": [
+ "3.0.0",
+ "2.0.0"
+ ]
+ }
+ },
+ {
+ "name": "If-Match",
+ "in": "header",
+ "description": "Conditionally execute only if the entity version matches the provided string (RFC 9110 13.1.1).",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "headers": {
+ "ETag": {
+ "description": "The version string of the server entity, per RFC 9110",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "409": {
+ "description": "Conflict",
+ "headers": {
+ "ETag": {
+ "description": "The version string of the server entity, per RFC 9110",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "412": {
+ "description": "Precondition Failed",
+ "headers": {
+ "ETag": {
+ "description": "The version string of the server entity, per RFC 9110",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request"
+ },
+ "404": {
+ "description": "Not Found"
+ },
+ "410": {
+ "description": "Gone"
+ }
+ }
+ },
+ "get": {
+ "tags": [
+ "TodoItem"
+ ],
+ "operationId": "TodoItem_Read",
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string",
+ "nullable": true
+ },
+ "x-position": 1
+ },
+ {
+ "name": "ZUMO-API-VERSION",
+ "in": "header",
+ "required": true,
+ "description": "Sets the Datasync API version to use.",
+ "schema": {
+ "type": "string",
+ "enum": [
+ "3.0.0",
+ "2.0.0"
+ ]
+ }
+ },
+ {
+ "name": "If-None-Match",
+ "in": "header",
+ "description": "Conditionally execute only if the entity version does not match the provided string (RFC 9110 13.1.2).",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "headers": {
+ "ETag": {
+ "description": "The version string of the server entity, per RFC 9110",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "409": {
+ "description": "Conflict",
+ "headers": {
+ "ETag": {
+ "description": "The version string of the server entity, per RFC 9110",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "412": {
+ "description": "Precondition Failed",
+ "headers": {
+ "ETag": {
+ "description": "The version string of the server entity, per RFC 9110",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Not Found"
+ }
+ }
+ },
+ "put": {
+ "tags": [
+ "TodoItem"
+ ],
+ "operationId": "TodoItem_Replace",
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string",
+ "nullable": true
+ },
+ "x-position": 1
+ },
+ {
+ "name": "ZUMO-API-VERSION",
+ "in": "header",
+ "required": true,
+ "description": "Sets the Datasync API version to use.",
+ "schema": {
+ "type": "string",
+ "enum": [
+ "3.0.0",
+ "2.0.0"
+ ]
+ }
+ },
+ {
+ "name": "If-Match",
+ "in": "header",
+ "description": "Conditionally execute only if the entity version matches the provided string (RFC 9110 13.1.1).",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "x-name": "item",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ },
+ "required": true,
+ "x-position": 2
+ },
+ "responses": {
+ "200": {
+ "description": "OK",
+ "headers": {
+ "ETag": {
+ "description": "The version string of the server entity, per RFC 9110",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "409": {
+ "description": "Conflict",
+ "headers": {
+ "ETag": {
+ "description": "The version string of the server entity, per RFC 9110",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "412": {
+ "description": "Precondition Failed",
+ "headers": {
+ "ETag": {
+ "description": "The version string of the server entity, per RFC 9110",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request"
+ },
+ "404": {
+ "description": "Not Found"
+ },
+ "410": {
+ "description": "Gone"
+ }
+ }
+ }
}
},
"components": {
@@ -722,6 +1347,23 @@
"readOnly": true
}
}
+ },
+ "TodoItem": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/EntityTableData"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "title": {
+ "type": "string",
+ "nullable": true
+ }
+ }
+ }
+ ]
}
}
}
diff --git a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test.csproj b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test.csproj
index 3444686c7..7d57f53ac 100644
--- a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test.csproj
+++ b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test.csproj
@@ -39,4 +39,6 @@
+
+
diff --git a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/Service/KitchenSink.cs b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/Service/Models.cs
similarity index 85%
rename from sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/Service/KitchenSink.cs
rename to sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/Service/Models.cs
index 338579741..863443c6d 100644
--- a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/Service/KitchenSink.cs
+++ b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/Service/Models.cs
@@ -5,10 +5,12 @@
namespace Microsoft.AspNetCore.Datasync.Swashbuckle.Test.Service
{
- ///
- /// A model used for validation tests. It contains one of
- /// every single supported type in a nullable form.
- ///
+ [ExcludeFromCodeCoverage]
+ public class TodoItem : EntityTableData
+ {
+ public string? Title { get; set; }
+ }
+
[ExcludeFromCodeCoverage]
public class KitchenSink : EntityTableData
{
diff --git a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/Service/ServiceDbContext.cs b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/Service/ServiceDbContext.cs
index d99158660..c59c18988 100644
--- a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/Service/ServiceDbContext.cs
+++ b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/Service/ServiceDbContext.cs
@@ -21,6 +21,11 @@ public ServiceDbContext(DbContextOptions options) : base(optio
/// The set of kitchen sink values
///
public DbSet KitchenSinks => Set();
+
+ ///
+ /// The set of TodoItem values
+ ///
+ public DbSet TodoItems => Set();
///
/// Initializes the current database
diff --git a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/Service/TodoItemController.cs b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/Service/TodoItemController.cs
new file mode 100644
index 000000000..a5b049e59
--- /dev/null
+++ b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/Service/TodoItemController.cs
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved.
+// Licensed under the MIT License.
+
+using Microsoft.AspNetCore.Datasync.EFCore;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.AspNetCore.Datasync.Swashbuckle.Test.Service
+{
+ [Route("tables/[controller]")]
+ [ExcludeFromCodeCoverage]
+ public class TodoItemController : TableController
+ {
+ public TodoItemController(ServiceDbContext context, ILogger logger) : base()
+ {
+ Repository = new EntityTableRepository(context);
+ Logger = logger;
+ }
+ }
+}
diff --git a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/SwaggerGen_Tests.cs b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/SwaggerGen_Tests.cs
index d0c18b846..6e226eec1 100644
--- a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/SwaggerGen_Tests.cs
+++ b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/SwaggerGen_Tests.cs
@@ -10,13 +10,13 @@ namespace Microsoft.AspNetCore.Datasync.Swashbuckle.Test
{
public class SwaggerGen_Tests
{
- private TestServer server = SwaggerServer.CreateTestServer();
+ private readonly TestServer server = SwaggerServer.CreateTestServer();
private static string ReadExternalFile(string filename)
{
Assembly asm = Assembly.GetExecutingAssembly();
using Stream s = asm.GetManifestResourceStream(asm.GetName().Name + "." + filename)!;
- using StreamReader sr = new StreamReader(s);
+ using StreamReader sr = new(s);
return sr.ReadToEnd();
}
@@ -25,9 +25,12 @@ public void DocumentFilter_ReadsAllControllers()
{
Assert.NotNull(server);
- var controllers = DatasyncDocumentFilter.GetAllTableControllers();
- Assert.Single(controllers);
- Assert.Equal("KitchenSinkController", controllers.First().Name);
+ var controllers = DatasyncDocumentFilter.GetAllTableControllers().Select(m => m.Name).ToList();
+
+ // There should be two controllers
+ Assert.Equal(2, controllers.Count);
+ Assert.Contains("KitchenSinkController", controllers);
+ Assert.Contains("TodoItemController", controllers);
}
[Fact]
diff --git a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/swagger.json b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/swagger.json
index e7b030555..ec1f1b2df 100644
--- a/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/swagger.json
+++ b/sdk/dotnet/test/Microsoft.AspNetCore.Datasync.Swashbuckle.Test/swagger.json
@@ -559,6 +559,561 @@
}
}
}
+ },
+ "/tables/TodoItem": {
+ "post": {
+ "tags": [
+ "TodoItem"
+ ],
+ "parameters": [
+ {
+ "name": "ZUMO-API-VERSION",
+ "in": "header",
+ "description": "Datasync protocol version to be used.",
+ "required": true,
+ "schema": {
+ "enum": [
+ "3.0.0",
+ "2.0.0"
+ ],
+ "type": "string"
+ }
+ },
+ {
+ "name": "If-None-Match",
+ "in": "header",
+ "description": "Conditionally execute only if the entity version does not match the provided string (RFC 9110 13.1.2).",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "Created",
+ "headers": {
+ "ETag": {
+ "description": "The opaque versioning identifier of the entity, per RFC 9110 8.8.3.",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request"
+ },
+ "409": {
+ "description": "Conflict",
+ "headers": {
+ "ETag": {
+ "description": "The opaque versioning identifier of the conflicting entity, per RFC 9110 8.8.3.",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "412": {
+ "description": "Precondition failed",
+ "headers": {
+ "ETag": {
+ "description": "The opaque versioning identifier of the conflicting entity, per RFC 9110 8.8.3.",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ }
+ }
+ },
+ "get": {
+ "tags": [
+ "TodoItem"
+ ],
+ "parameters": [
+ {
+ "name": "ZUMO-API-VERSION",
+ "in": "header",
+ "description": "Datasync protocol version to be used.",
+ "required": true,
+ "schema": {
+ "enum": [
+ "3.0.0",
+ "2.0.0"
+ ],
+ "type": "string"
+ }
+ },
+ {
+ "name": "$count",
+ "in": "query",
+ "description": "If true, return the total number of items matched by the filter",
+ "schema": {
+ "type": "boolean"
+ }
+ },
+ {
+ "name": "$filter",
+ "in": "query",
+ "description": "An OData filter describing the entities to be returned",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "$orderby",
+ "in": "query",
+ "description": "A comma-separated list of ordering instructions. Each ordering instruction is a field name with an optional direction (asc or desc).",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "$select",
+ "in": "query",
+ "description": "A comma-separated list of fields to be returned in the result set.",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "$skip",
+ "in": "query",
+ "description": "The number of items in the list to skip for paging support.",
+ "schema": {
+ "type": "integer"
+ }
+ },
+ {
+ "name": "$top",
+ "in": "query",
+ "description": "The number of items in the list to return for paging support.",
+ "schema": {
+ "type": "integer"
+ }
+ },
+ {
+ "name": "__includedeleted",
+ "in": "query",
+ "description": "If true, soft-deleted items are returned as well as non-deleted items.",
+ "schema": {
+ "type": "boolean"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "headers": {
+ "ETag": {
+ "description": "The opaque versioning identifier of the entity, per RFC 9110 8.8.3.",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItemPage"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request"
+ }
+ }
+ }
+ },
+ "/tables/TodoItem/{id}": {
+ "delete": {
+ "tags": [
+ "TodoItem"
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "ZUMO-API-VERSION",
+ "in": "header",
+ "description": "Datasync protocol version to be used.",
+ "required": true,
+ "schema": {
+ "enum": [
+ "3.0.0",
+ "2.0.0"
+ ],
+ "type": "string"
+ }
+ },
+ {
+ "name": "If-Match",
+ "in": "header",
+ "description": "Conditionally execute only if the entity version matches the provided string (RFC 9110 13.1.1).",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "No Content"
+ },
+ "404": {
+ "description": "Not Found"
+ },
+ "410": {
+ "description": "Gone"
+ },
+ "409": {
+ "description": "Conflict",
+ "headers": {
+ "ETag": {
+ "description": "The opaque versioning identifier of the conflicting entity, per RFC 9110 8.8.3.",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "412": {
+ "description": "Precondition failed",
+ "headers": {
+ "ETag": {
+ "description": "The opaque versioning identifier of the conflicting entity, per RFC 9110 8.8.3.",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ }
+ }
+ },
+ "patch": {
+ "tags": [
+ "TodoItem"
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "ZUMO-API-VERSION",
+ "in": "header",
+ "description": "Datasync protocol version to be used.",
+ "required": true,
+ "schema": {
+ "enum": [
+ "3.0.0",
+ "2.0.0"
+ ],
+ "type": "string"
+ }
+ },
+ {
+ "name": "If-Match",
+ "in": "header",
+ "description": "Conditionally execute only if the entity version matches the provided string (RFC 9110 13.1.1).",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "headers": {
+ "ETag": {
+ "description": "The opaque versioning identifier of the entity, per RFC 9110 8.8.3.",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request"
+ },
+ "404": {
+ "description": "Not Found"
+ },
+ "410": {
+ "description": "Gone"
+ },
+ "409": {
+ "description": "Conflict",
+ "headers": {
+ "ETag": {
+ "description": "The opaque versioning identifier of the conflicting entity, per RFC 9110 8.8.3.",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "412": {
+ "description": "Precondition failed",
+ "headers": {
+ "ETag": {
+ "description": "The opaque versioning identifier of the conflicting entity, per RFC 9110 8.8.3.",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ }
+ }
+ },
+ "get": {
+ "tags": [
+ "TodoItem"
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "ZUMO-API-VERSION",
+ "in": "header",
+ "description": "Datasync protocol version to be used.",
+ "required": true,
+ "schema": {
+ "enum": [
+ "3.0.0",
+ "2.0.0"
+ ],
+ "type": "string"
+ }
+ },
+ {
+ "name": "If-None-Match",
+ "in": "header",
+ "description": "Conditionally execute only if the entity version does not match the provided string (RFC 9110 13.1.2).",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "headers": {
+ "ETag": {
+ "description": "The opaque versioning identifier of the entity, per RFC 9110 8.8.3.",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "304": {
+ "description": "Not Modified"
+ },
+ "404": {
+ "description": "Not Found"
+ }
+ }
+ },
+ "put": {
+ "tags": [
+ "TodoItem"
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "ZUMO-API-VERSION",
+ "in": "header",
+ "description": "Datasync protocol version to be used.",
+ "required": true,
+ "schema": {
+ "enum": [
+ "3.0.0",
+ "2.0.0"
+ ],
+ "type": "string"
+ }
+ },
+ {
+ "name": "If-Match",
+ "in": "header",
+ "description": "Conditionally execute only if the entity version matches the provided string (RFC 9110 13.1.1).",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "OK",
+ "headers": {
+ "ETag": {
+ "description": "The opaque versioning identifier of the entity, per RFC 9110 8.8.3.",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request"
+ },
+ "404": {
+ "description": "Not Found"
+ },
+ "410": {
+ "description": "Gone"
+ },
+ "409": {
+ "description": "Conflict",
+ "headers": {
+ "ETag": {
+ "description": "The opaque versioning identifier of the conflicting entity, per RFC 9110 8.8.3.",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ },
+ "412": {
+ "description": "Precondition failed",
+ "headers": {
+ "ETag": {
+ "description": "The opaque versioning identifier of the conflicting entity, per RFC 9110 8.8.3.",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/TodoItem"
+ }
+ }
+ }
+ }
+ }
+ }
}
},
"components": {
@@ -658,6 +1213,61 @@
}
},
"additionalProperties": false
+ },
+ "TodoItem": {
+ "type": "object",
+ "properties": {
+ "title": {
+ "type": "string",
+ "nullable": true
+ },
+ "id": {
+ "type": "string",
+ "nullable": true
+ },
+ "updatedAt": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "version": {
+ "type": "string",
+ "format": "byte",
+ "nullable": true,
+ "readOnly": true
+ },
+ "deleted": {
+ "type": "boolean",
+ "readOnly": true
+ }
+ },
+ "additionalProperties": false
+ },
+ "TodoItemPage": {
+ "type": "object",
+ "properties": {
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/TodoItem"
+ },
+ "nullable": true,
+ "readOnly": true
+ },
+ "count": {
+ "type": "integer",
+ "format": "int64",
+ "nullable": true,
+ "readOnly": true
+ },
+ "nextLink": {
+ "type": "string",
+ "format": "uri",
+ "nullable": true,
+ "readOnly": true
+ }
+ },
+ "additionalProperties": false
}
}
}