I have a page that executes a long process, parsing over 6 million rows from several csv files into my database.
Question is just as when the user clicks "GO" to start processing and parsing 6 million rows I would like to set a Session Variable that is immediately available to the rest of my web site application so that any user of the web site knows that a user with a unique ID number has started parsing files without having to wait until the end of the 6 million rows processed?
Also with jQuery and JSON, I'd like to get feedback on a webpage as to which csv file is being processed and how many rows have been processed.
There could be other people parsing files at the same time, how could I track all of this and stop any mix up etc with other users even though there is no login or user authentication on the site?
I'm developing in C# with .NET 4.0 Entity Framework 4.0, jQuery, and MS SQL 2008 R2.
I was thinking of using Session Variables however in my static [WebMethod] for my jQuery JSON calls I am not able to pull back my Session unless I'm using HttpContext.Current.Session but I am not sure how if this solution would work?
Any guidance or ideas would be mostly appreciated.
Thanks
First of all: Session variables are not supposed to be seen for any user everywhere.
when some client connects to the server, there is a session made for them by the server, and next time the same user requests (within the expiration time of the session), the session (and it's variables) are usable.
You can use a static class for this if you intend to.
for example
public static class MyApplicationStateBag
{
public static Dictionary<string,object> Objects {get; private set;}
}
and for your progress report. you can use a asp:Timer to check the progress percentage every second or two.
here is a sample code that I have written for asp:Timer within an UpdatePanel:
Writing a code trigger for the updatepanel.
I suggest you use a Guid for identifying the current progress as the key to your state bag.
The correct way of doing this is via services, for example WCF services. You don't want to put immense load on the web server, which is not supposed to do that.
The usual scenario:
User clicks on GO button
Web server creates a job and starts this job on a separate WCF service
Each job has ID and metadata (status, start time, etc.) that is persisted to the storage
Web server returns response with job ID to the user
User, via AJAX (JQuery) queries the job in the storage, once completed you can retrieve results
You can also save Job ID to the session
P.S. it's not a direct answer to your question, but I hope it helps
Related
I am currently working on a task where I need to synchronize the data, example:
Client makes a request to get data to the API (API has access to the database), client received the data and saves it to the list. That list is used for some time etc..... Then in the meanwhile another client accesses the same API and database and makes some changes... to the same table... After a while the first client want's to update his current data, since the table is quite big let's say 10 thousand records, grabbing the entire table again is inefficient. I would like to grab only the records that have been modified,deleted, or newly created. And then update the current list the client 1 has. if the client has no records, he classifies all of them as newly created (at start up) and just grabs them all. I would like to do as much checking on the client's side.
How would I go about this ? I do have fields such as Modified, LastSync, IsDeleted. So I can find the records I need but main issue is how to do it efficiently with minimal repetition.
At the moment I tried to get all the rows at first, then after I want to update (Synchronize) I get the minimal required info LastSync Modified IsDeleted Key, from the API, which I compare with what I have on the client and then send only keys of the rows that don't match to the server to get the entire values that match the keys. But I am not sure about efficiency of this also... not sure how to update the current list with those values efficiently the only way I can think of is using loop in loop to compare keys and update the list, but I know it's not a good approach.
This will never work as long as you do not do the checks on the server side. There is always a chance that someone post between your api get call to server and you post call to server. Whatever test you can do at the client side, you can do it on the server side.
Depending on your DB and other setup, you could accomplish this by adding triggers on the tables/fields that you want to track in the database and setting up a cache (could use Redis, Memcached, Aerospike, etc.) and a cache refresh service . If something in the DB is added/updated/deleted, you can set up your trigger to write to a separate archive table in the DB. You can then set up a job from, e.g., Jenkins (or have a Kafka connector -- there are many ways to accomplish this) to poll the archive tables and the original table for changes based on an ID or date or whatever criteria you need. Anything that has changed will be refreshed and then written back to the cache. Then your API wouldn't be accessing the DB at all. It would just call the cache for the most recent data whenever a client requests it. Your separate service wold be responsible for synchronization of data, database access, and keeping the cache up to date.
I have asp.net Mvc application in which I am migrating mails from one exchange server to another , now I want to keep running migration process and don't want to keep open browser means when user closes browser process must be running at the back and after opening the browser user can check the progress of migration.
Can anyone help me in this, how to achieve this task using asp.net Mvc 4 c# or using any other service
Given the low amount of information in your question, I can only answer concisely.
When the user triggers the migration (i.e. sends the request to MVC), you'll have to trigger the migration in a different thread.
Make sure that the different thread has access to a globally accessible variable, e.g. bool MigrationIsRunning. Your migration will set this to true when starting, and back to false when completed (by success, or by error. Either way).
When your user returns to the migration page, have your Controller method check the value of MigrationIsRunning (the variable from the previous step), and return the correct feedback to the user.
Note: instead of a bool, you could use a custom class that shows more detail. I'm not sure what your users need to know when the migration's running.
Note 2: If your entire application should be inaccessible during the migration, you're better off with placing step 3 either in your Masterpage, or Global.asax, so you have full coverage of your web application instead of a single page.
I am creating a website, where people can add each other as friend.
For example I got 2 users:
User ONE with UserID = 1
User TWO with UserID = 2
When User One adds User Two, I write this to a database, with an Integer to track the status:
0 = waiting
1 = accepted (are now friends)
If denied -> I just delete that record from the database.
When User One add User Two, I want to send a notification to User Two.
So User Two should get a notification about that User One has added him, without refreshing the page.
What can I use to create notifications after adding someone as friend?
Should I look to a kind of trigger on the database that sends something to the website after a record is added, or are there other mechanisms that you guys recommend me?
It's a ASPX website, without MVC.
The same mechanism I would like to use for a Message System.
There are 3 ways of achieving this, from simplest to most complex:
Polling
Write a javascript that calls a rest service on your site every x minutes and updates the DOM of the page
Long Polling
Similar to polling but keeping an open connection to have instant replies without waiting between polls. Requires having an api that can keep a pool of open connection and a background thread on the server that polls the database for changes, which it percolates up to the javascript if needed
Web Sockets
Upgrades the connection to a full two ways connection (websocket protocol). Similar to long polling server side.
As you can see any other option than 1. is fairly complex, but you can take a look at the SingalR library to get you started.
You can use AJAX to poll the database for such updates, AJAX is mainly used to refrain from forms submissions by acting asynchronously.
Here is a simple jQuery example of AJAX polling:
function doPoll(){
$.post('ajax/test.html', function(data) {
alert(data); // process results here
setTimeout(doPoll,5000);
});
}
Also, as Brad M commented, you can "cache" the "Friends" table into the memory and poll against it rather than the DB - It would be much faster.
I have web page index.aspx and corresponding server side code index.aspx.cs. This C# code has a method which cannot executed in parallel if multiple clients connect to my website. How can I restrict this?
Here is what the method does. It creates a folder, zip it and make it available for the user to download. My requirement is that when one user is executing this method, some other user should not do this because it will create the same folder again which leads to corruption of data.
I tried using Session objects. But I came to know that session objects are stored per client basis.
Can anyone suggest me some solution?
My immediate advice would be: create a random folder name per request, which would allow you to run them concurrently. However, if that isn't an option then you will need to synchronize using something like lock or Mutex. However, this would only work well if you are returning the result from the current request, rather than zipping it in one request, and letting them download it the next.
Frankly, though, I think that you should do the zip in the request for the zip. Indeed, unless the file will be huge you don't even need to touch the file-system - you can create a zip in-memory using MemoryStream and any of the zip encoders (System.IO.Packaging.ZipPackage for example) - then just hand the client the data from the MemoryStream.
If you are using MVC, this is just return File(contents, contentType). With vanilla ASP.NET you need a few more steps.
The Application context or a static class is application wide. So you can store a flag which indicates that the process is already started. After the procees ended, you can delete the flag.
http://msdn.microsoft.com/en-us/library/94xkskdf(v=vs.100).aspx
And always use Application.Lock when you write to the application state and lock(mutex) when you use a static class.
In your case a static class would be a better solution, because it seems that the application context exist only for compatible purposes to classic asp: Using static variables instead of Application state in ASP.NET
static object mutex= new object();
lock(mutex)
{
//Do the work
}
If you use the classic asp.net session you do not need to do anything because session all ready lock the run of the pages from multiple users.
If you not, then you can follow what Marc suggest, use Mutex.
About the session lock:
Web app blocked while processing another web app on sharing same session
jQuery Ajax calls to web service seem to be synchronous
ASP.NET Server does not process pages asynchronously
Replacing ASP.Net's session entirely
Are we "doing it wrong"?
A colleague and I are messing around with an ASP.NET page to act as a "portal" to view the results from a diagnostic program on a UniData server. Although we do the odd-job of ASP/ASP.NET at work, it is not our primary language.
To access this server, we have to use UniObjects, which is an API for authenticating and using the UniData server.
We needed each user visiting the website to have to authenticate with UniData and get their own session via the UniObjects library, then be able to use it without signing in again (unless the session isn't used with in 'x' minutes).
The method we have come up with is as follows:
We have a singleton with a Hashtable. It maps Windows username with a session object.
If the user goes to our page and 'username' doesn't exist in the Hashtable, it redirects to a login page where the session object is created and added to the Hashtable if authentication succeeds. Otherwise, it grabs the users existing session object from the Hashtable and uses that for the request (unless it has expired, in which case we remove it and redirect to the login page).
Each session object (which is a wrapper object for stuff from UniObjects) has a "lastUsed" method. We need to clean-up user's sessions since we have license restrictions on users logged into the UniData server, so every time a user gets redirected to the sign-in page, it checks if any sessions have not been used in 'x' mins, in which case it closes that session and removes it from the Hashtable. It is done here so users won't experience any delay related to checking all sessions on every request, only at login.
Something is telling me that this solution smells, but I don't have enough ASP.NET experience to work out what we should be doing? Is there a better method for doing this or is it actually okay?
Since all of your users seem to be authenticated, I would suggest you think about using a different way of managing session state and timeout.
Part of the issue you have is that if a user just closes the browser without logging out, or stops using the application, you have to wait until the session times out to kill it off and free up UniObjects for your licensing issues.
My suggestion is as follows:
Add an invisible IFRAME to your
MasterPage template, or to each page
in the site if you aren't using
MasterPages.
That MasterPage will
load a KeepAlive.aspx page, that
contains a META Refresh, reloading
the page every 5 minutes.
You can
reduce the session timeout to 10
minutes (maybe even 6)
Now, if a user closes their browser windows, their session times out much quicker than usual, but if their browser window is left open, their session is persistent.
A code example and walkthrough can be seen here.
You now need to solution to prevent the user from leaving their browser window open all night and hogging your UniData licences. In this case I would implement a similar methodology, where a stagnant page (i.e. user has done nothing for 20 minutes) is refreshed to a logout ASPX page, clearing the session.
If you are using UniObjects COM, make sure you get your COM marshalling working correctly. Take a look at:
SafeCOMWrapper - Managed Disposable Strongly Typed safe wrapper to late bound COM
http://www.codeproject.com/KB/COM/safecomwrapper.aspx
Another thing to watch out for is that the dynamic array class in UniObjects COM has a threading issue that doesn't play nice with .NET. If you can, use your own dynamic array class or array splits in .NET instead of the Dynamic array class in UniObjects COM.
Sometimes when you try to access the data from the class, it shows an empty string, but when you debug it, the data is there. Don't know the root cause of this.
If you need a generic dynamic array class that works with .NET, I can supply you one.
UniObjects.NET does not have these problems to my knowledge.
Nathan Rector
When you say you are using UniObjects... are you using the COM or .NET object set? The easiest would be to use UniObject Conneciton pooling.
When you create your Singleton, are you storing it in the Application object, Session Object, or Cache Object?
I would suggest Application object, as the Session object is can do strange things. One way to handle and check timeouts would be to use the Cache Key with a CacheRemoveCallback. This way you can use a File/Path Monitor dependency to watch for a windows file change to cause a remove manually, or a timeout from the Cache dependency.
Draw back to this is that timeouts on Cache Dependencies are only driven by page activity, and if the asp.net session recycles, it may/will destory the cache dependencies.
Nathan Rector