How to avoid receiving duplicate request in controller - c#

I have build WebApi service(MvcApplication) that recive UserName ,and Email.
i have url to this service:
Ex: www.domain.com/Controller/SendUser
And i have some affiliates that use this URL to my service in they website/landing page,and they send me data with Username,and Email of potential client.
Some affiliates have build they submit form wrong,and allow to users press SEND button many times before they see response on the screen or redirect to next page.And here where the problem appears.
I getting 5-10 request to my service with duplicate data,and start to run all my validation function and methods insert to database.
IMPORTANT:
I don't wont solution on database level,i want to stop the request in the beginning,don't even start all validation services.
I need to receive request,temporary save UserName+Email,and if i receiving in the same second or in next 10 seconds the same UserName+Email just to avoid it.
I tries to add static dictionary to Global.asax and save EncodedLead(from User+Email),I lock the my dictionary GlobalMemoryLeads before i check if ContainsKey(X),and than i add a key,but some how i still get error that key is all ready exist even when dictionary is lock.
It seems that threads go throw lock and try to add the same key even when
GlobalMemoryLeads.ContainsKey(EncodedLead) return false,sow another thread can add key to dictionary that is locked by another thread??What i am missing here?
How to avoid duplicate requests?
UPDATED
My code:
[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 });
}

