Skip to content

alastairtree/JsonApiDotNetCore.MongoDb

 
 

Repository files navigation

MongoDB support for JsonApiDotNetCore

Plug-n-play implementation of IResourceRepository<TResource, TId> allowing you to use MongoDB with your JsonApiDotNetCore APIs.

Build status NuGet

Installation and Usage

dotnet add package JsonApiDotNetCore.MongoDb

Models

public sealed class Book : MongoDbIdentifiable
{
    [Attr]
    public string Name { get; set; }
}

Controllers

public sealed class BooksController : JsonApiController<Book, string>
{
    public BooksController(IJsonApiOptions options, ILoggerFactory loggerFactory, IResourceService<Book, string> resourceService)
        : base(options, loggerFactory, resourceService)
    {
    }
}

Middleware

public class Startup
{
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IMongoDatabase>(sp =>
        {
            var client = new MongoClient(Configuration.GetSection("DatabaseSettings:ConnectionString").Value);
            return client.GetDatabase(Configuration.GetSection("DatabaseSettings:Database").Value);
        });

        services.AddJsonApi(resources: builder =>
        {
            builder.Add<Book, string>();
        });
        services.AddJsonApiMongoDb();

        services.AddResourceRepository<MongoDbRepository<Book, string>>();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseRouting();
        app.UseJsonApi();
        app.UseEndpoints(endpoints => endpoints.MapControllers());
    }
}

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:

public class Startup
{
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        // ...

        services.AddJsonApi(facade => facade.AddCurrentAssembly());
        services.AddJsonApiMongoDb();

        services.AddScoped(typeof(IResourceReadRepository<>), typeof(MongoDbRepository<>));
        services.AddScoped(typeof(IResourceReadRepository<,>), typeof(MongoDbRepository<,>));
        services.AddScoped(typeof(IResourceWriteRepository<>), typeof(MongoDbRepository<>));
        services.AddScoped(typeof(IResourceWriteRepository<,>), typeof(MongoDbRepository<,>));
        services.AddScoped(typeof(IResourceRepository<>), typeof(MongoDbRepository<>));
        services.AddScoped(typeof(IResourceRepository<,>), typeof(MongoDbRepository<,>));
    }
}

Customise MongoDB persistence options and _id generation

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, (so far still generated server side).

Resources properties can use any of usual MongoDB Driver mapping code so to achieve string based ids you have to override the json:api resource class attributes using BsonClassMap:

    // in startup change to string generated ids for MongoDbIdentifiable
    BsonClassMap.RegisterClassMap<MongoDbIdentifiable>(cm =>
    {
        cm.MapIdProperty(x => x.Id)
            .SetIdGenerator(StringObjectIdGenerator.Instance);
    });

    // optionally you can also change the mapping for resources here
    BsonClassMap.RegisterClassMap<Book>(cm =>
    {
        cm.AutoMap();
        cm.MapProperty(x => x.Name).SetElementName("bookName");
    });

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.

    services.AddJsonApi(options => {
        // Allow us to POST books with already assigned IDs
        options.AllowClientGeneratedIds = true;
    }, resources: builder =>
    {
        builder.Add<Book, string>();
    });
    services.AddJsonApiMongoDb();

    services.AddResourceRepository<MongoDbRepository<Book, string>>();

Development

Restore all NuGet packages with:

dotnet restore

Testing

You don't need to have a running instance of MongoDB on your machine. To run the tests just type the following command in your terminal:

dotnet test

If you want to run the examples and explore them on your own you are going to need that running instance of MongoDB. If you have docker installed you can launch it like this:

docker run -p 27017:27017 -d mongo:latest

And then to run the API:

dotnet run

Limitations

  • Relationships are not supported

About

MongoDB support for JsonApiDotNetCore

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C# 99.0%
  • Other 1.0%