Calling an asp.net mvc controller’s action method using windows task scheduler or another schdule tools - asp.net

I am planning to create an asp.net mvc web application which will perform a single sync job, to achieve this:-
We have a 3rd party ERP system which will be generating a .csv file on timely basis, where it will generates a .csv file once per hour. The .csv file contain info about our company assets, such as type, price, name ,location, etc…
Now i will develop an asp.net mvc web application which will read the .csv data and update a database with this data.
So I am planning to do the following :-
I will create a new database, which will contain the data.
I will create a new asp.net mvc-5 web application which have a SYNC action method, which will read the .csv data, and update the database.
now the problem I am facing is that I need the sync job to run per hour or on a specific schedule. Now from my previous experience I can list these 2 approaches to call an action method on timely basis:-
Inside the asp.net mvc ‘s global.asax I can create a schedule which runs each hour.
I can use third party tools such as Hangfire to schedule the tasks.
Now using any of these approaches will cause this limitation:-
The global.asax or the third party tools such as Hangfire will run under the application pool, and if no action is performed on the application, then the schedule will never run, since the application pool will not be active. But on my previous applications this was not a real problem as the systems contained many views beside the schedule jobs , so the system stay active almost 100% over working hours.
But in my current project the web application will not be accessed by users, since it will only do a single sync job, and there is not any other functionalities for end users. so in this case the sync job will never run , since the application pool will not be active.
So can anyone advice if these approaches sound valid to fix my problem:-
To create a windows schedule task which will be calling the action method URL per hour:-
schtasks /create /tn "my scheduled task" /tr "powershell
-ExecutionPolicy unrestricted -Command \"(New-Object Net.WebClient).DownloadString(\\http://url
.to.be.executed/cron.php\\")\" /sc DAILY /st 07:00:00 /ru System
To create 2 schedule tasks inside the global.asax . one schedule task will call the application url each 5 minutes to keep the application pool alive, and another schedule task which call the sync action method each hour. In this case the application will keep calling itself every 5 minutes which will force the application pool to say alive and the sync job will run each hour even if no users access the system …
So can anyone advice on this please?
Thanks

MVC is all about user interaction, and many users interacting with the same application at that. If all you need is one task to be run on a schedule, then you don't even need a UI for that, and there's no issues of needing to handle multiple simultaneous remote requests or such that a web application satisfies. You could literally just create a console app and use Windows Task Scheduler. MVC is complete overkill, and more than that, unsuited to the purpose.

Related

Windows scheduler API with console application Vs .net scheduler tools with asp.net mvc to execute long running processes inside my asp.net MVC