In general, avoid locking on a public type, or instances beyond your code's control.
The common constructs lock (this), lock (typeof (MyType)), and lock ("myLock") violate this guideline:
lock (this) is a problem if the instance can be accessed publicly.
lock (typeof (MyType)) is a problem if MyType is publicly accessible.
lock ("myLock") is a problem because any other code in the process using the same string, will share the same lock.
Best practice is to define a private object to lock on, or a private static object variable to protect data common to all instances
try to do something like that:
private Object thisLock = new Object();
lock (thisLock)
{
if (!MvcApplication.GlobalMemoryLeads.ContainsKey(EncodedLead))
{
try
{
MvcApplication.GlobalMemoryLeads.Add(EncodedLead, false);
...

Related

Thread.Abort doesn't release a file

I made a code that create a Database in .sqlite, all working good but I want to be sure that when the user start for the first time the application the Database population must be completed. If the user abort the database population, the database must be deleted (because the application don't working with an incomplete resource). Now I've used the thread for execute the method that create this Database, and I've declared the thread variable global in the class, like:
Thread t = new Thread(() => Database.createDB());
The Database.createDB() method create the DB. All working perfect, the DB is created correctly. Now I fire the closing of the window that creating the DB like:
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
MessageBoxResult result = MessageBox.Show(
#"Sure?",
"Attention", MessageBoxButton.YesNo, MessageBoxImage.Question);
try
{
if (result == MessageBoxResult.Yes)
{
t.Abort();
if (File.Exists("Database.sqlite"))
{
File.Delete("SoccerForecast.sqlite");
Process.GetCurrentProcess().Kill();
} ....
The event was fired correct and the thread stopped, but when the condition start if (File.Exists("Database.sqlite")) the compiler tell me:
Can't delete file - in using by another process.
But I've stopped the thread, why this exception appear? What I doing wrong?
UPDATE:
In CreateDb() method I also have a call to other method of different class, one of this have the structure like this:
public void setSoccer()
{
Database.m_dbConnection.Open();
string requestUrl = "...";
string responseText = Parser.Request(requestUrl);
List<SoccerSeason.RootObject> obj = JsonConvert.DeserializeObject<List<SoccerSeason.RootObject>>(responseText);
foreach (var championships in obj)
{
string sql = "string content";
SQLiteCommand command = new SQLiteCommand(sql, Database.m_dbConnection);
try
{
command.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
string query = "select * from SoccerSeason";
SQLiteCommand input = new SQLiteCommand(query, Database.m_dbConnection);
SQLiteDataReader reader = input.ExecuteReader();
int i = 0;
while (reader.Read())
{
//reading data previously inserted in the database
}
Database.m_dbConnection.Close(); /
}
I was wondering where I should put the flag variable because this code have a different loop inside.
It could be that when you're aborting the thread it's not cleanly closing the database connections, hence the error you're seeing.
Might I suggest a slight redesign because using Thread.Abort is not ideal.
Instead use a variable as a cancel flag to notify the thread to shut down.
Then when the thread detects that this cancel flag is set it can properly close connections and handle the database delete itself.
Update:
A brief example to illustrate what I mean; it ain't pretty and it won't compile but it gives the general idea.
public class Database
{
public volatile bool Stop= false;
public void CreateDb()
{
if(!Stop)
{
// Create database
}
if(!Stop)
{
// Open database
// Do stuff with database
}
// blah blah ...
if(Stop)
{
// Close your connections
// Delete your database
}
}
}
...
protected override void OnClosing(CancelEventArgs e)
{
Database.Stop = true;
}
And now that you know roughly what you're looking for I heartily recommend Googling for posts on thread cancellation by people who know what they're talking about that can tell you how to do it right.
These might be reasonable starting points:
How to: Create and Terminate Threads
.NET 4.0+ actually has a CancellationToken object with this very purpose in mind Cancellation in Managed Threads

Mutex throwing UnauthorizedAccessException

I am trying to write a custom mechanism for compressing and caching web scripts. I am using a Mutex to provide managed access for the cache creation methods.
public class HttpApplicationCacheManager
{
public object Get(
Cache cache, // Reference to the HttpContext.Cache
string key, // Id of the cached object
int retrievalWaitTime,
Func<object> getData, // Method that builds the string to be cached
Func<CacheDependency> getDependency) // CacheDependency object for the
// string[] of file paths to be cached
{
Mutex mutex = null;
bool iOwnMutex = false;
object data = cache[key];
// Start check to see if available on cache
if (data == null)
{
try
{
// Lock base on resource key
// (note that not all chars are valid for name)
mutex = new Mutex(false, key);
// Wait until it is safe to enter (someone else might already be
// doing this), but also add 30 seconds max.
iOwnMutex = mutex.WaitOne(retrievalWaitTime * 1000);
// Now let's see if some one else has added it...
data = cache[key];
// They did, so send it...
if (data != null)
{
return data;
}
// Still not there, so now is the time to look for it!
data = getData();
var dependency = getDependency();
cache.Insert(key, data, dependency);
}
catch
{
throw;
}
finally
{
// Release the Mutex.
if ((mutex != null) && (iOwnMutex))
{
mutex.ReleaseMutex();
}
}
}
return data;
}
}
The
Whilst this works, I occasionally see the following error:
System.UnauthorizedAccessException
Access to the path 'SquashCss-theme.midnight.dialog' is denied.
I have found some posts suggesting that this might be due to a race condition. Unfortunately, my Mutex knowledge is very limited and I am struggling to see where the problem might be.
Any help would be much appreciated.
Why not just use any of the built-in .NET caches? I don't see anything in your code that could not be handled by the .NET cache implementations. Another option maybe the readerwriterlockslim class, since you really only need to lock on writes.

SQL CLR make sure finally block is executed

I have a SQL server CLR stored proc that is used to retrieve a large set of rows, then do a process and update a count in another table.
Here's the flow:
select -> process -> update count -> mark the selected rows as processed
The nature of the process is that it should not count the same set of data twice. And the SP is called with a GUID as an argument.
So I'm keeping a list of GUIDs (in a static list in the SP) that are currently in process and halt the execution for subsequent calls to the SP with the same argument until one currently in process finishes.
I have the code to remove the GUID when a process finishes in a finally block but it's not working everytime. There are instances (like when the user cancels the execution of the SP)where the SP exits without calling the finally block and without removing the GUID from the list so subsequent calls keeps waiting indefinitely.
Can you guys give me a solution to make sure that my finally block will be called no matter what or any other solution to make sure only one ID is in process at any given time.
Here's a sample of the code with the processing bits removed
[Microsoft.SqlServer.Server.SqlProcedure]
public static void TransformSurvey(Guid PublicationId)
{
AutoResetEvent autoEvent = null;
bool existing = false;
//check if the process is already running for the given Id
//concurrency handler holds a dictionary of publicationIds and AutoresetEvents
lock (ConcurrencyHandler.PublicationIds)
{
existing = ConcurrencyHandler.PublicationIds.TryGetValue(PublicationId, out autoEvent);
if (!existing)
{
//there's no process in progress. so OK to start
autoEvent = new AutoResetEvent(false);
ConcurrencyHandler.PublicationIds.Add(PublicationId, autoEvent);
}
}
if (existing)
{
//wait on the shared object
autoEvent.WaitOne();
lock (ConcurrencyHandler.PublicationIds)
{
ConcurrencyHandler.PublicationIds.Add(PublicationId, autoEvent); //add this again as the exiting thread has removed this from the list
}
}
try
{
// ... do the processing here..........
}
catch (Exception ex)
{
//exception handling
}
finally
{
//remove the pubid
lock (ConcurrencyHandler.PublicationIds)
{
ConcurrencyHandler.PublicationIds.Remove(PublicationId);
autoEvent.Set();
}
}
}
Wrapping the code at a higher level is a good solution, another option could be the using statement with IDisposable.
public class SQLCLRProcedure : IDisposable
{
public bool Execute(Guid guid)
{
// Do work
}
public void Dispose()
{
// Remove GUID
// Close Connection
}
}
using (SQLCLRProcedure procedure = new SQLCLRProcedure())
{
procedure.Execute(guid);
}
This isn't verified in a compiler but it's commonly referred to as the IDisposable Pattern.
http://msdn.microsoft.com/en-us/library/system.idisposable.aspx

Multithreaded linq2sql applications TransactionScope difficulties

I've created a file processing service which reads and imports xml files from a specific directory.
The service starts several workers which will poll a filequeue for new files and uses linq2sql for dataaccess. Each workerthread has its own datacontext.
The files being processed contain several orders and each order contains several addresses (Customer/Contractor/Subcontractor)
I've defined a transactionscope around the handling of each file. This way I want to ensure that the whole file is handled correctly, or that the whole file is rolled back when an exception occurs:
try
{
using (var tx = new TransactionScope(TransactionScopeOption.RequiresNew))
{
foreach (var order in orders)
{
HandleType1Order(order);
}
tx.Complete();
}
}
catch (SqlException ex)
{
if (ex.Number == SqlErrorNumbers.Deadlock)
{
throw new FileHandlerException("File Caused a Deadlock, retrying later", ex, true);
}
else
throw;
}
One of the requirements for the service is that is creates or updates found addresses in the xml files. So I've created an address service which is responsible for address management. The following piece of code gets executed for each order (within the method HandleType1Order()) in the xml importfile (And thus is part of the TransactionScope for the entire file).
using (var tx = new TransactionScope())
{
address = GetAddressByReference(number);
if (address != null) //address is already known
{
Log.Debug("Found address {0} - {1}. Updating...", address.Code, address.Name);
UpdateAddress(address, name, number, isContractor, isSubContractor, isCustomer);
}
else
{
//address not known, so create it
Log.Debug("Address {0} not known, creating address", number);
address = CreateAddress(name, number, sourceSystemId, isContractor, isSubContractor,
isCustomer);
_addressRepository.Save(address);
}
_addressRepository.Flush();
tx.Complete();
}
What I'm trying to do here, is to create or update an address, with the number being unique.
The method GetAddressByReference(string number) returns a known address or null when an address is not found.
public virtual Address GetAddressByReference(string reference)
{
return _addressRepository.GetAll().SingleOrDefault(a=>a.Code==reference);
}
When I run the service it however creates multiple addresses with the same number. The method GetAddressByReference() get's called concurrently and should return a known address when a second thread executes the method with the same addressnumber, however it returns null. There is propably something wrong with my transaction boundaries, or isolationlevel, but I can't seem to get it to work.
Can someone point me in the right direction? Help is much appreciated!!
p.s. I've no problem with the transactions being deadlocked and causing a rollback, the file will just be retried when a deadlock occurs.
Edit 1 Threading code:
public void Work()
{
_isRunning = true;
while (true)
{
ImportFileTask task = _queue.Dequeue(); //dequeue blocks on empty queue
if (task == null)
break; //Shutdown worker when a null task is read from the queue
IFileImporter importer = null;
try
{
using (new LockFile(task.FilePath).Acquire()) //create a filelock to sync access accross all processes to the file
{
importer = _kernel.Resolve<IFileImporter>();
Log.DebugFormat("Processing file {0}", task.FilePath);
importer.Import(task.FilePath);
Log.DebugFormat("Done Processing file {0}", task.FilePath);
}
}
catch(Exception ex)
{
Log.Fatal(
"A Fatal exception occured while handling {0} --> {1}".FormatWith(task.FilePath, ex.Message), ex);
}
finally
{
if (importer != null)
_kernel.ReleaseComponent(importer);
}
}
_isRunning = false;
}
The above method runs in all of our worker threads. It uses Castle Windsor to resolve the FileImporter, which has a transient lifestyle (thus not shared accross threads).
You didn't post your threading code, so its difficult to say what the issue is. I'm assuming you have started DTC (Distributed Transaction Coordinator)?
Are you using a ThreadPool? Are you using the "lock" keyword?
http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx

Synchronizing Access to a member of the ASP.NET session

I'm building a Javascript application and eash user has an individual UserSession. The application makes a bunch of Ajax calls. Each Ajax call needs access to a single UserSession object for the user.
Each Ajax call needs a UserSession object.
Data in the UserSession object is unique to each user.
Originally, during each Ajax call I would create a new UserSession object and it's data members were stored in the ASP.NET Session. However, I found that the UserSession object was being instantiated a lot. To minimize the construction of the UserSession object, I wrapped it in a Singleton pattern and sychronized access to it.
I believe that the synchronization is happening application wide, however I only need it to happen per user. I saw a post here that says the ASP.NET cache is synchronized, however the time between creating the object and inserting it into the cache another Thread could start construction it's another object and insert it into the cache.
Here is the way I'm currently synchronizing access to the object. Is there a better way than using "lock"... should be be locking on the HttpContext.Session object?
private static object SessionLock = new object();
public static WebSession GetSession
{
get
{
lock (SessionLock)
{
try
{
var context = HttpContext.Current;
WebSession result = null;
if (context.Session["MySession"] == null)
{
result = new WebSession(context);
context.Session["MySession"] = result;
}
else
{
result = (WebSession)context.Session["MySession"];
}
return result;
}
catch (Exception ex)
{
ex.Handle();
return null;
}
}
}
}
You don't need to lock Session state access.
The physical values of a session state are locked for the time needed to complete a request. The lock is managed internally by the HTTP module and used to synchronize access to the session state.
http://msdn.microsoft.com/en-us/library/aa479041.aspx
In general, you don't need this kind of code for asp.net session access, since access to each session is limited to a single user. The only reason I can think of for locking access to your session object is if you expect to have multiple simultaneous ajax requests, and even so, I think asp.net would synchronize the access for you.
If you do decide to lock, you only really need to do it if your session object is null:
if (context.Session["MySession"] == null) {
lock(SessionLock) {
if (context.Session["MySession"] == null) {
context.Session["MySession"] = new WebSession(context); // try-catch block removed for clarity (and my laziness)
}
}
}
return (WebSession)context.Session["MySession"];

Categories

Resources