I have an ASP.NET MVC web application which is hosted by an external provider, on IIS 7.
I wish to run a process every 15 minutes or so, which checks a backlog of emails that need to be sent, and actually sends them.
It seems that the normal way to do this is with Microsoft Message Queue, but since this is a hosted environment which I can't directly control, I won't be able to install or configure MSMQ.
So far I've decided to do it by appending rows to a table in my SQL Server database (same hosting).
So how should I implement the bit where I check the backlog and send the emails?
Should it be some kind of separate thread in my main web application, which restarts itself every 15 minutes?
Another option I considered was just opening an HTTP-POST interface which, when called with an appropriate admin password, runs an iteration of the email sender.
I could then create a small console app on my local PC which calls the interface every 15 minutes.
The first option is simpler, but the second might be more robust.
Any ideas?
I would recommend you taking a look at Quartz.NET. Also an important thing you should be aware is that the web server could unload the ASP.NET application from memory if it is not used meaning that all threads that have been spawned would simply die. That's one of the reasons why such tasks shouldn't be performed in ASP.NET applications but rather offloaded in Windows Services.
Jeff Atwood did a post on how he originally achieved the badge system on Stack Overflow using an expiring cache to reset the process periodically.
https://blog.stackoverflow.com/2008/07/easy-background-tasks-in-aspnet/
I have done something similar to this in the past sending emails out every day. The service was non essential, and it didn't matter if the emails missed a day or two, as they would go out eventually anyway, but the system worked quite well. It's all asp.net so works fine in the hosting environments I use, without access to service on the server or creating a local trigger from your desktop.
Related
I am developing a tuition fee management system using asp .net MVC for a university assignment. I am quite new with asp .net just learn it this April 2021. One of the requirements is that the system automatically sends an email every month to every user as a reminder about the outstanding balance. So how do I start to develop this requirement since I've been searching and only found tutorials email send manually and to one user only?
There is not built-in functionality in .NET that runs your code once a month, but there are several tools to do this. If you are using Azure, AWS or GCP (or any other cloud platform), you’d might consider a serverless Function to do this. These Functions can be triggered once a month by the cloud provider.
If you’re not hosting it in the cloud (or want to avoid any provider-specific features), you can use for instance Quartz (https://www.quartz-scheduler.net) or Hangfire (https://www.hangfire.io). There are many libraries available, all with their pros and cons. Hangfire for instance has a dashboard built-in to monitor and debug any issues, but this also costs some server resources and might be an overkill if you have a single job to run.
You should however take into account that communication with an SMTP server is quite time-consuming. Sending thousands of emails could therefore take a lot of time. Especially if you are using serverless Functions, this will become an issue due to the time-limits that apply for these Functions. Also when you run these as jobs in Quartz or Hangfire, you want to take into account this job might be aborted halfway. Therefore, you usually insert those mails into a queue (or database) and then have a second process to actually send these mails. Maybe even via a specialized email delivery service?
In my job we are building Web Apps that rely on a common Enterprise class. This class has a method that sends a request to our server every time the app_start or app_end event triggers so we can monitor the status remotely. But we are now requiring that at least once a day the web app reports its status, a bit like telemetry. I don't know how to accomplish this, so far I have found some options, but some have limitations:
Use hangfire. I don't like this since it requires to setup a Database or add more tables and install a new Nuget package on each project, but could be my last option.
Use a Windows Service that reads databases. This could be less work but it can't access the Web App web.config code
Use a Javascript tasks that sends an AJAX request. This requires to have an open web browser and is a big risk.
I'm looking for a server side approach that could allow to set to trigger an event or function at 1am.
I would got with Hangifire.
It is dead easy to setup and very reliable.
You don't need to setup the database, you might want to check memory storage:
https://github.com/perrich/Hangfire.MemoryStorage
Also check:
What is the equivalent to CRON jobs in ASP.NET? - C#
You can use FluentScheduler instead of Hangfire (it is more lightweight).
Instead of a Javascript task that sends an AJAX request you can use a WebJob or an Azure Function.
I'm working on an ASP.net MVC project and I noticed that when the web app gets published, IIS doesn't build a cache or anything for the views until a controller has been hit. So in other words it can take a very long time for a visitor to get the page loaded if they happen to be the first person to visit the page after the whole project gets republished.
To counter this, I'd have to manually hit every endpoint with a view in the project once. When the project first started this was a simple task but as you can imagine right now this is not maintainable.
My question is how do I execute a batch of curl commands to the endpoints with views in the project? I'm not sure where to start. Is there a programmatic way to create the batch command and append it to the AfterPublish event?
The behaviour you're encountering is due to Application Pool Start Mode in IIS. Instead of implementing AfterPublish events, you're probably better off configuring your Application Pool to do what you want it to do.
Start Mode
A few web applications take a significant amount of time to start up. IIS by default only launches a worker process when the first request for the web application is received. So for the web applications that require a longer time to initialize, users might see slow responses.
For such applications it is a good idea to launch the worker process as soon as IIS is started. The application pools have a startMode setting which when set to AlwaysRunning launches the worker process for the application pool as soon as IIS is started.
IIS 8 provides you this setting in the Application Pool Settings UI.
Source: https://blogs.msdn.microsoft.com/vijaysk/2012/10/09/iis-8-whats-new-application-pool-settings/
If you really want to run those actions after you publish the website, you'll have to learn more about the Visual Studio build process. This link can get you started: https://learn.microsoft.com/en-ca/visualstudio/msbuild/how-to-extend-the-visual-studio-build-process?view=vs-2017
IIS has to start the application again after I rebuild the website, it takes a very long time and it cuts into productivity.
I am wondering if I can somehow replace the MVC website with a small console application that listens to a port and returns a string that is then interpreted by the browser as valid html. I am not sure if this was done.
Something very lightweight.
So that it does not take 30-50 seconds on each rebuild, to see my site in action.
I want to build my app, then immediately do a request and test it and not wait almost a minute.
Is there something that does that?
There is a way to build Self-Hosted Web Api applications.
It can be console exe, or setup to run as a service.
The ASPNET engine, is designed to compile itself (views, etc), but a minute? This might be due to the weak PC, for instance.
You can use the Browser control in a windows form app. But it is not recommended, there is no way of avoiding IIS restart since your files have been changed.
I'm developing an application that has various types of Notifications. Examples of notifications:
Message Created
Listing Submitted
Listing Approved
I'd like to tie all of these up to SignalR so that any connected clients get updates in real-time.
As far as architecture goes - right now the application is entirely within a single solution hosted on an Azure Website. The triggers for each of these notification types live within this application.
When a trigger is hit, I'd like to tell signalR, "Hey, send this message to the following clients" along with a list of userIds. I'm assuming that it's possible to identify connected clients based on userId... and I'm assuming that the process of send message to clients should be executed outside of the web application, so as to not slow down the MVC app or risk losing data in a broken async call. First question - are these assumptions correct?
Assuming so, this means that I'll need something like a dedicated web/worker role to be sending messages to clients. I could pass messages from my web application directly to this process, but what happens if the process dies? The resiliency concerns lead me to believe that the proper way to pass messages would be via a queue of some sort. Second question - is this a valid train of thought?
Assuming so, this means that I can either use a good ol' Azure SQL database as a queue, but it seems like there are some specialized (and maybe cheaper) services to handle message queueing, such as this:
http://www.windowsazure.com/en-us/develop/net/how-to-guides/queue-service/
Third question: Should this be used as a queueing mechanism for signalR? I'm interested in using Redis for caching in the future... would Redis be better or worse than the queue service?
Final Question:
I've attempted to illustrate my proposed architecture here:
What I'm most unclear on here is how the MVC app will know when to queue, or how the SignalR processes will know when to broadcast. Should the MVC app queue blindly, without caring about connected clients? This seems to introduce a lot of wasted space on the queue, and wasted cycles in the worker roles, since a very small percentage of clients will ever be connected.
The only other approach I can think of is to somehow give the MVC app visibility into the SignalR processes to see if the client is connected... and if they are, then Enqueue. This makes me uncomfortable though because it means I have to hit that red line on the diagram for every trigger that gets hit, which - even if done async - gets me worrying about performance and reliability.
What is the recommended architecture for scalable, performant SignalR message broadcasting? Performance is top priority, followed closely by cost.
Bonus question:
What if some messages are of higher priority than others? Should two queues be used, one of which always gets checked before the other?
If you want to target some users, you'll have to come up with a mechanism, off the top of my head I can give an example, if any user hits a page, you can create a group for that page and push to all users in that group/in that page.
It's not clear to me why you need the queues. Usually users subscribe to some events when hitting a page or by some action like join a chat room, and the server pushes data using those events/functions when appropriate.
For scalability, you can run signalr in different servers, in which case you should use sql server, or service bus or redis as a backplane.
Firstly you need to create a SignalR server to which all the users can connect to. This SignalR server can be created either in the web role or worker role. If you have a huge user base then its better to create the SignalR server on a separate role.
Then wherever the trigger is hit and you want to send messages to users, you have to create a SignalR client (.NET or javascript) and then connect to SignalR server. Then you can send the message to SignalR server which in turn will broadcast to all the other users connected. After that you can disconnect the connection with SignalR server. This way you dont have to use queues to communicate with the SignalR role.
And also to send messages to specific users you can store the socket id's along with their user id's in a table (azure table storage should do) when they connect to SignalR server. Then using socket id you can send messages to specific user.