I am working on an asp.net mvc-5 web application, deployed under windows 2012 & iis-8. my asp.net mvc have many CRUD operations which are implemented as action methods inside my asp.net mvc.
But my asp.net mvc web application will be doing scheduled long running network scan process, the network scan will mainly do the following steps:-
Get the list of our servers and vms from our database.
Get the scanning username and password for each server and vm from a third party tool, using Rest API.
Call some powershell scripts to retrieve the servers & vms info such as network info, memory, name, etc.
Update our ERP system with the scan info using Rest API.
Now I did a pilot project using the following approach:-
I define a Model method inside my asp.net mvc to do the above 4 steps.
Then I install hangfire tool which will be calling the scan method on predefined scheduler.
Also I create a View inside my asp.net mvc which allow users to set the hangfire schedule settings (this require to do an IIS reset on the host server for hangfire to get the new settings).
Now I run a test scan for a round 150 servers which took around 40 minutes to complete , and it worked well. The only thing I noted is that if I set the schedule to run on non-business hours (where no activity is made on IIS) then hangfire will not be able to call the job, and once the first request is made the missed jobs will run. I overcome this limitation by defining a windows task which calls IIS each 15 minutes, to keep application pool live, and it worked well...
Now the other approach I am reading about is doing my above is as follow:-
Instead of defining Model method inside asp.net mvc to do the scan, I can create a separate console application to do the scan.
Then inside my asp.net mvc to create a view which allow users to create and schdule a task inside the windows tasks scheduler. I can do so by integrating with the windows task scheduler API.
Where this windows task will be calling the console application.
Now I am not sure which approach is better and why ? now generally speaking long running/background jobs should not run under iis.. But at the same time defining these long running processes as console app and calling these apps inside windows task scheduler will create extra dependencies on my web application. And will add extra effort when moving the application from move server to another (for example from test to live)..
Beside this I read that tools such as hangfire, quartz and other are designed to allow running long running tasks inside IIS and they eliminate the need to create console applications and scheduling these console applications using task scheduler ..
So can anyone advice on this?
In my opinion, if it is possible to solve the scheduling problem on the web application side, there is no need to create a scheduler task or a new console application for triggering purposes. The problem you will probably face when using scheduling task in a web application is generally common as you might see is that: The scheduler works like a charm during debugging of the web application, but not being able to trigger after publishing it to IIS. At this point the problem is generally related to IIS rather than the schedulers Quartz.NET, Hangfire, etc. Although there are lots of articles or solution methods posted on the web, unfortunately only some of them is working properly. In addition to this, most of them require lots of configuration settings on the web and machine configuration.
However, there are also some kind of solutions for such a kind of scheduling problem and I believe in that it is worthy to give a try Keep Alive Service For IIS 6.0/7.5. Just install it on the server to which you publish your application and enjoy. Then your published application will be alive after application pool recycling, IIS/Application restarting, etc. That is also used in our MVC application in order to send notification mails weekly and has been worked for months without any problem. Here are the sample code that I use in our MVC application. For more information please visit Scheduled Tasks In ASP.NET With Quartz.Net and Quartz.NET CronTrigger.
*Global.asax:*
protected void Application_Start()
{
JobScheduler.Start();
}
*EmailJob.cs:*
using Quartz;
public class EmailJob : IJob
{
public void Execute(IJobExecutionContext context)
{
SendEmail();
}
}
*JobScheduler.cs:*
using Quartz;
using Quartz.Impl;
public class JobScheduler
{
public static void Start()
{
IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
scheduler.Start();
IJobDetail job = JobBuilder.Create<EmailJob>().Build();
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger1", "group1")
.StartNow()
.WithSchedule(CronScheduleBuilder
.WeeklyOnDayAndHourAndMinute(DayOfWeek.Monday, 10, 00)
//.WithMisfireHandlingInstructionDoNothing() //Do not fire if the firing is missed
.WithMisfireHandlingInstructionFireAndProceed() //MISFIRE_INSTRUCTION_FIRE_NOW
.InTimeZone(TimeZoneInfo.FindSystemTimeZoneById("GTB Standard Time")) //(GMT+02:00)
)
.Build();
scheduler.ScheduleJob(job, trigger);
}
}
Also I create a View inside my asp.net mvc which allow users to set the hangfire schedule settings (this require to do an IIS reset on the host server for hangfire to get the new settings).
You're resetting your webserver to update a task's schedule? That doesn't sound healthy. What you might do is keep track of what the scheduled time should be, and on execution, check if the current time is within a certain range of the scheduled time (or has already been executed), otherwise abort the job.
The only thing I noted is that if I set the schedule to run on non-business hours (where no activity is made on IIS) then hangfire will not be able to call the job, and once the first request is made the missed jobs will run. I overcome this limitation by defining a windows task which calls IIS each 15 minutes, to keep application pool live, and it worked well...
Hangfire's documentation has a page about running delayed tasks that mentions what you need to change to accomodate this.
Using Windows' Task Scheduler doesn't seem like a good idea; it's not meant for the execution of ad-hoc, short-lived tasks. You probably need elevation to create tasks, and you'd probably need to define another scheduled task to clean up the mountain of tasks that would exist after a few dozen background jobs have been executed.
You're also correct that using Windows' Task Scheduler would make it more difficult to move your application around.

Console Application or WebService

I am working on a functionality that will generate around 2000 excel sheets. THe process will accept input from front end web application. I dont want my web application to wait till the process of generating the excel files is over. I should write a console application and trigger it through web application or a web service? Whic is the better way of implementation?
Thanks,
Rohit
I would suggest storing excel-gen as a task in a database, then have a background service constantly running, checking that task queue, processing it (creating spreadsheets), then finally updating job records as done. Your asp.net app can in turn, aside from creating job records, simply check on status periodically or on page-refresh.

