ASP.NET WebAPI 中的无限方法执行(Mongodb 反序列化)
Infinitely method execution (Mongodb Deserialization) in ASP.NET WebAPI
简而言之:默认Console Application
项目中的方法工作正常,但在另一个项目(asp.net WebAPI
) 中相同的方法不起作用。我有两个 mongoDB 集合,如下所示。 subjects 集合(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" : [ ]
}
]
}
用户集合的示例文档:
{
"_id" : ObjectId("5b9a23d1a54d26b98f6acf34"),
"loginName" : "someName",
"pass" : "hashedpassword"
}
我写了几个类(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; }
}
和 类 用于数据库操作:
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)
};
}
}
控制台应用程序代码,工作正常:
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();
}
}
控制台输出(上面的代码工作正常):
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
我将 JSON 格式化程序设置为默认格式化程序。 ASP.NET WebAPI 代码:
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 }
);
}
}
在 Chrome(IIS) 中没有得到那个值,因为方法没有 return 这个值。
第一个断点有效,因此方法执行,但第二个断点从不执行:Chrome debug window Breakpoints
我不知道发生了什么。我对这种奇怪的代码行为感到很困惑。我的代码有什么问题?请帮忙。提前致谢!
是死锁了吗?如果是这样,那是因为您混合了异步和非异步代码,并且在尝试重新捕获同步上下文时发生了死锁。让代码一路异步。
public async Task<IEnumerable<User>> Get()
{
List<User> users = await MongoDataModel.Instance.GetUsers(MongoDataModel.Instance.CurrentMongoDB);
TestMethod();
return users;
}
- 有关详细信息,请参阅标记的副本
- 您应该使用与 Microsoft 相同的命名约定,即任何 returns
Task
或 Task<T>
都应以 Async
为后缀,因此重命名 GetUsers
到 GetUsersAsync
.
- 如果要使用异步,请在整个调用堆栈中使用它。
简而言之:默认Console Application
项目中的方法工作正常,但在另一个项目(asp.net WebAPI
) 中相同的方法不起作用。我有两个 mongoDB 集合,如下所示。 subjects 集合(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" : [ ]
}
]
}
用户集合的示例文档:
{
"_id" : ObjectId("5b9a23d1a54d26b98f6acf34"),
"loginName" : "someName",
"pass" : "hashedpassword"
}
我写了几个类(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; }
}
和 类 用于数据库操作:
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)
};
}
}
控制台应用程序代码,工作正常:
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();
}
}
控制台输出(上面的代码工作正常):
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
我将 JSON 格式化程序设置为默认格式化程序。 ASP.NET WebAPI 代码:
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 }
);
}
}
在 Chrome(IIS) 中没有得到那个值,因为方法没有 return 这个值。 第一个断点有效,因此方法执行,但第二个断点从不执行:Chrome debug window Breakpoints
我不知道发生了什么。我对这种奇怪的代码行为感到很困惑。我的代码有什么问题?请帮忙。提前致谢!
是死锁了吗?如果是这样,那是因为您混合了异步和非异步代码,并且在尝试重新捕获同步上下文时发生了死锁。让代码一路异步。
public async Task<IEnumerable<User>> Get()
{
List<User> users = await MongoDataModel.Instance.GetUsers(MongoDataModel.Instance.CurrentMongoDB);
TestMethod();
return users;
}
- 有关详细信息,请参阅标记的副本
- 您应该使用与 Microsoft 相同的命名约定,即任何 returns
Task
或Task<T>
都应以Async
为后缀,因此重命名GetUsers
到GetUsersAsync
. - 如果要使用异步,请在整个调用堆栈中使用它。