From c4fe73bd97e91e3ff5913aec22285072d820f6fa Mon Sep 17 00:00:00 2001 From: Alastair Crabtree Date: Sat, 13 Feb 2021 17:43:39 +0000 Subject: [PATCH 1/2] task: improve docs for custom persistence options --- README.md | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1546701..bdf3b4d 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ dotnet add package JsonApiDotNetCore.MongoDb ### Models ```cs +// MongoDbIdentifiable is just a utility base class, could use IIdentifiable instead public sealed class Book : MongoDbIdentifiable { [Attr] @@ -63,14 +64,16 @@ public class Startup } } ``` + Note: If your API project uses only MongoDB (not in combination with EF Core), then instead of registering all MongoDB resources and repositories individually, you can use: + ```cs public class Startup { public IServiceProvider ConfigureServices(IServiceCollection services) { - // ... + // ... services.AddJsonApi(facade => facade.AddCurrentAssembly()); services.AddJsonApiMongoDb(); @@ -85,6 +88,60 @@ public class Startup } ``` +### Customise MongoDB persistence options and _id generation + +In addition to `MongoDbIdentifiable` your resource classes are free to use any of the MongoDB driver persistence options or inherit from their own base class. + +For example, you could change the example above so that the `Book` resource has string IDs rather than object ids in the DB, but still have them generated server side: + +```cs +public class Book : IIdentifiable +{ + // If Id=null generate a random string ID using the MongoDB driver + [BsonId(IdGenerator = typeof(StringObjectIdGenerator))] + [Attr] + public virtual string Id { get; set; } + + // override the attribute name in the db + [BsonElement("bookName")] + [Attr] + public string Name { get; set; } + + // all json:api resources need this + [BsonIgnore] + public string StringId { get => Id; set => Id = value; } +} +``` + +Resources just need to inherit from the base `IIdentifiable` interface from JsonApiDotNetCore (or the provided default `MongoDbIdentifiable`) and then just use any of usual [MongoDB Driver mapping code](https://mongodb.github.io/mongo-csharp-driver/2.12/reference/bson/mapping/). + +You could also achieve the exact same result using MongoDB `BsonClassMap` [rather than attributes](https://mongodb.github.io/mongo-csharp-driver/2.11/reference/bson/mapping/) so your `Book` does not need any MongoDB specific code like below. + +```cs + // in startup + BsonClassMap.RegisterClassMap(cm => + { + cm.AutoMap(); + cm.MapIdProperty(x => x.Id).SetIdGenerator(StringObjectIdGenerator.Instance); + cm.UnmapMember(x=>x.StringId); + }); +``` + +Using `StringObjectIdGenerator` above could then be combined with `AllowClientGeneratedIds` JsonApi setting in `Startup.ConfigureServices` so that IDs can be generated on the client, and will be auto-assigned server side if not provided providing a flexible string based id for the `Book` resource: + +```cs + services.AddJsonApi(options => { + // Allow us to POST books with already assigned IDs! + options.AllowClientGeneratedIds = true; + }, resources: builder => + { + builder.Add(); + }); + services.AddJsonApiMongoDb(); + + services.AddResourceRepository>(); +``` + ## Development Restore all NuGet packages with: From 7471cba2a070b97955f0ad3fb0316bf82e1c225a Mon Sep 17 00:00:00 2001 From: Alastair Crabtree Date: Wed, 17 Feb 2021 00:08:41 +0000 Subject: [PATCH 2/2] doc: fix docs on MongoDbIdentifiable and describe client id generation --- README.md | 44 ++++++++++++++------------------------------ 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index bdf3b4d..ef3c2ed 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,6 @@ dotnet add package JsonApiDotNetCore.MongoDb ### Models ```cs -// MongoDbIdentifiable is just a utility base class, could use IIdentifiable instead public sealed class Book : MongoDbIdentifiable { [Attr] @@ -90,48 +89,33 @@ public class Startup ### Customise MongoDB persistence options and _id generation -In addition to `MongoDbIdentifiable` your resource classes are free to use any of the MongoDB driver persistence options or inherit from their own base class. +`MongoDbIdentifiable` has some sensible defaults for storing documents with _ids, but these need to be customised and overridden if you want client side or string based ids. -For example, you could change the example above so that the `Book` resource has string IDs rather than object ids in the DB, but still have them generated server side: +For example, you could change the example above so that the `Book` resource has string IDs rather than object ids in the DB, (so far still generated server side). -```cs -public class Book : IIdentifiable -{ - // If Id=null generate a random string ID using the MongoDB driver - [BsonId(IdGenerator = typeof(StringObjectIdGenerator))] - [Attr] - public virtual string Id { get; set; } - - // override the attribute name in the db - [BsonElement("bookName")] - [Attr] - public string Name { get; set; } - - // all json:api resources need this - [BsonIgnore] - public string StringId { get => Id; set => Id = value; } -} -``` - -Resources just need to inherit from the base `IIdentifiable` interface from JsonApiDotNetCore (or the provided default `MongoDbIdentifiable`) and then just use any of usual [MongoDB Driver mapping code](https://mongodb.github.io/mongo-csharp-driver/2.12/reference/bson/mapping/). - -You could also achieve the exact same result using MongoDB `BsonClassMap` [rather than attributes](https://mongodb.github.io/mongo-csharp-driver/2.11/reference/bson/mapping/) so your `Book` does not need any MongoDB specific code like below. +Resources properties can use any of usual [MongoDB Driver mapping code](https://mongodb.github.io/mongo-csharp-driver/2.12/reference/bson/mapping/) so to achieve string based ids you have to [override the json:api resource class attributes](https://mongodb.github.io/mongo-csharp-driver/2.11/reference/bson/mapping/) using `BsonClassMap`: ```cs - // in startup + // in startup change to string generated ids for MongoDbIdentifiable + BsonClassMap.RegisterClassMap(cm => + { + cm.MapIdProperty(x => x.Id) + .SetIdGenerator(StringObjectIdGenerator.Instance); + }); + + // optionally you can also change the mapping for resources here BsonClassMap.RegisterClassMap(cm => { cm.AutoMap(); - cm.MapIdProperty(x => x.Id).SetIdGenerator(StringObjectIdGenerator.Instance); - cm.UnmapMember(x=>x.StringId); + cm.MapProperty(x => x.Name).SetElementName("bookName"); }); ``` -Using `StringObjectIdGenerator` above could then be combined with `AllowClientGeneratedIds` JsonApi setting in `Startup.ConfigureServices` so that IDs can be generated on the client, and will be auto-assigned server side if not provided providing a flexible string based id for the `Book` resource: +The `StringObjectIdGenerator` above can then be combined with `AllowClientGeneratedIds` JsonApi setting in `Startup.ConfigureServices` so that string IDs can be generated on the client, but will be auto-assigned to random strings server side if not provided. This style of ids will be more familiar to developers used to no-sql style databases. ```cs services.AddJsonApi(options => { - // Allow us to POST books with already assigned IDs! + // Allow us to POST books with already assigned IDs options.AllowClientGeneratedIds = true; }, resources: builder => {