I have web project that created in Visual Studio 2010 and use SQL Server 2008 R2 for database,
Commonly i use SQL Server Agent to send report (from SQL database) to my client email, and now i want to move my application to other web hosting. My question is there any method to generate report and send to email automatically by schedule in web hosting?
Thank you for your suggestion.
Scheduling tasks in a web project is possible using the Revalee open source project.
Revalee is a service that allows you to schedule web callbacks to your web application. In your case, you would schedule a callback that would generate your report and send emails automatically. Revalee works very well with tasks that are discrete transactional actions, like updating a database value or sending an automated email message (read: not long running). The code to generate your report and send the emails would reside within your web app. More specifically, on a target web page that Revalee would call at your scheduled time. When your application launches for the very first time, then you would schedule the first web callback. When your application is called back to generate the report, then you would schedule the next callback.
To use Revalee, you would:
Install the Revalee Service, a Windows Service, on your server. The Windows Service is available in the source code (which you would compile yourself) or in a precompiled version available at the Revalee website (above).
Use the Revalee client library in your Visual Studio project. The client library is available in the source code (which, again, you would compile yourself) or in a precompiled version available via NuGet.
You would register a future callback (for example, at a specific time) when your application launches via the ScheduleMidnightCallback() method (see below).
private DateTimeOffet? previousCallbackTime = null;
private void ScheduleMidnightCallback()
{
// Schedule your callback for midnight tomorrow
var tomorrow = DateTimeOffset.Now.AddDays(1.0);
var callbackTime = new DateTimeOffset(tomorrow.Year,
tomorrow.Month,
tomorrow.Day,
0, // Hour
0, // Minute
0, // Second
tomorrow.Offset);
// Your web service's Uri, including any query string parameters your app might need
Uri callbackUrl = new Uri("http://yourwebapp.com/Callback.aspx");
// Register the callback request with the Revalee service
RevaleeRegistrar.ScheduleCallback(callbackTime, callbackUrl);
previousCallbackTime = callbackTime;
}
When the web scheduled task activates and calls your application back, you perform whatever action you need to do at midnight and you schedule the next callback too. You do this by adding the following method call (CallbackMonitor()) to your Callback.aspx page handler.
private DateTimeOffset? mostRecentCallback = null;
private void CallbackMonitor()
{
var midnight = new DateTimeOffset(DateTimeOffset.Now.Year,
DateTimeOffset.Now.Month,
DateTimeOffset.Now.Day,
0, // Hour
0, // Minute
0, // Second
DateTimeOffset.Now.Offset);
if (!mostRecentCallback.HasValue
|| mostRecentCallback.Value < midnight)
{
mostRecentCallback = midnight;
// Perform your report generation & send email-related tasks
// ...do your work here...
// Schedule subsequent callback
ScheduleMidnightCallback();
}
}
I hope this helps.
One last thing: Revalee does have an ASP.NET MVC specific library as well, in case you are migrating your web application from ASP.NET to ASP.NET MVC.
Disclaimer: I was one of the developers involved with the Revalee project. To be clear, however, Revalee is free, open source software. The source code is available on GitHub.
Related
I want to create some functions in ASP.NET Web API, which should be executed daily at specific time and do specific task like update statuses/Records/Generating Emails, SMS.
Should i create a TaskService in Code
using System;
using Microsoft.Win32.TaskScheduler;
class Program
{
static void Main(string[] args)
{
// Get the service on the local machine
using (TaskService ts = new TaskService())
{
// Create a new task definition and assign properties
TaskDefinition td = ts.NewTask();
td.RegistrationInfo.Description = "Does something";
// Create a trigger that will fire the task at this time every other day
td.Triggers.Add(new DailyTrigger { DaysInterval = 2 });
// Create an action that will launch Notepad whenever the trigger fires
td.Actions.Add(new ExecAction("notepad.exe", "c:\\test.log", null));
// Register the task in the root folder
ts.RootFolder.RegisterTaskDefinition(#"Test", td);
// Remove the task we just created
ts.RootFolder.DeleteTask("Test");
}
}
}
or should i create a .bat file and create a new task in Task Scheduler.
As you have mentioned in the question, you need to do the specific tasks like update statuses/Records/Generating Emails, SMS etc.
So database access comes into the scenario and on the other hand, you will have to send emails and SMS's which may require third party libraries or other configuration setting access.
Thus, to do all this it will be better to go with code implementation via which you can maintain your changes and requirements well enough.
About the ".bat file and windows scheduler", you need to have great skills using the limited batch commands available to fulfill your requirement.
So, my suggestion is code, .exe and windows scheduler task.
Also, this should be a separate application, don't mix it up with Web API code. You can always create a new project in the web API solution with web API project and reuse whatever code is possible.
You should do this outside your web code. This is because your webapp should have no access to the task system or web service. By default IIS 7.5+ runs app's in their own limited user account (https://www.iis.net/learn/manage/configuring-security/application-pool-identities).
If you want to have a reliable tasks scheduling wherein you can apply time interval depend on your choice, I recommend [quartz]: https://www.quartz-scheduler.net/. Quartz allow to add/edit/delete/etc a scheduled task easily, manageable and no CPU overhead.
Moreover Quartz is an open source job scheduling system that can be used from smallest apps to large scale enterprise systems.
I recommend you to try Hangfire. It's free and you can use it for free in commercial app. Ducumentation you can find here.
In a C#/asp.net application I search for a way to schedule jobs to be executed once, at a specific point in time. Eg. at February 4th 2016 at 02:00. That is:
Are there any frameworks out there that can do this (scheduling jobs for execution at a specific point in time)? I know Tivoli Workload Scheduler from IBM but that seems rather aged and expensive.
It would be nice if the framework came with a web dashboard allowing job administrators to administer (schedule and overview) jobs I some calendar like view.
Hangfire does exactly what you want by passing a DateTime value into the schedule method:
BackgroundJob.Schedule(yourMethodCall, new DateTime(2015, 03, 07, 12, 00, 00))
Comes with a nice web front end too :)
If you want to schedule the job in c#, check out http://www.quartz-scheduler.net/
If you are running on a Windows-based server, then you could use the Revalee open source project to solve this issue. Revalee, which runs as a Windows Service, stores all scheduled tasks in a persistent data store (specifically, the Extensible Storage Engine (ESE) [aka. JET Blue]), so that you will not lose state even if your entire server needs to be rebooted. When your task is due, Revalee calls your application back in order to trigger whatever task you needed to run.
For example, from within your C# ASP.NET application you would register a Revalee callback like so (after installing & configuring the Revalee.Client package):
private void ScheduleSendMessage()
{
// The callback time will be 4 Feb 2016 2:00 UTC (example assumes UTC)
DateTimeOffset callbackTime = new DateTimeOffset(2016, 2, 4, 2, 0, 0, 0, TimeSpan.Zero);
// The callback url is set (your send message code will reside there)
Uri callbackUrl = new Uri("http://mywebapp.com/SendMessage.aspx");
// Register the callback request with the Revalee service
RevaleeRegistrar.ScheduleCallback(callbackTime, callbackUrl);
}
I have an ASP .NET page which allows users to start programs. These programs and the parameter are stored in a database and a windows service then executes these programs.
The programs are dlls which implements my IPlugin interface, so I can add them at runtime (the dlls are loaded at runtime so I can add them at runtime without compiling or restarting the service).
I created the ASP .NET page, more than 10 programs (plugins) and the windows service. Everything is running fine, but I think the implementation of the windows service is bad.
The windows service periodically queries the database and executes the needed program if it gets a new entry. The service can run multiple programs in parallel (at the moment 3 programs).
Currently my service method looks like this:
while (Alive)
{
// gets all running processes from the database
Processes = Proc.GetRunningProcs();
// if there are less than 3 processes running and
// a process is in queue
if (ReadyToRun())
{
// get next program from queue, sets the status to
// runnig and update the entry in the database
Proc.ProcData proc = GetNextProc();
proc.Status = Proc.ProcStatus.Running;
Proc.Update(proc);
// create a new thread and execute the program
Thread t = new Thread(new ParameterizedThreadStart(ExecuteProc));
t.IsBackground = true;
t.Start(proc);
}
Thread.Sleep(1000);
}
I have a method that queries the database for entries with status 'Canceling' (if a user cancels a program, the status will be set to 'Canceling') and does a Thread.Abort().
Is there a better practice? Like using tasks with the cancel mechanism or is the whole concept (storing the processes in database (program name, parameter, status,... and querying this information periodically) wrong?
As an alternative you can use some existing libraries for your purposes like Quartz.NET http://www.quartz-scheduler.net/. It takes care about job persistence, job scheduling and many other things. All you must do to create an adapter and put it into Windows Service.
I'm working on an MVC .Net web application. I have a database in which i have a table called Tasks, every task is associated to one user and every task has a delay. I want to send emails automatically to the user to whom the task is associated before two days (for example) from its expiration date.
You can use Windows Service to send email automatically.
Please refer below link
http://www.dotnetfunda.com/articles/article931-how-to-send-mail-automatically-for-every-five-minutes-using-csharp.aspx
You can set the timer for 2 days with your logic.
You could write a Windows Service application or a Console application that will be scheduled to run at regular intervals using the Windows Scheduler (for example once a day), it will query your database, extract the records matching the required criteria and, yeah, SmtpClient.
The reason I am saying this is because this task should not be done by your web application. It should be performed by a separate application. Recurring background tasks such as the one you need to perform is a no-no in a web application. The Haacked discussed why this is a very bad idea: http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx
Little mock up example:
DateTime today = DateTime.Now;
TimeSpan diff = user.Tasks.ExpirationDate.Subtract(today);
int dateDiff = Convert.ToInt32(diff.TotalDays);
if (dateDiff == 2)
{
//Send Email
}
You could then place this in a Services/Email folder in your mvc app and create a separate console app to request the page everyday, therefore running the query, e.g:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("YOUR PAGE");
string response = new System.IO.StreamReader(req.GetResponse()
.GetResponseStream()).ReadToEnd();
You would use Windows Task Scheduler to run the console app every day which would start the console app > console app requests page > page checks expiration date on tasks > sends emails
in my web-application I want to send mail for users according to pre selected periods by themselves. for example: 1 HTML Mail Per 3days to user 01 and 1 HTML Mail Per 20days to user 02
how can I perform that? any resources? I can send mail by my app from My Gmail Account to any mail addresses in my tables but i dont know how to send it automatically in a period of time.(i use C# and SQL Express)
Help me out!
I found the Solution. according to my search we have 3 ways to handle that:
working with SQL Server to send mail notification in periods of time.(or this)
using Windows service and Creating Timer object and checking the time with it.
but in ways 1 and 2 we should access to server and we need dedicated hosting server to for example installing WinService on it. so it does not work in a sharing Host space we usually use. So I Found the best way as you see:
3. Simulating Windows Services Using ASP.NET Caching For Scheduled Jobs.
the link above is a terrific solution. So there is no need to work out-side of our web application.
You will need something which can periodically run jobs for you, like a cron daemon or windows task scheduler.
Essentially you have the periodic job kick off and do whatever mail handling you need.
You can also do this from code if you can create a windows service to basically sleep until the next batch of mails needs to be sent.
The easiest is to write the task scheduler or cron job to run periodically. In that way you just need a small piece of code to handle the mail sending portion and then you just schedule it to run once an hour or day or whatever needed.
Hai,
Have a look at quartz.net
Quartz.NET is a full-featured, open source job scheduling system that can be used from smallest apps to large scale enterprise systems.
Quartz.NET is a port of very propular open source Java job scheduling framework, Quartz. Quartz.NET supports clustering and database persistence out-of-the-box and has powerful means to schedule jobs using cron like expressions, interval triggers and exclusion advices.
The great thing about IIS hosted ASP.NET is that IIS will (by default) periodically recycle your application pool according to the settings on the app pool itself.
When your application pool is starting (which could be at least once a day especially if it's allowed to idle i.e. a business app where most activity is 9-5) the Application_Start event-handler in Global.asax is fired. This could be used for your recurring task.
Now you don't necessarily want to run this email send synchronously within that Application_Start handler because to me it seems this messaging functionality is not core to the startup but by all means use this event-handler as an easy way to periodically do your housekeeping.
To send async you should use async delegates for example.
i think there a solution:
1- you have to add 2 column in the user table in your sql db if you have a user table and in the first column add the date of the last email sent to the user and the second column has the period for sending the email for that user for ex:
LastEmailSentDate datetime
SendEmailPeriod int
2- in your application code write a function that compare the last date of the last sent email with the period of the sending the email.
// here the funciton code
public void CompareLastSentDate()
{
// lets assume that you bring the data for the db using Sqdatareader reader
//get the field from the LastEmailSentDate field in the database as i mention before
DateTime LastEmailSentDate = Convert.ToDate(reader["DatePeriod"])
// get the field from the SendEmailPeriod of the user field from database
int sendEmailPeriod = Convert.Toint32(reader["SendEmailPeriod"])
// now you have the date before the period of day ex: before 3 days depend on user
DateTime DatePeriod = new DateTime(DateTime.Now.Year, DateTime.Now.Month, (DateTime.Now.Day - sendEmailPeriod ));
// if the last email send is before period of day that mean u have to send an email again
if(LastEmailSentDate.Day <= DatePeriod.Day)
{
// sent the email to the user
}
}
note: now u can loop among the users and sent the email
you can call this function once in a day by calling it from ur app home page Page_Load event and after the first call of the day add an application["LastFunctionCallDate"] = DateTime.Now flag so in the next you can check this flag if its == today and if not call it again