Asp.net MVC4Web应用程序中对webservice的异步调用
我正在构建我的第一个真正的MVC4应用程序,我遇到了以下问题 我有一个“用户”类的模型。它的数据通过对webservice的异步调用获得:Asp.net MVC4Web应用程序中对webservice的异步调用,asp.net,asp.net-mvc-4,webservice-client,Asp.net,Asp.net Mvc 4,Webservice Client,我正在构建我的第一个真正的MVC4应用程序,我遇到了以下问题 我有一个“用户”类的模型。它的数据通过对webservice的异步调用获得: public sealed class AdminDMSEntities { public List<User> UserList { get; private set; } public AdminDMSEntities() { this.UserList = new List<User>(
public sealed class AdminDMSEntities
{
public List<User> UserList { get; private set; }
public AdminDMSEntities()
{
this.UserList = new List<User>(0);
ServiceClient client = new ServiceClient();
client.GetUsersCompleted += (s, e) =>
{
if (e.Result == null)
throw new ArgumentNullException("No users were retrieved");
UserList = new List<User>(0);
e.Result.ForEach(w => this.UserList.Add(new User(w.Guid, w.TrusteeType, w.Username, w.Email, w.LastLogin, w.PasswordChanged, w.IsUsingTempPassword)));
};
client.GetUsersAsync();
}
}
问题是,我将以InvalidOperationException结束,因为控制器并没有等待异步调用完成,而是在正确填充用户之前将UserList传递给视图
我可以暂时让调用同步,但很可能以后我会被迫使用异步调用,所以我想知道如何确保控制器在将UserList传递给view之前等待异步调用完成
提前谢谢
编辑:我已尝试使用AsyncController的方法,如下所示,目前我已将其添加到AdminDMS实体类中:
public static async Task<AdminDMSEntities> AdminDMSEntitiesAsync()
{
AdminDMSEntities result = null;
Task<AdminDMSEntities> getUsersAsyncTask = Task.Factory.StartNew(() => new AdminDMSEntities());
await getUsersAsyncTask;
return result;
}
公共静态异步任务AdminsEntitiesAsync()
{
AdminDMSEntities结果=null;
Task getUsersAsyncTask=Task.Factory.StartNew(()=>newadmindmsentities());
等待getUsersAsyncTask;
返回结果;
}
这是对控制器的更改:
public class UsersController : AsyncController
{
private AdminDMSEntities adminEntities = null;
//
// GET: /User/
public async Task<ActionResult> Index()
{
if (adminEntities == null)
{
adminEntities = await AdminDMSEntities.AdminDMSEntitiesAsync();
}
return View(adminEntities.UserList);
}
}
公共类UsersController:AsyncController
{
private AdminDMSEntities adminEntities=null;
//
//获取:/User/
公共异步任务索引()
{
如果(adminEntities==null)
{
adminEntities=等待AdminDMSEntities.AdminDMEntitiesAsync();
}
返回视图(adminEntities.UserList);
}
}
结果是adminEntities包含类的实例,但列表中没有用户(应该有11个)
EDIT2:因为有人告诉我创建新任务不是正确的做法,所以我采用了第一种建议的方法从代码中删除AdminDMSEntities类。我感谢达林帮了我的忙:)你可以用一个电话。其思想是让控制器从类派生,而不是从控制器
类派生。此类提供了允许您执行异步操作的方法
例如:
public class MyController: AsyncController
{
public void IndexAsync()
{
AsyncManager.OutstandingOperations.Increment();
var client = new SomeClient();
client.GetUsersCompleted += (s, e) =>
{
UserList = new List<User>();
AsyncManager.Parameters["users"] = e.Result.Select(
w => new User(
w.Guid,
w.TrusteeType,
w.Username,
w.Email,
w.LastLogin,
w.PasswordChanged,
w.IsUsingTempPassword
)
)
.ToList();
AsyncManager.OutstandingOperations.Decrement();
};
client.GetUsersAsync();
}
public ActionResult IndexCompleted(IEnumerable<User> users)
{
return View(users);
}
}
你可以用一个。其思想是让控制器从类派生,而不是从控制器
类派生。此类提供了允许您执行异步操作的方法
例如:
public class MyController: AsyncController
{
public void IndexAsync()
{
AsyncManager.OutstandingOperations.Increment();
var client = new SomeClient();
client.GetUsersCompleted += (s, e) =>
{
UserList = new List<User>();
AsyncManager.Parameters["users"] = e.Result.Select(
w => new User(
w.Guid,
w.TrusteeType,
w.Username,
w.Email,
w.LastLogin,
w.PasswordChanged,
w.IsUsingTempPassword
)
)
.ToList();
AsyncManager.OutstandingOperations.Decrement();
};
client.GetUsersAsync();
}
public ActionResult IndexCompleted(IEnumerable<User> users)
{
return View(users);
}
}
它看起来像我需要的,但我无法让它运行。我的GetUsersAsync方法来自自动生成的服务引用,它返回“void”,所以我在我的原始帖子中使用了构造函数中的代码,我必须使用
wait task.Factory.StartNew(()=>client.GetUsersAsync())创建任务代码>非起始null仍在传递给视图。不应创建新任务。您应该在控制器操作中直接使用自动生成的客户端实例。然后订阅GetUsersCompleted
事件,如我的回答所示。我删除了前面的评论,我刚刚找到了自动生成方法的定义。我将尝试您的方法,然后再与您联系。我查看了定义,自动生成的方法只返回“void”。所以我试着在我原来的帖子里用“编辑”这个词。不过,最好使用异步方法返回用户数组或用户列表,然后我可以使用异步方法接受您的建议。现在我将尝试第一种解决方案第一种解决方案工作正常。但我更喜欢async Wait解决方案,我需要弄清楚如何更改服务的方法来尝试它。它看起来像我需要的,但我无法让它运行。我的GetUsersAsync方法来自自动生成的服务引用,它返回“void”,所以我在我的原始帖子中使用了构造函数中的代码,我必须使用wait task.Factory.StartNew(()=>client.GetUsersAsync())创建任务代码>非起始null仍在传递给视图。不应创建新任务。您应该在控制器操作中直接使用自动生成的客户端实例。然后订阅GetUsersCompleted
事件,如我的回答所示。我删除了前面的评论,我刚刚找到了自动生成方法的定义。我将尝试您的方法,然后再与您联系。我查看了定义,自动生成的方法只返回“void”。所以我试着在我原来的帖子里用“编辑”这个词。不过,最好使用异步方法返回用户数组或用户列表,然后我可以使用异步方法接受您的建议。现在我将尝试第一种解决方案第一种解决方案工作正常。但我更喜欢AsyncWait解决方案,我需要弄清楚如何更改服务的方法来尝试它。
public class MyController: AsyncController
{
public async Task<ActionResult> Index()
{
var client = new SomeClient();
var users = await client.GetUsersAsync().Select(
w => new User(
w.Guid,
w.TrusteeType,
w.Username,
w.Email,
w.LastLogin,
w.PasswordChanged,
w.IsUsingTempPassword
)
)
.ToList();
return View(users);
}
}