2016-10-07 6 views
-1

.NET非同期タスクに関する経験は限られていますが、過去にはBackgroundWorkerとIAsyncResultを使用しました。以下のコードはMVC4プロジェクトにあります。エラーがなければ、すべて正常に動作します。問題は、何かが失敗したときです。非同期呼び出しで予期せぬ事態が発生したようで、私は説明することができません。MVC非同期で説明できないフロー

現在、SMTPサーバーの設定は存在しないサーバーに設定されているため、非同期呼び出し時にコードが爆発してawait smtp.SendMailAsync(message);になります。エラーを生成するメールサーバーへの呼び出しではなく、エラーがユーザー作成プロセスのどこかから来ているように見えます。「名前は既に取得されています。ランダムに入力されたユーザー名がメッセージを表示するため、これは間違いではありません(例: "[email protected]")。

私が期待するもの:

  • ユーザーが
  • 役割は、電子メールを送信するために
  • コールを追加しましたエラー「接続がサーバーのメールを拒否した」を生成、失敗している作成されます。

    • ユーザーが
    • 役割が失敗した電子メールを送信するために
    • 呼び出しを追加している作成されますが、エラーメッセージは、.NETのユーザーの作成ロジックのどこかから来ている:

    は、実際に何が起こりますIUserStoreで。

私は期待される結果をローカルに得ていますが、サーバー上で私は奇妙な動作をします。

エラーを引き起こすために見せかけ、ユーザーのメソッドを作成します。

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); 
    } 

更新:を私たちは、どこかの違いにこれを絞り込むましたlocal、dev、liveの間のIIS設定。ローカルとデベロッパーの仕事、ライブはしません。我々は解消しました物事:かかわらず

  • アプリケーションプール(新しいものを作成した)
  • ELMAH(ライブから削除)
  • はapplicationHost.configの

アクションメソッドが二回呼ばなっています、 GETとPOSTの両方の要求に対してはコントローラのうち、例外がスローされたときにはのみです。これは、最初の例外がアクションメソッドを再び実行させるようになっているかのようです。

+3

デバッグを難読化している何かがここにないと確信していますか?要求パイプラインが2回トリガされているため、ユーザーを2回作成しようとしています。論理的にはこのコードに何も問題はありませんので、何らかの環境問題でなければなりません。 –

+1

これはとても奇妙です。設定は私が見る限り同じです。プロダクションサーバー上で実行される異常なことは何もないので、タスクと非同期に関する私の理解に疑問を感じさせます。 – Echilon

+0

これはブラウザが要求を2回提出させるためのものです。要求のロギングを実装し、そこから後方に作業することをお勧めします。私はあなたがこの1つであなたを助けることができるとは思わない –

答えて

0

新しいプロジェクトでサイトを複製し、Nugetからすべての依存関係をインストールした後、私たちは最終的にこれをCisco IronPortを実行するプロキシサーバーに固定しました。

誤った構成やインフラストラクチャチームが意図的に設定したことが原因で、クライアントから1つだけ送信されたとしても、プロキシサーバーは2つの同一の要求をサーバーに送信しています。

プロキシサーバーを無効にするか、外部(電話)接続から訪問すると、1つの要求が発生します。