我已经构建了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 });
}
答案 0 :(得分:1)
通常,避免锁定公共类型或超出代码控制范围的实例。
常见的构造锁(this),lock(typeof(MyType))和lock(“myLock”)违反了这条准则:
最佳做法是定义要锁定的私有对象,或私有静态对象变量以保护所有实例共有的数据
尝试做类似的事情:
private Object thisLock = new Object();
lock (thisLock)
{
if (!MvcApplication.GlobalMemoryLeads.ContainsKey(EncodedLead))
{
try
{
MvcApplication.GlobalMemoryLeads.Add(EncodedLead, false);
...