Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return BsonDocument in ApiController

I'm working on an API in ASP.NET MVC 4, I'm using MongoDB as a backend.

Due to MongoDB storing and returning BSON objects, and MVC4 returning JSON objects, I figured that it would be rather easy to simply return the BSON on the rest calls.

This didn't work, so I found the .toJson() method on th BsonDocument class, converts the BSON object to a JSON-string representation. Unfortunately when I return this string through my ApiController, MVC apparently thinks it should re-serialize the string as JSON, which the browser can't interpret.

So I would like to ask if there is a way to disable the JSON serialization for a specific ApiController method?

My current workaround is to de-serialize the JSON returned from .toJson() before returning it such that it will be serialized again, but this seems rather wasteful.

like image 644
FrederikNS Avatar asked Sep 19 '12 08:09

FrederikNS


People also ask

Can Apicontroller return view?

You can return one or the other, not both. Frankly, a WebAPI controller returns nothing but data, never a view page. A MVC controller returns view pages.

Does Web API support BSON format?

Web API 2.1 introduces support for BSON.

What is BSON file?

BSON stands for Binary Javascript Object Notation. It is a binary-encoded serialization of JSON documents. BSON has been extended to add some optional non-JSON-native data types, like dates and binary data.


3 Answers

I encountered this problem too, I took the Bson data, iterated through it converting each document to json at the Web API end, as I presume you did, creating a list of json strings - I sent this back and deserialized each string back to a Bson Document:

List<string> data = response.Content.ReadAsAsync<List<string>>().Result;

List<BsonDocument> docList = new List<BsonDocument>();
foreach (string dataStr in data) {
    BsonDocument doc = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>(dataStr);
    docList.Add(doc);                 
}

Which I found in this post: Convert string into MongoDB BsonDocument

Bit ham fisted, but it works.

like image 115
Dale Avatar answered Oct 14 '22 02:10

Dale


Presumably you have a schema associated with your application and the resource your api controller is attempting to return. By forcing it to use json, you are ignoring many of the benefits of the WebApi by completely sidestepping content negotiation. What if your client wants xml or yaml or ...

The issue you are experiencing is that WebApi doesn't know how to serialize a BsonDocument. So, you could write a ModelBinder for it such that it knows how to deal with it. Alternatively, and alluding to my first paragraph, create strongly typed entity/resource classes and since both MongoDB and WebApi already know about these types, they'll be able to work with them natively.

like image 43
Craig Wilson Avatar answered Oct 14 '22 02:10

Craig Wilson


I face the same thing and wanted to simplify the back-end code.

I found Support for dynamic is simply works since driver v2.0, early this year. Just replace BsonDocument with dynamic keyword like this:

public async Task<dynamic> GetAll(string collectionName)
{
    //var collection = db.GetCollection<BsonDocument>(collectionName);
    //var result = await collection.Find(new BsonDocument()).ToListAsync();
    var collection = db.GetCollection<dynamic>(collectionName);
    return await collection.Find(new BsonDocument()).ToListAsync();
}

and also for insert:

var collection = db.GetCollection<dynamic>(collectionName);
await collection.InsertManyAsync(new List<dynamic>()
{
    new
    {
        PointType = "Building",
        Name = "My Place",
        Location = GeoJson.Point(GeoJson.Position(lng, lat))
    }
});

It is really helpful to create migration script. However don't accept dynamic or 'anything' from client site.

like image 1
CallMeLaNN Avatar answered Oct 14 '22 04:10

CallMeLaNN