【问题标题】:System.Web.HttpContext.Current get lostSystem.Web.HttpContext.Current 迷路了
【发布时间】: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 () =&gt; await Edit(model)).Result;ForEach 方法中。在那个循环之后,我需要保存其他数据,以便在它之后使用另一个await db.SaveChangesAsync();

如果我将 ForEach 方法配置为 async,我总是遇到第二个 await db.SaveChangesAsync(); 的问题。抛出一个错误,告知某些数据库操作不完整。这就是为什么我使用.ResultForEach 方法而不是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


【解决方案1】:

我该怎么做才能保留 http 上下文?或者,我该如何打那个电话?

删除Task.Run 调用。你应该strongly avoid ever using Task.Run on ASP.NET

JsonResult json = Task.Run(async () =&gt; await Edit(model)).Result;ForEach 方法内...如果我将ForEach 方法配置为async... 会抛出错误,提示某些数据库操作不完整。这就是为什么我使用.ResultForEach 方法不是异步的。

确实,ForEach 方法不能正确理解async lambdas,如果你将它的lambdas 设为async,那么你最终会得到async void lambdas,即should be avoided。那将是cause the "asynchronous operation incomplete" errors

我假设修复是这样的:

  1. ForEach 不适用于 async,所以我需要使其同步。
  2. Blocking didn't work,所以我需要使用Task.Run来避免死锁。
  3. 好吧,现在我没有收到HttpContext.Current。如何获得HttpContext.Current

但更好的解决方法是:

  1. ForEach 不适用于 async,所以我需要使用 ForEach 以外的东西。

ForEach 更改为foreach 会以更好的方式解决您的问题。

【讨论】:

    猜你喜欢
    • 2017-03-02
    • 2018-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-03
    • 2022-01-23
    • 2015-02-07
    相关资源
    最近更新 更多