2017-08-17 57 views
0

我建的WebAPI服務(MvcApplication),其recive用戶名和電子郵件。如何避免收到重複的請求控制器

我有鏈接到這個服務:

Ex: www.domain.com/Controller/SendUser 

,我有一些關聯公司,在他們的網站/登陸頁面使用這個網址我的服務,他們給我的數據與用戶名和潛在客戶的電子郵件。

一些分支機構擁有構建他們提交表單錯誤,並允許用戶按發送鍵很多時候他們在屏幕上看到的反應或問題似乎哪裏重定向到下一page.And這裏之前。

我得到5-10請求我與重複數據服務,並開始運行我的所有驗證函數和方法插入到數據庫中。

重要: 我做數據庫水平不慣於解決方案,我想停止在一開始的要求,甚至不啓動所有驗證服務。

我需要接收請求,臨時保存用戶名+電子郵件,如果我在相同的第二或在接下來的10秒的相同的用戶名+電子郵件接收,只是爲了避免它。

我試圖添加靜態字典到Global.asax並保存EncodedLead(從用戶+電子郵件),我鎖定我的字典GlobalMemoryLeads之前我檢查是否ContainsKey(X),並比我添加一個密鑰,但一些如何我即使字典被鎖定,仍然會出現密鑰全部準備好的錯誤。

看來,線程拋出鎖,並嘗試添加相同的密鑰,即使當GlobalMemoryLeads.ContainsKey(EncodedLead)返回false時,播種另一個線程可以添加到另一個線程鎖定的字典的關鍵??我缺少的東西這裏?

如何避免重複請求?

修訂

我的代碼:

 [AcceptVerbs(WebRequestMethods.Http.Get, WebRequestMethods.Http.Post)] 
     [AllowCrossSiteJson] 
     public ActionResult SendUser(string UserName, string Email,) 
     { 
      string response = ""; 
      bool duplicate=false; 
      try 
      { 
      string Lead = UserName + email; 
      int EncodedLead = Lead.GetHashCode(); 

      //here i lock my GlobalMemoryLeads dictionary 
     lock (MvcApplication.GlobalMemoryLeads) 
      { 
      //here i check if that key is all ready ContainsKey 
     if (!MvcApplication.GlobalMemoryLeads.ContainsKey(EncodedLead)) 
      { 
       try 
       { 
       MvcApplication.GlobalMemoryLeads.Add(EncodedLead, false); 
       } 
     catch (Exception ex) 
     { 

    //here i get error that key is all ready exist 
    //how it possible if i have 
    //1: Globalizes lock 
    //2 i check ContainsKey before 
    return Json(new { respondNotSuccess = "Duplicate Lead" }); 
    } 

      } 

       } 

      } 
      catch (Exception ex) 
      { 
       response = "Exception " + ex.Message; 

      } 

      return Json(new { respondSuccess = response }); 
     } 
+1

是' GlobalMemoryLeads'是一個Dictionary還是一個ConcurrentDictionary?如果它是一個不安全的調用多線程的'Dictionary'。另外,是否考慮使用實際的[MemoryCache](https://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache(v = vs.110).aspx)而不是字典,你會得到一些額外的好處,比如滑動到期窗口。 –

+1

您可以更改提交表單以在第一次提交時禁用按鈕嗎? – mjwills

+0

mjwills,no。我的分支機構擁有自己的表單,只使用我的URl發送數據,我沒有訪問他們的代碼/表單 –

回答

1

一般情況下,避免鎖定在一個公共類型,或者超出你的代碼的控制情況。

共同構造鎖(本),鎖(typeof運算(的MyType)),並鎖定( 「myLock」)違反此準則:

  • 鎖(這)是一個問題,如果該實例可以被訪問公開。
  • 如果MyType是可公開訪問的,則鎖定(typeof(MyType))是一個問題。
  • 鎖(「myLock」)是一個問題,因爲使用相同字符串的進程中的任何其他代碼將共享相同的鎖。

最佳做法是定義一個私有對象來鎖定或私有靜態對象變量,以保護共同數據到所有實例

嘗試做這樣的事情:

private Object thisLock = new Object(); 

lock (thisLock) 
    { 
     if (!MvcApplication.GlobalMemoryLeads.ContainsKey(EncodedLead)) 
     { 
      try 
      { 
      MvcApplication.GlobalMemoryLeads.Add(EncodedLead, false); 
      ...