Send Birthday Emails to Employees MVC ASP.net - c#

I'm trying to create a function where I send Email to a user when it their birthday. I have all their personal data in my database, so I just wonder like where do i start? Or what do i do? I'm creating this in an MVC app. This is what I've done so far.
This is my function in my repository.
public List<Employee> GetEmployeesBasesOnBirthDate(int customerId, string birthdate)
{
return db.Employees.Where(x => x.CustomerId == customerId && x.BirthDate.Contains(birthdate)).ToList();
}
And this is what i do in my Controller
public ActionResult BirthdayEmail()
{
var repository = new SiteRepository();
var employeebirthday = repository.GetEmployeesBasesOnBirthDate(CommonHelper.CustomerId, DateTime.Now.ToString());
return View();
}
What do I do now?

You can create a method which automatically send Emails on their birthdays.
using System.Net.mail; includes a method for mailmessage you can use it to make you mail message body and use your database data to send mail templets to your Employees.
I know it's not the complete solution but if you do little more search on mail templates you will get solution for your code.
Hope it helps.

You could change your method GetEmployeesBasesOnBirthDate(int customerId, DateTime birthdate)
And then compare dates, do you need exact time or dates only ?
After that you should loop trough employee list and send email.

I'm guessing you'll want to send out the emails in an asynchronous fashion rather than from an action method. If that is the case, you will need a background job that:
gets fired automatically in the morning
retrieves the list of employees that were born on that day
actually sends out the emails
For asynchronous jobs you want to look into Hangfire which, among other things, lets you set up recurring tasks. Moreover, its documentation also includes a tutorial teaching you how to send mail.
This could be a sound architecture, but if you need more specific answers you'll need to post specific questions.
Note: the fact that dates are stored as strings in the db will cause a lot of grief and ugly parsing all over the place. If at all possible change that to use an actual date type.

Related

How do I show a loading screen/icon while loading a view that requires querying a database? Asp.Net Core C#

Currently I have a view that has just a single form with three values. When a user submits the form with those three values, my controller checks if all three values actually have a value other than being empty, and if they do then it calls my service that fetches data.
public IActionResult Index(string clientName = "", string tableName = "", string date = "")
{
if (!string.IsNullOrEmpty(clientName) && !string.IsNullOrEmpty(tableName) && !string.IsNullOrEmpty(date))
{
// Unimportant stuff for setting temp variables for FetchData parameters removed
TheData = _fieldDataService.FetchData(tempAcr, tempID, tableName, date, numRows);
}
return View(TheData);
}
My goal is to make the view display a loading icon or something while the data is being fetched. I've looked into JQuery and Ajax but I have no experience with either and cannot figure out how to apply them to my specific task. Since I am using Asp.Net Core, I also looked into using Blazor, but I couldn't wrap my head around it either.
Could somebody point me in the right direction as to what I should/could use to solve this problem? I have a vague understanding that there needs to be some sort of asynchronous function that retrieves the data, but nothing more than that.
You need to fetch the data with JavaScript and manipulate the UI to show a loader. But anyway, a request like this should be so fast, that you don't even need a loader.
I'm also a bit worried that you are passing a tableName as input parameter. You aren't just string concatenating the query right? You might be susceptible to SQL injections, see https://en.wikipedia.org/wiki/SQL_injection.
To do a request with JavaScript, look into the XMLHttpRequest, see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest, or the new way of doing it with fetch(...), see https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch.
This answer shows a more practical example: Display loading image while ajax fetches file content.

Trying to sync data from third party api

