Powellellogram
Powellellogram

Reputation: 436

Can't get documents by ID in MongoDB Web API

My Get request allows me to get the first document in my collection by ID but won't allow me to get any other documents by ID, so it only ever returns the first document by ID or null. I also have a GetAll request to return all 1000 documents in my database which seems to work.

Here is my code:

Get request in Controller:

 // GET api/something/id
    [HttpGet]
    public HttpResponseMessage Get(string id)
    {

        var something = _somethingService.Get(id);
        if (something != null)
        {
            return Request.CreateResponse(HttpStatusCode.OK, something);

        }
        return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Nothing for provided id.");
    }

Somethings Model:

public class SomethingsModel
{
    [BsonElement("_id")]
    [BsonRepresentation(BsonType.String)]
    public ObjectId id { get; set; }

    public string SomethingId
    {
        get { return id.ToString(); }
        set { id = ObjectId.Parse(value); }
    }

    [BsonElement("name")]
    public string Name { get; set; }

    [BsonElement("description")]
    public string Description { get; set; }
    //[BsonElement("category")]
    //public string Category { get; set; } 

    [BsonElement("address")]
    public AddressModel Address { get; set; }

    [BsonElement("latlong")]
    public LatLongModel LatLong { get; set; }

    [BsonElement("price")]
    public int Price { get; set; }

    [BsonElement("rating")]
    public int Rating { get; set; }

    [BsonElement("photourl")]
    public string PhotoUrl { get; set; }

}

Somethings Service:

 public class SomethingService : ISomethingService
{
    private readonly SomethingsUnitOfWork _sUnitOfwork;

    public SomethingService()
    {
        _sUnitOfwork = new SomethingsUnitOfWork();
    }

    public SomethingsModel Get(string id)
    {
        return _sUnitOfwork.Somethings.Get(id);
    }

    public IQueryable<SomethingsModel> GetAll()
    {
        return _sUnitOfwork.Somethings.GetAll();
    }

    public void Delete(string id)
    {
        _sUnitOfwork.Somethings.Delete(s => s.SomethingId, id);
    }

    public void Insert(SomethingsModel something)
    {
        _sUnitOfwork.Somethings.Add(something);
    }

    public void Update(SomethingsModel something)
    {
        _sUnitOfwork.Somethings.Update(s => s.SomethingId, something.SomethingId, something);
    }

}

SoemthingsRepository:

public class SomethingsRepository<T> where T : class
{
    private MongoDatabase _database;
    private string _tableName;
    private MongoCollection<T> _collection;

    // constructor to initialise database and table/collection  
    public SomethingsRepository(MongoDatabase db, string tblName)
    {
        _database = db;
        _tableName = tblName;
        _collection = _database.GetCollection<T>(tblName);
    }


    /// <summary>
    /// Generic Get method to get record on the basis of id
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public T Get(string id)
    {
        return _collection.FindOneById(id);

    }

    /// <summary>
    /// Get all records 
    /// </summary>
    /// <returns></returns>
    public IQueryable<T> GetAll()
    {
        MongoCursor<T> cursor = _collection.FindAll();
        return cursor.AsQueryable<T>();

    }

    /// <summary>
    /// Generic add method to insert enities to collection 
    /// </summary>
    /// <param name="entity"></param>
    public void Add(T entity)
    {
        _collection.Insert(entity);
    }

    /// <summary>
    /// Generic delete method to delete record on the basis of id
    /// </summary>
    /// <param name="queryExpression"></param>
    /// <param name="id"></param>
    public void Delete(Expression<Func<T, string>> queryExpression, string id)
    {
        var query = Query<T>.EQ(queryExpression, id);
        _collection.Remove(query);
    }

    /// <summary>
    ///  Generic update method to delete record on the basis of id
    /// </summary>
    /// <param name="queryExpression"></param>
    /// <param name="id"></param>
    /// <param name="entity"></param>
    public void Update(Expression<Func<T, string>> queryExpression, string id, T entity)
    {
        var query = Query<T>.EQ(queryExpression, id);
        _collection.Update(query, Update<T>.Replace(entity));
    }

}




And

my document schema:

{
"_id": {
    "$oid": "591593fbb2c2a737588dbbcc"
},
"name": "Kulas Inc",
"description": "Bypass Esophag to Duoden with Synth Sub, Perc Endo Approach",
"address": {
    "lineone": "9 Leroy Terrace",
    "city": "Afonsoeiro",
    "country": "Portugal",
    "postcode": "2870-013"
},
"latlong": {
    "latitude": "38.7",
    "longitude": "-8.9167"
},
"price": 61,
"rating": 70,
"photourl": "http://dummyimage.com/160x221.jpg/dddddd/000000"
}

Apologies for the amount of code. I'm unsure why I'd be able to get the first document in my Collection but none of the others. I have a feeling there's an issue with serilization in my code, or the fact that my _id is nested for each document?

Upvotes: 3

Views: 2513

Answers (1)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236248

Your entity has id of type ObjectId. You should use this type instead of string when you are getting entity from the database:

public T Get(string id)
{
    return _collection.FindOneById(ObjectId.Parse(id));
}

Notes:

  • You can use lower case convention with BsonClassMap to store all elements lowercase by default.
  • MongoDb uses _id name for identity field. You don't need to specify it manually.
  • You can change the return type of methods to IHttpActionResult and use Ok and NotFound methods from ApiController to create appropriate action results.

Upvotes: 1

Related Questions