【发布时间】:2021-04-30 14:51:34
【问题描述】:
我开发了一个 MVC 5 应用程序。
在控制器内部,我有这个动作:
// POST: Usuario/Edit
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<JsonResult> Edit(UsuarioViewModel model)
{
//
// some tasks
//
//
return Json("Some text", JsonRequestBehavior.AllowGet);
}
在提交 html 表单后调用该操作时,System.Web.HttpContext.Current 不为空。我在代码的某处使用了该对象。
现在,我需要从同一个控制器中的其他操作方法调用这个相同的操作方法。在这种情况下,System.Web.HttpContext.Current 为空,显然会导致应用程序抛出空对象异常。
动作方法和调用分别是:
// POST: Usuario/CreateFromStaff
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<JsonResult> CreateFromStaff(int[] trabajadores)
{
//
// some tasks
//
//
UsuarioViewModel model = new UsuarioViewModel();
//
// model properties assignments
//
//
JsonResult json = Task.Run(async () => await Edit(model)).Result; // When this call is made, the Http context get lost.
}
我该怎么做才能保留 http 上下文?或者,我该如何打那个电话?
问题编辑:
只是为了更清楚。 Edit 操作方法是存储记录的标准方法,在本例中是用户记录。在这个动作方法的某个时刻,我有:
await db.SaveChangesAsync();
另一方面,JsonResult json = Task.Run(async () => await Edit(model)).Result; 在 ForEach 方法中。在那个循环之后,我需要保存其他数据,以便在它之后使用另一个await db.SaveChangesAsync();。
如果我将 ForEach 方法配置为 async,我总是遇到第二个 await db.SaveChangesAsync(); 的问题。抛出一个错误,告知某些数据库操作不完整。这就是为什么我使用.Result 和ForEach 方法而不是async。
谢谢 詹姆
【问题讨论】:
-
为什么在 MVC 应用程序中使用
HttpContext.Current?你真的应该尽量避免这样做。其次,不要在 Task 实例上使用 .Result ,这会导致运行时死锁。在调用堆栈中一直使用 async/await。此外,async/await 将捕获包含HttpContext.Current的同步上下文,假设您没有使用低于 4.6 的 .net 运行时版本的ConfigureAwait(false)。 -
如果您需要访问 HttpContext,您可以使用 IoC / DI 框架在您的类型中注册和注入 HttpContextBase。真的,虽然我会尽可能避免一起使用它。
-
我需要
HttpContext.Current,因为在辅助类中我需要获取调用哪个控制器来执行审计任务。该助手类位于控制器之外,因此我需要以这种方式获取上下文。我正在使用.Result,因为异步方法位于 ForEach 循环中。在那个循环之后我有await db.SaveChangesAsync();。由于Edit方法内部是另一个await db.SaveChangesAsync();调用,所以我总是遇到问题。也许这个问题是针对其他问题的。这时候就需要解决http上下文的问题了。 -
@Igor 除了我的其他评论外,我还编辑了问题以解释为什么我需要使用
.Result。你是对的,我根本没有使用ConfigureAwait....所以默认情况下,它是ConfigureAwait(true) -
@Igor 如果我需要从控制器外部的其他类中知道出于审计目的而调用的控制器,我该怎么做?目前,我知道的唯一方法是通过 HttpContext。
标签: c# asp.net-mvc httpcontext