MVC异步

时间:2016-10-07 10:39:05

标签: .net asp.net-mvc asynchronous task control-flow

我对.NET异步任务的经验有限,但我过去使用过BackgroundWorker和IAsyncResult。下面的代码在MVC4项目中。当没有错误时,一切正常。问题是什么时候失败了。异步调用似乎发生了意想不到的事情,我无法解释。

目前,SMTP服务器设置设置为不存在的服务器,因此代码会在对await smtp.SendMailAsync(message);的异步调用中爆炸。而不是对邮件服务器的调用产生错误,错误似乎来自用户创建过程中的某个位置“名称已被采用”。绝对不是这种情况,因为任何随机输入的用户名都会导致该消息(例如:“asdhadsgasgdjasdgj@sadasd.com”)。

我期待的是什么:

  • 创建用户
  • 添加了角色
  • 发送电子邮件的调用失败,生成“连接拒绝邮件服务器”错误。

实际发生的事情:

  • 创建用户
  • 添加了角色
  • 发送电子邮件的调用失败,但错误消息来自IUserStore中.NET的用户创建逻辑中的某处。

我在本地获得了预期的结果,但在服务器上我得到了奇怪的行为。

创建用户方法似乎导致错误:

public virtual Task CreateAsync(User user)
{
     if (user == null)
           throw new ArgumentNullException("user");

     return Task.Factory.StartNew(() =>
     {
           using (SqlConnection cn = new SqlConnection(DbHelper.ConnectionString))
           {
                  cn.Insert<User>(user);
           }
     });
}

注册控制器中的操作:

  [POST("register")]
  [ValidateAntiForgeryToken]
  public async Task<ActionResult> Register(RegisterViewModel vm)
  {
         if (ModelState.IsValid)
         {
               var user = AutoMapper.Mapper.Map<User>(vm);
               user.PasswordDate = DateTime.Now;
               var result = await _userManager.CreateAsync(user); // Error message seems to come from here
               if (result.Succeeded)
               {
                      // Add roles
                      //...
                      foreach (var area in vm.AllowedAreas.Where(a => a.Value))
                             await _userManager.AddClaimAsync(user.Id, new Claim("Area", area.Key));

                      // Generate an email and send it out
                      var thanksForRegisteringVm = new ThanksForRegisteringViewModel();
                      thanksForRegisteringVm.FullName = vm.FullName;
                      thanksForRegisteringVm.EmailAddress = vm.EmailAddress;
                      var emailBody = RenderViewAsString.Render("~/Views/Emails/ThanksForRegistering.cshtml", thanksForRegisteringVm);
                      var message = new MailMessage()
                      {
                             Subject = "Thanks for Registering",
                             Body = emailBody,
                             IsBodyHtml = true
                      };
                      message.To.Add(vm.EmailAddress);
                      var smtp = new SmtpClient();
                      await smtp.SendMailAsync(message); // this will definitely be the true source of the error - a non existant mail server in web.config

                      return RedirectToAction("ThanksForRegistering");
               }
               else
               {
                      foreach (var error in result.Errors)
                             ModelState.AddModelError("", error);
               }
         }

         // If we got this far, something failed, redisplay form
         setUpRegisterViewModel(vm);
         return View(vm);
  }

更新:我们已经将此范围缩小到本地,开发和直播之间的IIS配置中的某个地方。本地和开发工作,生活没有。我们已经消除的事情:

  • 应用程序池(创建一个新的)
  • Elmah(从现场取消)
  • 对ApplicationHost.config

对于GET和POST请求,无论控制器如何,都会调用Action Method两次,但是在抛出异常时。就好像第一个异常导致action方法再次执行一样。

1 个答案:

答案 0 :(得分:0)

在新项目上复制网站并安装Nuget的所有依赖项后,我们最终将其固定到代理服务器 - 运行Cisco IronPort。

可能由于配置错误或基础架构团队有意设置的内容,代理服务器正在向服务器提交两个相同的请求,即使只有一个是从客户端发送的。

禁用代理服务器或从外部(电话)连接访问会导致一个请求。