Hosting WF as Windows Service

I am trying to construct a simple windows workflow to monitor a directory for inbound files and do some DB updates using Windows WF 4.0. Currently I am planning to build a 'WCF Workflow Service' and host it as a 'Windows service' running 24/7 (with a daily service shutdown and startup).
Further in the future I am planning to consume this service using an ASP.NET/WPF application to create a basic dashboard kind of stuff.
Considering the idea of directory polling for files with WF hosted on windows service, does it seems to be a good idea? What can be the cons of this?
Please advice if there are any drawbacks on this or can this achieved by better means?
I'm actually doing this, but it is a bit more complex than you think, and should be avoided if possible.
You should not be blocking from within an Activity; if it is expected to be a long running Activity that is waiting from input from the outside (FileSystemWatcher event, for instance), the workflow should idle itself and wait to be woken from the outside.
How I did this was I created a workflow extension that hosted the FileSystemWatcher. Once the Activity was ready to watch for a file, it created a bookmark and passed it to the extension.
The extension then started the FSW, holding onto the bookmark.
When a FSW event was fired, the extension resumed the bookmark, passing in an object that contained details about the event. The Activity did what was needed with the event, then re-scheduled itself.
Normally I wouldn't have done this, but I had some requirements that forced me to use WF4 to accomplish this goal. If I didn't have to use WF4, I would have just spun up the FSW within the service and consumed the events.
Unless you expect to have to be very flexible with your configuration detailing what you do with the FSW event, and expect this to change relatively often during deployment of the service, I'd skip WF4.

Scheduling a asp.net function?

Is it possible for user who access my page to run a schedule task in asp.net? any reference?
The page can turn on a flag to run a scheduled process, than a windows service can be setup to monitor that flag (stored in DB or file), when its turned on, run the process.
HTH.
ASP.NET itself can't run a scheduled task, but you can use Powershell or Windows Task Scheduler to queue up and schedule tasks to be run at a later time.
If you want a user to be able to alter them it would probably be easiest to have a task set to call a special ASP.NET page which would then run any logic needed to actually do the tasks scheduled by users.
If you have a SQL database backend, you can always create SQL Agent jobs to run and use your ASP.net application to control them. (When to start, frequency, etc)

Long-running thread process under ASP.NET + WCF

Duplicate
This is a close duplicate of Dealing with a longer running process in WCF. Please considering posting your answer to that one instead of this.
Original Question
I'm implementing the business layer of an application that must run some background processes at scheduled times. The business layer is made up of several WCF services all running under the same web application.
The idea is defining a set of 'tasks' that must be run at different times (eg. every 5 minutes, everyday at 23:00, etc). That wouldn't be hard to implement as a windows service, but the problem is, the tasks need access to data caches that are living in the services, so this 'scheduler' must run under the IIS context in order to access that data.
What I'm doing currently is using a custom ServiceHostFactory in one of the WCF services which spawns a child thread and returns. The child thread sleeps and wakes up every X minutes to see if there are scheduled tasks and executes them.
But I'm worried about IIS randomly killing my thread when it recycles the application pool or after some inactive time (eg. no activity on any of the WCF services, which listen for requests from the presentation layer). The thread must run uninterrupted regardless of activity on the services. Is this really possible?
I have found an article by someone doing the same thing, but his solution seems to be pinging the server from the child thread itself regularly. Hopefully there is a better solution.
I have at some point implemented a Windows Service that would load a web page on a regular basis. The purpose of that was was that the site was hosting a Workflow Foundation runtime, and we wanted to ensure that the web application was brought back up after IIS recycling the application pool. Perhaps the same approach can be used in this case; have a service (or Scheduled Task in Windows; even simpler) run every x minutes and load a page that will check for tasks.
Is it a possibility to run either a Windows Service or place applications in the Windows Scheduler to execute methods in the WCF at certain times? Maybe use a BackgroundWorker inside the WCF. Another option would be for WCF to spawn other applications to do the business logic, passing the appropriate data, or pointers to the data in memory(unsafe).

Resources