【问题标题】:Two simultaneous AJAX requests to same action causing error对同一操作的两个同时 AJAX 请求导致错误
【发布时间】:2021-06-15 14:26:14
【问题描述】:

我有以下操作:

public async Task<ActionResult> Cart(bool refresh = false, bool mobile = false)
{

   var user = await Auth.GetUserAsync();
   //rest of the code

}

同时被 2 个 AJAX 调用调用两次(一个用于渲染移动部分,另一个用于渲染普通页面)。

$(document).ready(function () {
   $("basket").html('<i class="fa fa-spinner fa-spin"></i>');
   $('basket').load(PartialURL + "/Cart");
   $('MobileBasket').load(PartialURL + "/Cart?mobile=true");
});

真正的问题出现在Auth.GetUserAsync()函数中。

代码:

  public static async Task<User> GetUserAsync()
    {
        
            if (HttpContext.Current == null || HttpContext.Current.Request == null
                || HttpContext.Current.User == null || HttpContext.Current.Request.IsAuthenticated == false)
                return null;


            //if session does not exist, but user is logged in, fill session information
            if (HttpContext.Current.Session[sessionKey] == null && HttpContext.Current.Request.IsAuthenticated)
                using (var dal = new DAL.DAL())
                {
                    //load user from DB
                    var user = await dal.SingleOrDefaultAsync<User>(m => m.Email == HttpContext.Current.User.Identity.Name);
                    HttpContext.Current.Session[sessionKey] = user;
                }


            return HttpContext.Current.Session[sessionKey] as User;


    }

在其中一个调用中,该函数正常返回用户,但另一个调用产生以下错误(来自 fiddler 的屏幕截图)。注意第一次调用是如何成功的。

SingleOrDefaultAsync 的代码如下:

 public  Task<T> SingleOrDefaultAsync<T>(Expression<Func<T, bool>> predicate) where T : class
    {
        return  _context.Set<T>().SingleOrDefaultAsync(predicate);
    }

我在调试时进行了检查,两个请求中都存在电子邮件,_context 不为空,并且具有请求电子邮件的用户存在,但其中一个总是返回错误。错误是随机返回的。有时在第一个 AJAX 调用中,有时在第二个 AJAX 调用中。

谁能告诉我是什么导致了这个错误?非常感谢任何帮助。

【问题讨论】:

  • 如果您拨打其中一个电话,您是否会在单个电话中遇到错误?
  • @JMJ 不,我不知道。当有 2 个电话时,我才得到它。
  • 两个版本的内容有什么不同?如果您有移动版本,那么在控制器中为单个呼叫进行移动检测肯定会更好,或者只使用相同的内容但不为移动设备呈现所有内容?我真的认为需要一个更好的解决方案,而不是试图解决这个问题。
  • @JMJ 这是一个响应式 HTML 模板,它有 2 个购物车(用于宽屏和窄屏 - 调整窗口大小时)。我知道这可以在一个电话中完成,但是这个错误的原因是什么?为什么它在一个调用中起作用,而在另一个调用中不起作用。
  • @Robert 我是说他们看起来像是在某个地方共享某种资源。一次只能有一个人可以使用该资源,因此其中一个请求将始终失败 - 一个没有首先获取资源的请求。 (可能与会话相关,或数据库)我没有你的确切代码库来调试(不是我现在可以这样做)所以我不能给你 100%。不过,我要说的是,需要关注这个问题,因为无论如何它都不是一个好的实现。

标签: c# asp.net-mvc async-await


【解决方案1】:

我会假设,由于您进行了其他检查,HttpContext.Current.User.Identity.Name(甚至HttpContext.Current.User.Identity)为空,这就是导致错误的原因。

如果第一个请求已导致身份验证过程开始,但该过程尚未完成 - 这样您的空值检查成功,但后续成员访问失败,则可能是这样。换句话说,您有时间问题/竞争条件。不过,这只是一个猜测。

更新:按照我的建议将名称存储在变量中并在 lambda 中使用该变量,一切正常。但是为什么呢?

我的理论是传递给SingleOrDefaultAsync 方法的表达式包含表达式 HttpContext.User.Identity.Name,而不是该表达式的

然后在您的 DAL 中评估此表达式,其中 HttpContext.Current (大概)是 null(假设您的 DAL 不在您的 Web 项目中)。 QED?

【讨论】:

  • 我已经检查了这两个请求,HttpContext.Current.User.Identity.Name 都存在于两者中。
  • 您可以尝试创建一个变量var name = HttpContext.User.Identity.Name 并在您的lambda 中使用它吗?让我们在处理它的时候坚持一个空检查......
  • 看来这行得通。当我将名称存储到变量时,我不再收到该错误。我还添加了一个空检查,但它从未进入。这种行为的原因是什么?
  • 你拯救了这一天。谢谢!
猜你喜欢
  • 1970-01-01
  • 2013-01-21
  • 2015-02-14
  • 1970-01-01
  • 1970-01-01
  • 2019-08-05
  • 1970-01-01
  • 2011-11-28
  • 1970-01-01
相关资源
最近更新 更多