aqueduct
aqueduct copied to clipboard
"document" command fails when a multi-variable path is routed to a ManagedObjectController
Using the "db" aqueduct template as the basis for this test, I have added an additional variable to the "model" path like so:
@override
Controller get entryPoint {
final router = Router();
router.route("/model/[:id/[:subId]]").link(() => ModelController(context));
return router;
}
I have also extended the ManagedObjectController with a class called ModelController
which the route is now linked to.
class ModelController extends ManagedObjectController<Model> {
ModelController(ManagedContext context) : super(context);
@Operation.get('id', 'subId')
Future<Response> getObjectWithIdAndSubId(
@Bind.path('id') String id, @Bind.path('subId') String subId) =>
getObject(id);
}
When running pub run aqueduct document
, it fails with this output:
-- Aqueduct CLI Version: 4.0.0-b1
-- Aqueduct project version: 4.0.0-b1
*** Uncaught error
Bad state: Invalid argument(s): Invalid context. The data model of 'context' does not contain 'ManagedObject<dynamic>'.
**** Stacktrace
* #0 new Query (package:aqueduct/src/db/query/query.dart:32:7)
* #1 new ManagedObjectController (package:aqueduct/src/http/managed_object_controller.dart:44:14)
* #2 new ModelController (package:openapi_test/model/model_controller.dart:6:45)
* #3 OpenapiTestChannel.entryPoint.<anonymous closure> (package:openapi_test/channel.dart:37:54)
* #4 Controller.link (package:aqueduct/src/http/controller.dart:110:34)
* #5 OpenapiTestChannel.entryPoint (package:openapi_test/channel.dart:37:43)
* #6 ApplicationChannel.documentAPI (package:aqueduct/src/application/channel.dart:166:18)
* #7 Application.document (package:aqueduct/src/application/application.dart:167:38)
* <asynchronous suspension>
* #8 OpenAPIBuilder.execute (<data:application/dart>:17:1821)
* #9 main (<data:application/dart>:13:35)
* #10 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297:32)
* #11 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
****
The failure seems to be in the documentOperations()
method of the ManagedObjectController class. Particularly that it attempts to modify non-existent keys in the ops map under the assumption that all ops exist since it is a ManagedObjectController.
@override
Map<String, APIOperation> documentOperations(
APIDocumentContext context, String route, APIPath path) {
final ops = super.documentOperations(context, route, path);
final entityName = _query.entity.name;
if ((path.parameters
?.where((p) => p.location == APIParameterLocation.path)
?.length ??
0) >
0) {
ops["get"].id = "get$entityName";
ops["put"].id = "update$entityName";
ops["delete"].id = "delete$entityName";
} else {
ops["get"].id = "get${entityName}s";
ops["post"].id = "create$entityName";
}
return ops;
}
I think the problem is that in your router you have subID
, but in the controller you have subId
.
The original issue was on a different codebase with different path vars. I will check this again and ensure the path var names are identical in both the original occurrence and the example reproduction.
I have confirmed that the same exception still occurs after correcting the "subID" to "subId". I have also updated the issue to reflect this.