This question has probably been asked correctly before, and I'll gladly accept an answer pointing me to the right spot. The problem is I don't know how to ask the question correctly to get anything returned in a search.
I'm trying to pull data from a 3rd party api (ADP) and store data in my database using asp.net core.
I am wanting to take the users returned from the API and store them in my database, where I have an ADP ancillary table seeded with the majority of the data from the api.
I would then like to update or add any missing or altered records in my database FROM the API.
I'm thinking that about using an ajax call to the api to retrieve the records, then either storing the data to another table and using sql to look for records that are changed between the two tables and making any necessary changes(this would be manually activated via a button), or some kind of scheduled background task to perform this through methods in my c# code instead of ajax.
The question I have is:
Is it a better fit to do this as a stored procedure in sql or rather have a method in my web app perform the data transformation.
I'm looking for any examples of iterating through the returned data and updating/creating records in my database.
I've only seen vague not quite what I'm looking for examples and nothing definitive on the best way to accomplish this. If I can find any reference material or examples, I'll gladly research but I don't even know where to start, or the correct terms to search for. I've looked into model binding, ajax calls, json serialization & deserialization. I'm probably overthinking this.
Any suggestions or tech I should look at would be appreciated. Thanks for you time in advance.
My app is written in asp.net core 2.2 using EF Core
* EDIT *
For anyone looking - https://learn.microsoft.com/en-us/dotnet/csharp/tutorials/console-webapiclient
This with John Wu's Answer helped me achieve what I was looking for.
If this were my project this is how I would break down the tasks, in this order.
First, start an empty console application.
Next, write a method that gets the list of users from the API. You didn't tell us anything at all about the API, so here is a dummy example that uses an HTTP client.
public async Task<List<User>> GetUsers()
{
var client = new HttpClient();
var response = await client.GetAsync("https://SomeApi.com/Users");
var users = await ParseResponse(response);
return users.ToList();
}
Test the above (e.g. write a little shoestring code to run it and dump the results, or something) to ensure that it works independently. You want to make sure it is solid before moving on.
Next, create a temporary table (or tables) that matches the schema of the data objects that are returned from the API. For now you will just want to store it exactly the way you retrieve it.
Next, write some code to insert records into the table(s). Again, test this independently, and review the data in the table to make sure it all worked correctly. It might look a little like this:
public async Task InsertUser(User user)
{
using (var conn = new SqlConnection(Configuration.ConnectionString))
{
var cmd = new SqlCommand();
//etc.
await cmd.ExecuteNonQueryAsync();
}
}
Once you know how to pull the data and store it, you can finish the code to extract the data from the API and insert it. It might look a little like this:
public async Task DoTheMigration()
{
var users = await GetUsers();
var tasks = users.Select
(
u => InsertUser(u)
);
await Task.WhenAll(tasks.ToArray());
}
As a final step, write a series of stored procedures or a DTS package to move the data from the temp tables to their final resting place. If you are using MS Access, you can write a series of queries and execute them in order with some VBA. At a high level it would:
Check for any records that exist in the temp table but not in the final table and insert them into the final table.
Check for any records that exist in the final table but not the temp table and remove them or mark them as deleted.
Check for any records in common that have different column values and update the final table.
Each of these development activities raises it own set of questions, of course, which you can post back to StackOverflow with details. As it is your question doesn't have enough specificity for a more in-depth answer.

Notify user if their search criteria are met

I developing a sale system using asp.net mvc. My search system allows users to save their search criteria and will notify them by email when a new product is posted is met their criteria. I tried the following:
The first way: Create a function to send bulk mail through gmail and I put this function in the post function. You can see the code described below to understand what I said:
public ActionResult PostProduct()
{
....
var list = Check(); // get a list of user email when their search criteria are met with the posted product
Send(list); // send email to the list
// I don't know how long does it take to complete this function?
}
However, this method requires a lot of resources from the server and takes a lot of time to respond (if the number of emails up to 1000, it would be a bad thing), but I can customize the parameters into email content (such as links, images, ...)
The second way: I used a mail service (MailChimp) and I called its API successfully, sending mail seems easy but I can not adjust the input parameters. That means I can not customize the content of my email.
I would like to ask people if there is a better and wiser way of doing things than I used to. Thank for reading

Find All Available Meeting Rooms using Microsoft.Office.Interop.Outlook

