Can some one give me a best way to implement a daily job with .NET technology.
I have an asp.net application with the sqlserver database hosted in shared hosting, GODaddy in my instance.
My application is used to add / change the data in the database which is performing quite fairly at this time.
I got a new requirement to send some email alerts daily based on some data criteria that were stored in the database.
Initially I thought to write a windows service, but godaddy is not allowing to access the database other than its hosted applications.
Does someone has any idea to send alerts daily at 1:00AM?
Thanks in advance
See Easy Background Tasks in ASP.NET by Jeff Atwood.
Copy/paste from the link:
private static CacheItemRemovedCallback OnCacheRemove = null;
protected void Application_Start(object sender, EventArgs e)
{
AddTask("DoStuff", 60);
}
private void AddTask(string name, int seconds)
{
OnCacheRemove = new CacheItemRemovedCallback(CacheItemRemoved);
HttpRuntime.Cache.Insert(name, seconds, null,
DateTime.Now.AddSeconds(seconds), Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable, OnCacheRemove);
}
public void CacheItemRemoved(string k, object v, CacheItemRemovedReason r)
{
// do stuff here if it matches our taskname, like WebRequest
// re-add our task so it recurs
AddTask(k, Convert.ToInt32(v));
}
I haven't used GoDaddy for anything other than domain registration, so I have no experience with what you can or cannot do on their hosting platform. I also don't know what their support or knowledge base is like, but I'd say your best option is to ask GoDaddy what they recommend. Otherwise, you might keep implementing something that's technically feasible, but is blocked by the hosting company.
If it's not something that's a prime-time application, one quick and dirty thing to do is to have some kind of external bot calling a (secure) web page on the server that fires off the notification process. Not a real solution, but if this site is just a hobby of yours, it could get you by until you find something the host will allow.
Might also be a good time to find a new host, if this one is not meeting your requirements. There are lots of good ASP.NET hosts available these days.
You can use windows scheduler from the web server to schedule a stored procedure call that can send mail based on particular criteria.
osql.exe -S servername -d database -U username -P password -Q "EXEC spAlertOnCriteria"
References:
osql
Task Scheduler
Many hosting providers can request a URL for you every X minutes. I don't know if GoDaddy does, but if so, you could create an ASMX page that kicks off the job, and tell them to execute it automatically.
If they don't, one solution might be to fire off the job in a background thread at every page request. If you do that, make sure you put in code that limits it to running every X minutes or more (perhaps using a static variable or a database table) - read this story
If you can expose a service on the website hosting the application and database -- authenticated service, of course -- then you can hit that service remotely from any box with credentials, pull down the data, and send the mail that way.
This could be an automated process written as a Windows service, an application that is run under the Scheduler, or some button you push at 1:00 AM. Your pick.
Just because the app is the only thing that can access the database doesn't mean you can't expose the data in other ways.
Use either System.Timers, System.Threading to create a instance that is run at a predetermined time. Have that thread execute whatever the task is that you want... Make sure the code is thread safe!
Related
I have my Asp.Net WebApi hosted on Godaddy windows shared hosting.
When I access my api from different devices/machines, It takes around 30 sec for first request; after that, it works fine.
What is the issue? Can I make my web api run all the time? If so, how?
I have used Entity framework code first approach . Every time I face this issue when I call this api from my website which is:
Rs Travels - Go to holidays, click on domestic, see the slowness of web api.
Is there any way I can improve the performance of the web api?
If the API is not used often, it will take time on the first request to make things ready, it's the same if you restart IIS generally, things need to warm up.
Internally, we have a custom healthcheck system that calls specific URLs to monitor them, but as a consequence, it also keeps the service alive.
You could also do this fairly simply by creating a windows scheduler task locally, or on any server that simply calls the API periodically. It might be best to implement a specific Monitor method that performs any other keepalives that might be relevant.
Try this as an example Open Website from windows scheduler
It would be kinda difficult to change it since you do not own the web server (and thus its pool). You could try to call the api before you will actually need it (imagine a splash screen). Then it will be ready when you will actually need it. Of course, this will not work if form the initial page you are calling the API...
This worked for me !
https://stackoverflow.com/a/9474978/6426192
static Thread keepAliveThread = new Thread(KeepAlive);
protected void Application_Start()
{
keepAliveThread.Start();
}
protected void Application_End()
{
keepAliveThread.Abort();
}
static void KeepAlive()
{
while (true)
{
WebRequest req = WebRequest.Create("http://www.mywebsite.com/DummyPage.aspx");
req.GetResponse();
try
{
Thread.Sleep(60000);
}
catch (ThreadAbortException)
{
break;
}
}
}
I'm working on a little project for a basic Youtube remote control, whereby I have a helper app running on my PC, and then can send commands from a website accessed via the web browser on my phone.
Reading through threads on other sites from people trying to do the same thing I've realized it is not a concept that most people would be comfortable with, but I am struggling to think of another way to do it beyond writing a native app for my phone and having it communicate with the helper application internally via WLAN(Would be happy to do this, but don't have the cash to spring for a new mac to develop for my iphone).
If I were to stick with the Website/Winforms model, is there a way to do this in such a way that (most) people would be comfortable running?
The ideas I had so far were:
a) Build a web server into the helper app(Though not sure of the logistics of having it host an ASP.net site)
b) Host the site externally, and have the helper app periodically poll a database/webservice on a server to receive commands (Sketchy and i imagine very resource heavy)
Sorry for the wall of text, I'm capable of running with an idea and building it, I'm just not sure what is possible and considered the 'best' way to do something like this.
Any advice would be appreciated.
Cheers
Edit Thanks, just to be clear, when i say uncomfortable, I mean - Would you be ok with having a website being able to send potentially ANY command to your computer? This seems to be the problem raised in other discussions about this topic. Obviously I'm not trying to do anything malicious, but as I said, it seemed to be a concern.
If this is a controlled environment where you can always open a port on the firewall for incoming communication, you can have the web app make a WCF call back to the Windows Client through the users firewall.
If not (which is what I suspect), you may be better off polling a web service. Just do it every few seconds and whatever you're checking in that web service call (a database?) make sure it's well optimized. Perhaps just have it return some status int/enum or something very light weight to instruct the client on the next call to make (0 = no update, 1 = command1, 2 = command2, etc).
As for how you do the polling, you could do something like:
int seconds = 4;
System.Timers.Timer _clientTimer = new System.Timers.Timer(seconds * 1000);
_clientTimer.AutoReset = false;
_clientTimer.Elapsed += clientTimer_Elapsed;
_clientTimer.Start();
private void clientTimer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
// Connect to web service, get status, if status != 0 do something...
}
finally
{
_clientTimer.Start();
}
}
NOTE: the auto-reset = false means that each time the Elapsed event fires, the timer is stopped. In the approach I've taken, I let the timer stop so the client can process the web service results and then start the timer once again after it's done. This will help prevent multiple requests from piling up if a connection is real slow.
That's all I can think of :)
I would like to run a time consuming script (to update a database from a 3rd party API) at regular intervals. I was wondering what the best practice for this would be:
What should the 'script' be - an ASP.NET service? Bearing in mind I am on shared hosting, this may not be possible (but I would like to know).
How could the script be scheduled to run at regular intervals/at set time automatically?
Thanks in advance!
Some options for this:
Use a separate thread that keeps running all the time - and does the update on time (and then sleeps).
Use a timer and trigger the update event.
Use a Cache expiration trigger, but test this so that it keeps running without users visiting the site.
I would suggest checking out http://www.beansoftware.com/ASP.NET-Tutorials/Scheduled-Tasks.aspx for more details on these methods.
There is no way you can guarantee that something runs e.g. every night in a normal IIS setup. Batch jobs are thus a pain to handle. The only "mode" of execution for IIS is requests. If your application has no requests it doesn't run at all so IIS does not spend any resources on executing code in your application, i.e. it can unload it entirely.
If you have your own host, you would typically create a windows service to run your background tasks. I believe the same is possible in Azure. But for a standard sharesd IIS host, you basically can't setup a scheduled background task.
One of the simplest hacks is to setup a protected service that executes the job when it gets a request. Then you can make sure an external caller calls into your service at the required intervals.
What you can do is add a System.Timers.Timer in Global.asax.
System.Threading.Timer timer = new System.Threading.Timer(new TimerCallback(TimerElapsed), null, new Timespan(0), new Timespan(24, 0, 0));
// This will run every 24 hours.
private void TimerElapsed(object o)
{
// Do stuff.
}
In IISManager, enable HTTP-Keep Alives for your application.
In IIS Manager, select Http Response Headers Module, open it and in the Actions Pane, select Set Common Headers and in there select Enable Http Keep Alives.
Also, check for a setting of your application pool -
Select the application pool of your application, select Advanced Settings from the right Actions Tab.
In there there is a setting called - Idle Timeout (minutes)
By default it is 20 Minutes. Make it something like 60 Minutes or increase it even more and check.
I would like my ASP.NET MVC app to execute a query once per day. What is the recommended way to do this?
My first thought is to put a timer in Global.asax that goes off every 24 hours, then call my query from the Elapsed handler. Any pitfalls with doing it this way? Is there a better way?
Edit
Let me add a little detail to what I'm trying to do. I'd specifically like the query to execute at midnight every day. If a day is missed (say due to sever maintenance or upgrading the app), that wouldn't be a major issue.
Edit 2
Couple more details:
The query is actually an INSERT, not a SELECT. The purpose is to add a "renewal" record for any member that is due to renew his/her membership at the end of the month.
I'm using SQL Server Compact (it's a very small database).
Does it have to originate in the Web layer? Who'd be there to consume the HTML? Typically, periodic SQL queries are scheduled within the database. In case of MS SQL Server - via the SQL Agent job facility. SQL Server can even send e-mail.
RE: edit2: Should've told so right away. SQL Server Compact is not the same as SQL Server - for one, it does not have SQL Agent IIRC. Still, invoking the Web layer is an overkill. I'd use a Windows Scripting Host file (.js) in conjuction with Windows task scheduler. WSH files can connect to databases via ADO and do whatever they want - inserts, selects, anything.
To detect missed scheduled runs, introduce an extra table with a log of scheduled runs. Then on subsequent runs you can analyse the date of the last run and act accordingly.
Edit2: so no administrative access. You should really tell all those details in the question. In this case, I would go through the Web layer after all, but the scheduling would be on MY end - where I do have control. Have Task Scheduler run on your end and invoke an HTTP URL on the server. To invoke URLs, you can use something like the free CURL utility. Running IE in scheduled manner has the disadvantage of leaving the window open.
IIS is not a scheduling engine.
Edit3 re:comment: sorry, I've misunderstood the nature of your setup. My own experiences have clouded my judgement :) Can you just run a check during every logon operation, and if it's been a while since the last maintenance operation, run it right then and there? How long does the maintenance take? If it's ~1min+, makes sense to run it in a worker thread, so that the logging-on user is not made wait.
Scheduling daily maintenance is a good idea in general, and it is implemented fairly often, but it seems you simply don't have the capability.
I do this very thing in my web apps, but use Asynchronous HTTP Handlers (http://msdn.microsoft.com/en-us/library/ms227433.aspx#Y512); I believe this would be recommended. I just start it off on application start and shut it down on application end (Global.asx).
The thing to remember is that you'll probably have to store the last time the query ran in the database because you'll loose track of that when your application pool recycles.
I'm doing this by putting some fake information in "Cache" and put the time period i want then handel the "_onCacheRemove" event do whatever i wanna do then recreate the "CacheItem" again:
e.g.
I put my tasks in Enum with the time that i wanna to rerun this task in seconds:
public enum ScheduledTasks
{
CleanGameRequests = 120,
CleanUpOnlineUsers = 6
}
then deal with them at "Application_Start" :
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
// Adding the tasks i want at App_Start
// so if the application restarted my task will refreshed.
AddTask(ScheduledTasks.CleanGameRequests);
AddTask(ScheduledTasks.CleanUpOnlineUsers);
}
// event to handel
private static CacheItemRemovedCallback _onCacheRemove;
private void AddTask(ScheduledTasks task)
{
_onCacheRemove = new CacheItemRemovedCallback(CacheItemRemoved);
HttpRuntime.Cache.Insert(task.ToString(), (int)task, null,
DateTime.Now.AddSeconds((int)task), Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable, _onCacheRemove);
}
public void CacheItemRemoved(string key, object time, CacheItemRemovedReason r)
{
var task = (ScheduledTasks)Enum.Parse(typeof(ScheduledTasks), key);
switch (task)
{
case ScheduledTasks.CleanGameRequests:
// Do the concept that you wanna to do.
GameRequest.CleanUp();
break;
case ScheduledTasks.CleanUpOnlineUsers:
OnlineUsers.CleanUp();
break;
default:
break;
}
// Don't forget to recreate the "CacheItem" again.
AddTask(task);
}
Note: You may make your time management as you want. In my case i
wanna these tasks to run every period
of time regardless of what time it is.
In your case you should check the time
before then recreate the CacheItem
again.
Hope this helped :)
Unless you have very active site chances are that IIS will bring your application down and there will be no process to execute your task.
Alternatives:
just do that during/immediately after request that is close enough by time
have external task that will trigger the operation on your site via GET/POST.
reconfigure IIS to never recycle/stop your app pool. Than your timer has chance to execute.
use some external service on the server to schedule the task ("at" or even SQL tasks).
I have an application that runs as a Windows service. It stores various things settings in a database that are looked up when the service starts. I built the service to support various types of databases (SQL Server, Oracle, MySQL, etc). Often times end users choose to configure the software to use SQL Server (they can simply modify a config file with the connection string and restart the service). The problem is that when their machine boots up, often times SQL Server is started after my service so my service errors out on start up because it can't connect to the database. I know that I can specify dependencies for my service to help guide the Windows service manager to start the appropriate services before mine. However, I don't know what services to depend upon at install time (when my service is registered) since the user can change databases later on.
So my question is: is there a way for the user to manually indicate the service dependencies based on the database that they are using? If not, what is the proper design approach that I should be taking? I've thought about trying to do something like wait 30 seconds after my service starts up before connecting to the database but this seems really flaky for various reasons. I've also considered trying to "lazily" connect to the database; the problem is that I need a connection immediately upon start up since the database contains various pieces of vital info that my service needs when it first starts. Any ideas?
Dennis
what your looking for is SC.exe. This is a command line tool that users can use to configure services.
sc [Servername] Command Servicename [Optionname= Optionvalue...]
more specificly you would want to use
sc [ServerName] config ServiceName depend=servicetoDependOn
Here is a link on the commandlike options for SC.EXE
http://msdn.microsoft.com/en-us/library/ms810435.aspx
A possible (far from ideal) code solution:
In you startup method code it as a loop that terminates when you've got a connection. Then in that loop trap any database connection errors and keep retrying as the following pseudo code illustrates:
bool connected = false;
while (!connected)
{
try
{
connected = openDatabase(...);
}
catch (connection error)
{
// It might be worth waiting for some time here
}
}
This means that your program doesn't continue until it has a connection. However, it could also mean that your program never gets out of this loop, so you'd need some way of terminating it - either manually or after a certain number of tries.
As you need your service to start in a reasonable time, this code can't go in the main initialisation. You have to arrange for your program to "start" successfully, but not do any processing until this method had returned connected = true. You might achieve this by putting this code in a thread and then starting your actual application code on the "thread completed" event.
Not a direct answer put some points you can look into
Windows service can be started Automatically with a delay. You can check this question in SO for some information about it.
How to make Windows Service start as “Automatic (Delayed Start)”
Check this post How to: Code Service Dependencies