Back to Home

Save your form data within milliseconds with .Net Core 2.0

In these days when people are highly impatient, you can save website form data in a fast way and make a difference. Although ORMs like Entity Framework, NHibernate are commonly used in corporate architecture of today, you can give a chance to Dapper in communication forms and discover how fast the application is.

Required NuGet Packages

Dapper HangFire Hangfire.MySqlStorage.NetCore MailKit

Steps

First, to make Dapper connection, we are adding connection string in our controller. After that, we are defining our connection within controller constructor.

private string connectionString; public MainController() { connectionString = @"Data Source=localhost;Initial Catalog=mytable;User Id=user;Password=xyz123;"; }

By using IDbConnection interface, we are creating MySQL connection method.

public IDbConnection Connection { get { return new MySqlConnection(connectionString); } }

Adding some Html and Jquery.

<form id="contactForm"> <div> <label>Name</label> <input type="text" id="name" /> </div> <div> <label>Lastname</label> <input type="text" id="lastname" /> </div> <div> <label>Your Message</label> <textarea id="message"></textarea> </div> <div> <p id="success"></p> </div> <div> <input type="submit" value="Submit" /> </div> </form> <script> $(function () { $("#contactForm").submit(function () { $.ajax({ type: "POST", url: '@Url.Action("SaveForm", "Main")', data: { name: $("#name").val(), lastname: $("#lastname").val(), message: $("#message").val() }, success: function (data) { $("#success").html(data) } }); } }); </script>

We are creating a new object from data obtained from communication form and save this data on database.


public class Contact
{
    public int ContactId { get; set; }
    public string Name { get; set; }
    public string Lastname { get; set; }
    public DateTime Date { get; set; }
    public string Message { get; set; }
}

[HttpPost]
public JsonResult SaveForm(string name, string lastname, string message)
{
    var contact = new Contact
    {
    Date= DateTime.Now,
    Name= name,
    Lastname= lastname,
    Message = message
    };

    string query = "INSERT INTO Contacts (Date,Name,Lastname,Message)"
            + " VALUES(@Date,@Name,@Lastname,@Message)";

    using (IDbConnection dbConnection = Connection)
    {
        dbConnection.Open();
        dbConnection.Execute(query, contact);
    }
    return Json("Your message was successfully saved");
}

You will see that your data are recorded within milliseconds. However, to be faster, we only saved the data on database and didn’t send them as e-mail. We will use Hangfire for this purpose. Hangfire periodically checks our database and will send the unsend data to us via e-mail.

First, we are making necessary installations at startup.


public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddHangfire(c => c.UseStorage(new MySqlStorage(@"Data Source=localhost;Initial Catalog=mytable;User Id=user;Password=xyz123;", new MySqlStorageOptions())));
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    var joboptions = new BackgroundJobServerOptions { WorkerCount = 1 };
    app.UseHangfireServer(joboptions);
    app.UseHangfireDashboard("/hangfire");
    app.UseMvc();
}

Later, we are writing a method that will find the recorded but unsend data in our database and sends an e-mail with SendMail() method. After sending the email, we are deleting the records with Dapper.


public async Task CheckContacts()
{
    using (IDbConnection dbConnection = Connection)
    {
        var query = "SELECT * FROM Contacts";
        var list = dbConnection.Query(query);
        foreach (var contact in list)
        {
            await MailSender(contact);
            string query = "DELETE FROM Contacts WHERE ContactId = @ContactId";
            dbConnection.Execute(query, contact);
            await Task.Delay(10000);
        }
    }
}

We are writing our method to run Hangfire. When we call this method once, Hangfire will trigger CheckContacts() method in pre-determined period.


[HttpGet("admin/start")]
public IActionResult Start()
{
    RecurringJob.AddOrUpdate("CheckContacts", () => CheckContacts(), Cron.Hourly);
    return Ok("Started");
}

Lastly, our MailSender methot which sends emails.

public async Task MailSender(Contact contact) { try { var emailMessage = new MimeMessage(); emailMessage.From.Add(new MailboxAddress("", "from@gmail.com")); emailMessage.To.Add(new MailboxAddress("", "to@gmail.com")); emailMessage.Subject = "New message"; var bodyBuilder = new BodyBuilder(); bodyBuilder.HtmlBody = string.Format(@" <body> <div> <p>Name: {0}</p> <p>Lastname: {1}</p> <p>Date: {2}</p> <p>Message: {3}</p> </div> </body>", contact.Name, contact.Lastname, contact.Date.ToString("MM.dd.yyyy"), contact.Message); emailMessage.Body = bodyBuilder.ToMessageBody(); using (var client = new SmtpClient()) { await client.ConnectAsync("smtp.gmail.com", 465); await client.AuthenticateAsync("from@gmail.com", "xyz123"); await client.SendAsync(emailMessage); await client.DisconnectAsync(true); } } catch(Exception) { throw; } }