I was developing one application where I want to retrieve the available rooms from the "All Rooms" of the outlook address book. I am able to retrieve all the room entries from "All Rooms" Address Entry List. And then able to search for individual room's availability by calling AddressEntry.GetFreeBusy().
But the problem I am facing is the time performance of the code. If the number of rooms is high(let's say 500) then the time take to search availability of the room(worst case scenario where available room locates near to last of the list) is very high.
Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application()
var allRooms = app.Session.AddressLists["All Rooms"].Cast<Microsoft.Office.Interop.Outlook.AddressEntry>().ToLis();
DateTime today = DateTime.Today;
foreach(var room in allRooms)
{
//the below function will return the room status in a string of 1&0 for an interval of 1 min
string status = room.GetFreeBusy(today, 1, true); //sequentially calling this method is costly. What improvement can I do here?
//process the status and make some if free for certain time period add to list of available list
}
The GetFreeBusy method accepts three parameters and the default value for the MinPerChar parameter is 30 minutes. But your code only checks the first minute of the appointment. You need to go over the whole duration of your meeting (at least 30 minutes). Take a look at the similar forum thread.
If you are a .Net Developer then use Microsoft Graph APIs for this purpose. I used
POST /me/calendar/getSchedule
POST /users/{id|userPrincipalName}/calendar/getSchedule
from to achieve this. You can login as your userid and use ME option or you can use application mode login to login and use {id|userPrincipalName} to get calendar details for a room.
This link provides the basics on how to login and have good examples for Graph in general.
https://developer.microsoft.com/en-us/graph/graph-explorer
Ref:
https://learn.microsoft.com/en-us/graph/api/calendar-getschedule?view=graph-rest-1.0&tabs=http

Initial Exchange Web Services sync start on given time

We are doing Exchange web server synchronization with our application. To identify EWS changes we use; service.SyncFolderItems() method, like explain on MSDN. But, while doing initial sync it takes all the events in calendar, very older ones too. To avoid getting older events we need to use time period or Sync Start From time while requesting changes from SyncFolderItems() method.
1) Can SyncFolderItems() method accept user given time period when getting events from EWS ? & How ?
2) If not, Any workaround ?
There is a way to avoid older events in calendar using service.SyncFolderItems() method.
<SyncFolderItems>
<ItemShape/>
<SyncFolderId/>
<SyncState/>
<Ignore/>
<MaxChangesReturned/> <SyncScope/>
</SyncFolderItems>
That Ignore parameter will accept List of event Ids. and ignore them while syncing. To do that , First we need to retrieve older event IDs, Exchange will only accept two years old event
DateTime startDate = DateTime.Now.AddYears(-2); //start from two years earlier
DateTime endDate = DateTime.Now.AddMonths(-1); // End One Month before,
//you can use Convert.ToDateTime("01/01/2013"); what ever date you wanted.
Create Item id List;
List<ItemId> itmid = new List<ItemId>();
Create Calendar View object;
CalendarView cView = new CalendarView(startDate, endDate);
Retrieve Appointments;
// Retrieve a collection of appointments by using the calendar view.
FindItemsResults<Item> appointments = service.FindItems(WellKnownFolderName.Calendar, cView);
Or you can use this, But previous code have some optimization. (Google)
FindItemsResults<Appointment> appointments = service.FindAppointments(WellKnownFolderName.Calendar, cView);
Add retrieve event ids into list,
foreach (var item in appointments)
{
itmid.Add(item.Id);
}
Finally, in your SyncFolderItems method will looks like this;
service.SyncFolderItems(new FolderId(WellKnownFolderName.Calendar), PropertySet.IdOnly, itmid, 10, SyncFolderItemsScope.NormalItems, sSyncState);
Hope this will help any of you.
Currently, SyncFolderItems only supports synchronizing the entire mailbox. It doesn't support synchronizing starting from a specific time period. This type of request has been shared with the product planners. Hopefully we'll see this type of functionality.
In terms of workarounds, you could:
1) Sync all of the events with only the ItemId. Throw away items don't need.
2) Perform a FindItems with your intended time period, use GetItem (Bind) to get the events, and then use notifications to learn when a new item arrives, or when an item is updated. What you won't get with this is what has changed. For new items, this isn't an issue. But for updated items, you'll have to perform a GetItem (Load) and then diff the updated and old items to see what has changed.

Categories

Resources