2017-05-15 9 views
1

私はアプリケーションがASP.netコアであり、支払いを処理するためにspreedly支払いゲートウェイが統合されています。私のログファイルでは、支払いコントローラが2回実行されることがあります。私は、リクエストが受信された時刻に基づいてIDを生成し、IDは時には1秒だけ離れている場合もあれば、まったく同じ時刻にある場合もあります。これにより、カードが2回しか充電されない場合があります。私はこれを引き起こす可能性があるものを把握しているようだ。続きASP.Netコアアクションコントローラが2回呼び出されることがあります

は私が

を使用していたユーザは、申込書を記入し、支払ボタンをクリックして、私はspreedly

$('#REG').click(function() { 
      var options = { 
       company_name: "abcd", 
       sidebar_top_description: "Fees", 
       sidebar_bottom_description: "Only Visa and Mastercard accepted", 
       amount: "@string.Format("{0:c}",Convert.ToDecimal(Model.FeeOutstanding))" 
      } 
      document.getElementById('payment').value = 'App' 
      SpreedlyExpress.init(environmentKey, options); 
      SpreedlyExpress.openView(); 
      $('#spreedly-modal-overlay').css({ "position": "fixed", "z-index": "9999", "bottom": "0", "top": "0", "right": "0", "left": "0" }); 
     }); 

これはとしてspreedly支払いフォームが開きますトリガするために、このコードを使用していたコードですユーザーがすべてのカード情報を入力して支払いボタンを押すポップアップ。支払コントローラに実行する

public async Task<IActionResult> Index(DynamicViewModel model) 
{ 
    if (ModelState.IsValid) 
    { 
     try 
     { 
      if (TempData.ContainsKey("PaymentFlag") && !String.IsNullOrEmpty(TempData["PaymentFlag"].ToString())) 
      { 
       // Some code logic that calls few async methods 
       //generate a id based on the time of current request 
       "APP-" + DateTime.Now.ToString("yyyyMMddHmmss-") + model.UserID; 

       // ... Other code here  
} 

私が生成するIDが記録され、私はそれはIDが正確に同じ時間のいずれかを有するかを顧客のために二回走ったログファイル内のいくつかの回があったことがわかります1秒差。私はダブルクリックのシナリオをテストして、ダブルクリックを防ぐためのコードもいくつか入れました。しかし、私はなぜこのようなことが起こるのか理解できないようです。それは頻繁ではありません。 100件の支払いでそのような1件が発生します。

私は重複要求を処理するためのアクション属性を持っています。このコードを入力すると、重複要求の数は停止しましたが、完全には停止しませんでした。まだコントローラが2回呼び出される方法はほとんどありません。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] 
public class NoDuplicateRequestAttribute : ActionFilterAttribute 
{ 
    public int DelayRequest = 10; 
    // The Error Message that will be displayed in case of 
    // excessive Requests 
    public string ErrorMessage = "Excessive Request Attempts Detected."; 

    // This will store the URL to Redirect errors to 
    public string RedirectURL; 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     // Store our HttpContext (for easier reference and code brevity) 
     var request = filterContext.HttpContext.Request; 
     // Store our HttpContext.Cache (for easier reference and code brevity) 
     var cache = filterContext.HttpContext.RequestServices.GetService<IMemoryCache>(); 

     // Grab the IP Address from the originating Request (example) 
     var originationInfo = request.HttpContext.Connection.RemoteIpAddress.ToString() ?? request.HttpContext.Features.Get<IHttpConnectionFeature>()?.RemoteIpAddress.ToString(); 

     // Append the User Agent 
     originationInfo += request.Headers["User-Agent"].ToString(); 

     // Now we just need the target URL Information 
     var targetInfo = request.HttpContext.Request.GetDisplayUrl() + request.QueryString; 

     // Generate a hash for your strings (appends each of the bytes of 
     // the value into a single hashed string 
     var hashValue = string.Join("", MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(originationInfo + targetInfo)).Select(s => s.ToString("x2"))); 
     string cachedHash; 
     // Checks if the hashed value is contained in the Cache (indicating a repeat request) 
     if (cache.TryGetValue(hashValue,out cachedHash)) 
     { 
      // Adds the Error Message to the Model and Redirect 

     } 
     else 
     { 
      // Adds an empty object to the cache using the hashValue 
      // to a key (This sets the expiration that will determine 
      // if the Request is valid or not) 
      var opts = new MemoryCacheEntryOptions() 
      { 
       SlidingExpiration = TimeSpan.FromSeconds(DelayRequest) 
      }; 
      cache.Set(hashValue,cachedHash,opts); 
     } 
     base.OnActionExecuting(filterContext); 
    } 
+0

あなたのコントローラの 'Index'メソッドは基本的に空です。問題を診断するためにコードが必要です。あなたのコントローラの 'Developer Tools'にある' Network'タブをチェックして、実際に複数のリクエストがコントローラに送られてきたかどうかを確認します。それ以外に、あなたが提供したコードに何か狂っているものは見当たらないので、重複した要求を送信していることがわかります。 – Cameron

答えて

0

これはASP.NETコアの問題ではありません。実際には複数のリクエストがクライアントから来ていることが99%確信しています.ASP.NET Coreは、それが意味するように単純に処理しています。

あなたのためのオプションは、ページにguidや他の識別子を入れてリクエストとともに送信することです。コントローラで、キャッシュまたはセッションをチェックして、その識別子がすでに存在するかどうかを確認します。そうであれば、例外をスローするか、Ok()を返すか、オカレンスをログに記録するか、その場合は何もしたいが、カードを請求しないでください。

+0

私はページID(またはおそらく両方)ではなくリクエストIDを生成するので、同じページからの2つのリクエスト、2つの異なるページからの2つのリクエスト、またはバグのために実際に2回呼び出されたかどうかを確認できます。ミドルウェアの一つ。 –

+0

私はすでにこれを処理するアクション属性を持っていますが、何とかしてこのコードは場合によっては要求をキャッチできません。このコードを入力すると、実際には重複要求の数が大幅に減少しました。私は自分の投稿を更新して、私が使っている重複したリクエストコードを表示しました。 –

関連する問題