Search code examples
mongodbasp.net-coremongodb-.net-drivergeneric-programmingwebapi

How to write a Generic ASP.NET Core ApiController to do MongoDB CRUD operations from Client Side?


How to write a Generic ASP.NET Core ApiController to do MongoDB CRUD operations from Client Side Frameworks like Angular/React.

Note : Firebase offer such client side library for firestore and database


Solution

  • You can create a request payload definition that would contain an object (or collection) name, operation (Insert, Replace, Delete or any other that you want to support) and the object itself. Inject mongo database object into controller, get a collection by name and apply the operation. Pseudo code may look like this:

    class Operation
    {
        OperationType Type {get; set;}
        JObject Object {get; set;}
        string ObjectId {get; set;}
        string ObjectName {get; set;}
    }
    
    [HttpPost]
    public async Task<IActionResult> Apply(Operation operation)
    {
        WriteModel<BsonDocument> model = null;
    
        switch (operation.Type)
        {
            case OperationType.Insert:
                model = new InsertOneModel(ConvertToBsonDocument(operation.Object));
                break;
            case OperationType.Replace:
                model = new ReplaceOneModel(operation.ObjectId, ConvertToBsonDocument(operation.Object));
                break;
            case OperationType.Delete:
                model = new DeleteOneModel(operation.ObjectId);
                break;
        }
    
        await mongoDatabase.GetCollection<BsonDocument>(operation.ObjectName).BultWriteAsync(new[] {model});
    
        return Ok();
    }
    

    Or, to make operations to aligned with http spec and for better separation, you can split the logic across multiple actions:

    [HttpGet("{name}/{objectId}")]
    public async Task<IActionResult> Get(string name, string objectId)
    {
        var document = await mongoDatabase.GetCollection<BsonDocument>(name).Find(new BsonDocument("_id", ObjectId.Parse(objectId))).FirstOrDefaultAsync();
    
        var dotNetObj = BsonTypeMapper.MapToDotNetValue(document);
        var json = JsonConvert.SerializeObject(dotNetObj);
    
        return document is null
            ? NotFound()
            : (IActionResult)Content(json, "application/json");
    }
    
    
    [HttpPost("{name}")]
    public async Task<IActionResult> Post(string name, JsonElement @object)
    {
        await mongoDatabase.GetCollection<BsonDocument>(name).InsertOneAsync(ConvertToBsonDocument(operation.Object));
        return Ok();
    }
    
    [HttpPut("{name}/{objectId}")]
    public async Task<IActionResult> Put(string name, string objectId, JsonElement @object)
    {
        await mongoDatabase.GetCollection<BsonDocument>(name).ReplaceOneAsync(new BsonDocument("_id", ObjectId.Parse(objectId), ConvertToBsonDocument(operation.Object));
        return Ok();
    }
    
    [HttpDelete("{name}/{objectId}")]
    public async Task<IActionResult> Delete(string name, string objectId)
    {
        await mongoDatabase.GetCollection<BsonDocument>(name).DeleteOneAsync(new BsonDocument("_id", ObjectId.Parse(objectId));
        return Ok();
    }