In short: methods in default Console Application
project works fine, but in the another project(asp.net WebAPI
) the same methods doesn't works. I've a two mongoDB collections, that presented below. Sample document of subjects collection(JSON
):
{
"_id" : ObjectId("5b9a2637635d16b2a2c5c562"),
"userId" : ObjectId("5b9a23d1a54d26b98f6acf34"),
"name" : "someName",
"notes" : [
{
"date" : ISODate("2012-11-20T05:05:15.229Z"),
"title" : "someTitle",
"body" : "Note body - long teeeeeeext",
"files" : [ ]
}
]
}
Sample document of users collection:
{
"_id" : ObjectId("5b9a23d1a54d26b98f6acf34"),
"loginName" : "someName",
"pass" : "hashedpassword"
}
I wrote a few classes (POCO Representation
):
public class Subject
{
[BsonElement("_id")]
public ObjectId Id { get; set; }
[BsonElement("name")]
public string Name { get; set; }
[BsonElement("notes")]
public List<Notes> Notes { get; set; }
[BsonElement("userId")]
public ObjectId UserId { get; set; }
}
public class Notes
{
[BsonElement("date")]
[BsonRepresentation(BsonType.DateTime)]
public DateTime Date { get; set; }
[BsonElement("title")]
public string Title { get; set; }
[BsonElement("body")]
public string Body { get; set; }
[BsonElement("files")]
public List<ObjectId> Files { get; set; }
}
public class User
{
[BsonElement("_id")]
public ObjectId Id { get; set; }
[BsonElement("loginName")]
public string LoginName { get; set; }
[BsonElement("pass")]
public string HashedPass { get; set; }
}
And classes for DB manipulation:
public class MongoDataModel
{
/// <summary>
/// Singleton
/// </summary>
public static MongoDataModel Instance { get; set; }
public IMongoClient MongoClient { get; set; }
public IMongoDatabase CurrentMongoDB { get; set; }
public string CurrentDB { get; set; }
public async Task<List<User>> GetUsers(IMongoDatabase db)
{
List<User> users = await db.GetCollection<User>(MongoSettings.Instanse.UsersCollection)
.Find(new BsonDocument())
.ToListAsync();
return users;
}
public async Task<List<Subject>> GetSubjects(IMongoDatabase db)
{
List<Subject> subjects = await db.GetCollection<Subject>(MongoSettings.Instanse.SubjectCollection)
.Find(new BsonDocument())
.ToListAsync();
return subjects;
}
public MongoDataModel()
{
CurrentDB = "reminder1";
MongoClient = new MongoClient(MongoSettings.Instanse.ClientSettings);
CurrentMongoDB = MongoClient.GetDatabase(CurrentDB);
}
static MongoDataModel()
{
Instance = new MongoDataModel();
}
}
public class MongoSettings
{
public MongoClientSettings ClientSettings { get; set; }
/// <summary>
/// Singleton
/// </summary>
public static MongoSettings Instanse { get; set; }
public string UsersCollection { get; set; }
public string SubjectCollection { get; set; }
private string Host { get; set; }
private int Port { get; set; }
static MongoSettings()
{
Instanse = new MongoSettings()
{
Host = "localhost",
Port = 27017,
UsersCollection = "users",
SubjectCollection = "subjects",
};
Instanse.ClientSettings = new MongoClientSettings
{
Server = new MongoServerAddress(Instanse.Host, Instanse.Port)
};
}
}
Console app code, works ok:
class Program
{
static void Main(string[] args)
{
MongoDataModel.Instance
.GetUsers(MongoDataModel.Instance.CurrentMongoDB)
.GetAwaiter()
.GetResult().ForEach(usr => {
Console.WriteLine("Test user values\nUser id: {0}\nlogin:{1}\nHashed pass:{2}\n",
usr.Id, usr.LoginName, usr.HashedPass);
});
MongoDataModel.Instance
.GetSubjects(MongoDataModel.Instance.CurrentMongoDB)
.GetAwaiter()
.GetResult()
.ForEach(subj => {
Console.WriteLine("Test subject values\nid:{0}\nName:{1}\nNumber of notes:{2}\nNotes:",
subj.Id, subj.Name, subj.Notes.Count);
subj.Notes.ForEach(note => {
Console.WriteLine(" Note Title:{0}\n Note Body:{1}\n NoteDate:{2}",
note.Title, note.Body, note.Date.ToString());
});
});
Console.ReadLine();
}
}
Console output (code above works ok):
Test user values
User id: 5b9a23d1a54d26b98f6acf34
login:someName
Hashed pass:hashedpassword
Test subject values
id:5b9a2637635d16b2a2c5c562
Name:someName
Number of notes:1
Notes:
Note Title:someTitle
Note Body:Note body - long teeeeeeext
NoteDate:11/20/2012 5:05:15 AM
I set JSON formatter as default formatter. ASP.NET WebAPI code:
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<User> Get()
{
List<User> users = MongoDataModel.Instance
.GetUsers(MongoDataModel.Instance.CurrentMongoDB)
.GetAwaiter()
.GetResult();
TestMethod();
return users;
}
private void TestMethod() { }
}
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Formatters.JsonFormatter.SupportedMediaTypes
.Add(new MediaTypeHeaderValue("text/html"));
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
In the Chrome(IIS) doesn't get that values, because method doesn't return the value. First breakpoint works, therefore method executes, but second breakpoint executes never:Chrome debug window Breakpoints
I have no idea what's going on. I'm so confused by that strange code behavior. What's wrong with my code? Please help. Thank you in advance!
Is it deadlocking? If so its beacuse you are mixing async and non-async code and the deadlock is occuring when trying to recapture the synchronization context. Make the code async all the way.
public async Task<IEnumerable<User>> Get()
{
List<User> users = await MongoDataModel.Instance.GetUsers(MongoDataModel.Instance.CurrentMongoDB);
TestMethod();
return users;
}
Task
or Task<T>
should be suffixed with Async
so rename GetUsers
to GetUsersAsync
.