如何避免在控制器中接收重复请求

时间:2017-08-17 05:00:21

标签: c# .net asp.net-mvc web-services

我已经构建了WebApi服务(MvcApplication),它可以重新发送UserName和Email。

我有这个服务的网址:

Ex: www.domain.com/Controller/SendUser

我有一些分支机构在他们的网站/登陆页面上使用此URL到我的服务,他们向我发送带有用户名和潜在客户的电子邮件的数据。

某些关联企业已经构建错误的提交表单,并允许用户多次按SEND按钮,然后才能在屏幕上看到响应或重定向到下一页。此处出现问题。

我通过重复数据向我的服务请求5-10,并开始运行我的所有验证功能和方法插入数据库。

重要: 我不会解决数据库级别,我想在开始时停止请求,甚至不启动所有验证服务。

我需要接收请求,临时保存UserName +电子邮件,如果我在同一秒或接下来的10秒内收到相同的UserName +电子邮件,只是为了避免它。

我尝试将静态字典添加到Global.asax并保存EncodedLead(来自用户+电子邮件),我在检查ContainsKey(X)之前是否锁定了我的字典GlobalMemoryLeads,而不是我添加了一个键,但有些我仍然如何即使字典被锁定,也会获得密钥已准备就绪的错误。

似乎线程会抛出锁定并尝试添加相同的密钥,即使这样 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 个答案:

答案 0 :(得分:1)

通常,避免锁定公共类型或超出代码控制范围的实例。

常见的构造锁(this),lock(typeof(MyType))和lock(“myLock”)违反了这条准则:

    如果可以公开访问实例,则
  • lock(this)是一个问题。
  • 如果MyType可公开访问,则
  • lock(typeof(MyType))是一个问题。
  • lock(“myLock”)是一个问题,因为进程中使用相同字符串的任何其他代码都将共享同一个锁。

最佳做法是定义要锁定的私有对象,或私有静态对象变量以保护所有实例共有的数据

尝试做类似的事情:

private Object thisLock = new Object();

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