European ASP.NET MVC 4 and MVC 5 Hosting

BLOG about ASP.NET MVC 3, ASP.NET MVC 4, and ASP.NET MVC 5 Hosting and Its Technology - Dedicated to European Windows Hosting Customer

ASP.NET MVC Hosting - HostForLIFE.eu :: Using SMTP to Send Emails in ASP.NET Core MVC

clock September 26, 2024 08:10 by author Peter

Assume you are creating a system for booking travel, and when a user books a car, two emails are sent.

  • Service email: Sent with information about the reservation to the firm.
  • Customer email: Submitted to the client as a reservation confirmation.

The use of the MailMessage and SmtpClient classes to do this is demonstrated in the C# code that follows.

This article explains how to combine the HTML form that is provided, the C# backend mail-sending code, and AJAX capability that uses jQuery to transfer form data to the server. I've included the necessary cshtml code that includes validation, Ajax integration, and captcha features.

Code Breakdown
CSHTML with AJAX Integration
<div class="booking_content">
    <h2>Reserve Your Ride Online</h2>
    <form action="" method="post" id="booking_form" novalidate="novalidate" class="row booking_form">
        <div class="col-md-6">
            <div class="form-group">
                <input type="text" class="form-control" name="name" placeholder="&#xe08a  Your Name">
                <label class="border_line"></label>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <input type="text" class="form-control" name="subject" placeholder="&#xe06b  Subject">
                <label class="border_line"></label>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <input type="text" class="form-control" name="email" placeholder="&#xe090  Your Email">
                <label class="border_line"></label>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <input type="text" class="form-control" name="mobile" placeholder="&#xe090  Phone">
                <label class="border_line"></label>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <input type="text" class="form-control" name="stratdestination" placeholder="&#xe01d  Start Destination">
                <label class="border_line"></label>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <input type="text" class="form-control" name="endDestination" placeholder="&#xe01d  End Destination">
                <label class="border_line"></label>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <input type="text" class="form-control date-input-css" name="timedate" placeholder="&#xe06b  Time and Date">
                <label class="border_line"></label>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <select class="form-control" name="cartype">
                    <option>--Select Car Type--</option>
                    <option value="A/C Tata Indigo">A/C Tata Indigo</option>
                    <!-- Add other car types -->
                </select>
                <label class="border_line"></label>
            </div>
        </div>
        <div class="col-sm-6 col-md-6">
            <div class="form-group row">
                <label class="col-sm-4 col-md-3 control-label">
                    <div id="divGenerateRandomValues"></div>
                </label>
            </div>
        </div>
        <div class="col-sm-6 col-md-6">
            <div class="form-group row">
                <input type="text" id="textInput" class="form-control" placeholder="Enter Captcha" />
                <span class="errCap text-danger"></span>
            </div>
        </div>
        <div class="col-lg-12">
            <div class="form-group">
                <button type="submit" value="submit" class="btn slider_btn dark_hover btnBookNow" id="btnSubmit">Book Now</button>
            </div>
        </div>
    </form>
</div>

<!-- Modal -->
<div class="modal fade sccmodl" id="sccmodl" tabindex="1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true" data-backdrop="static" data-keyboard="false">
    <div class="modal-dialog modal-dialog-centered" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5>Booking Information</h5>
                <button type="button" class="close No" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <h6 class="indxmsg"></h6>
            </div>
            <div class="modal-footer">
                <input type="button" class="btn btn-info btn-sm btnOk" value="Ok" />
            </div>
        </div>
    </div>
</div>


@section Scripts {
    <script type="text/javascript">
        var iNumber = Math.floor(1000 + Math.random() * 9000);

        $(document).ready(function () {
            $("#btnSubmit").prop("disabled", true);
            $("#divGenerateRandomValues").html("<input id='txtNewInput' value='" + iNumber + "' disabled/>");

            // Validate Captcha
            $("#btnSubmit").click(function (e) {
                e.preventDefault();
                if ($("#textInput").val() != iNumber) {
                    $('.errCap').text('Invalid Captcha !');
                } else {
                    $('.errCap').text('');
                    submitForm();
                }
            });

            var wrongInput = function () {
                return $("#textInput").val() != iNumber;
            };

            $("#textInput").bind('input', function () {
                $("#btnSubmit").prop('disabled', wrongInput);
            });
        });

        function submitForm() {
            $('#booking_form').validate({
                rules: {
                    name: { required: true, minlength: 2 },
                    subject: { required: true, minlength: 4 },
                    email: { required: true, email: true },
                    mobile: { required: true, minlength: 10, maxlength: 10, number: true },
                    stratdestination: { required: true, minlength: 2 },
                    endDestination: { required: true, minlength: 2 },
                    timedate: { required: true },
                    cartype: { required: true }
                },
                messages: {
                    name: { required: "Enter your name", minlength: "At least 2 characters" },
                    subject: { required: "Enter a subject", minlength: "At least 4 characters" },
                    email: { required: "Enter a valid email" },
                    mobile: { required: "Enter a valid phone number", minlength: "10 characters" },
                    stratdestination: { required: "Enter a start destination" },
                    endDestination: { required: "Enter an end destination" },
                    timedate: { required: "Select a date" },
                    cartype: { required: "Select a car type" }
                },
                submitHandler: function (form) {
                    $.ajax({
                        type: "POST",
                        url: "/Home/SendMail",
                        data: $(form).serialize(),
                        success: function (response) {
                            $('#sccmodl').modal('show');
                            $('.indxmsg').html(response);
                        },
                        error: function () {
                            alert("Error in sending the form.");
                        }
                    });
                }
            });
        }
    </script>
}


1. SendMail Action
Here’s the main controller action that handles the sending of the emails.
[HttpPost]
public ActionResult SendMail(string name, string email, string mobile, string subject, string timedate, string stratdestination, string endDestination, string cartype)
{
    try
    {
        // Create mail messages
        MailMessage mail = new MailMessage();
        MailMessage forCustomer = new MailMessage();
        SmtpClient smtpClient = new SmtpClient("mail.prakash.in", 587);

        // Configure SMTP client
        smtpClient.UseDefaultCredentials = false;
        smtpClient.Credentials = new NetworkCredential("[email protected]", "Bmbn0Dn26g6i~kybW");
        smtpClient.EnableSsl = false;

        // Configure mail for service
        mail.To.Add("[email protected]");
        mail.Bcc.Add("[email protected]");
        mail.From = new MailAddress("[email protected]", "Company Name");
        mail.Subject = subject;
        mail.Body = GenerateServiceMailBody(name, email, mobile, subject, timedate, stratdestination, endDestination, cartype);
        mail.IsBodyHtml = true;

        // Configure mail for customer
        forCustomer.To.Add(email);
        forCustomer.From = new MailAddress("[email protected]", "Company Name");
        forCustomer.Subject = subject;
        forCustomer.Body = GenerateCustomerMailBody(name);
        forCustomer.IsBodyHtml = true;

        // Send emails
        smtpClient.Send(mail);
        smtpClient.Send(forCustomer);

        return Json("Mail sent successfully! Please check your mail.");
    }
    catch (SmtpException smtpEx)
    {
        // Log detailed SMTP exception
        return Json($"SMTP Error: {smtpEx.Message}");
    }
    catch (Exception ex)
    {
        // Log general exception
        return Json($"Error: {ex.Message}");
    }
}


Explanation
SMTP Configuration: The SMTP client is configured using the SmtpClient class. In this case, it uses the mail.prakash.in the SMTP server on port 587, and the credentials for the email account are provided.
smtpClient.UseDefaultCredentials = false;
smtpClient.Credentials = new NetworkCredential("[email protected]", "Bmb~kybW");
smtpClient.EnableSsl = false;


Sending Emails to Multiple Recipients
Two separate emails are created.

  • The first email is sent to the company (service email) with the customer's booking details.
  • The second email is a confirmation sent to the customer.


Both emails are sent using smtpClient.Send(mail).

2. HTML Email Templates

HTML-formatted emails are used to send user-friendly content. Here, we generate two different types of email bodies: one for the service and one for the customer.

Service Email Template
private string GenerateServiceMailBody(string name, string email, string mobile, string subject, string timedate, string stratdestination, string endDestination, string cartype)
{
    return "<table cellspacing='0'>" +
        "<tr><td colspan='2'>Your contact person details:<br/></td></tr>" +
        "<tr><td colspan='2'><b><br/> Name: " + name + " <br/> Email: " + email + " <br/> Mobile: " + mobile + "  <br/> Subject: " + subject + "  <br/> Booking Date: " + timedate + " <br/> Start Destination: " + stratdestination + " <br/> End Destination: " + endDestination + " <br/> Booking Car: " + cartype + "  </b></td></tr>" +
        "<tr><td colspan='2'><br/>Please contact above person as soon as possible.<br />Thanks!</td></tr>" +
        "</table>";
}


Customer Email Template
private string GenerateCustomerMailBody(string name)
{
    return "<table cellspacing='0'>" +
        "<tr><td colspan='2'>Hello ,<br/></td></tr>" +
        "<tr><td colspan='2'><b><br/>  " + name + "    </b></td></tr>" +
        "<tr><td colspan='2'><br/>Thanks for your email. </td></tr>" +
        "<tr><td colspan='2'><br/>Please connect with us. </td></tr>" +
        "</table>";
}

The email sent to the customer confirms that their booking has been received and includes a personalized greeting.

3. Error Handling

Error handling is an essential aspect when dealing with external services like SMTP. Two exception blocks are used:

  • SmtpException: Catches issues related to SMTP (e.g., wrong credentials, SMTP server down).
  • Exception: A general catch block for any other issues that may arise.


catch (SmtpException smtpEx)
{
    return Json($"SMTP Error: {smtpEx.Message}");
}
catch (Exception ex)
{
    return Json($"Error: {ex.Message}");
}

Conclusion
This approach enables sending structured HTML emails from an ASP.NET MVC application using MailMessage and SmtpClient. You can easily customize the email templates, manage multiple recipients, and handle errors effectively.

When working with sensitive information like email credentials, it’s essential to avoid hardcoding them in the source code. Instead, store these values securely in a configuration file, like web.config, or use environment variables for improved security.

By following this structure, you can seamlessly add email functionality to your MVC applications and provide a smooth experience for both service providers and customers.



ASP.NET MVC Hosting - HostForLIFE.eu :: Full Upload and Download of Files in ASP.NET Core MVC

clock September 2, 2024 08:15 by author Peter

A strong framework that enables creating web apps quick and simple is ASP.NET Core MVC. Users must upload and download files to and from the server in numerous real-world situations. In this post, we'll create a basic ASP.NET Core MVC application with file upload and download capabilities.


1. Establishing the Project
Start by using Visual Studio or the.NET CLI to build a new ASP.NET Core MVC project.

Making Use of CLI

dotnet new mvc -n FileUploadDownloadApp
cd FileUploadDownloadApp


Using Visual Studio

  • Open Visual Studio and create a new project.
  • Select "ASP.NET Core Web App (Model-View-Controller)".
  • Name it FileUploadDownloadApp.

2. Creating the Model
The next step is to create a model that represents the file to be uploaded. We will store the uploaded file in an IFormFile object.
public class FileUploadViewModel
{
    public IFormFile File { get; set; }
}


The IFormFile interface represents the uploaded file in the HTTP request.

3. Creating the Controller
The controller handles user requests to upload and download files. Create a new FileController with actions for file upload, file listing, and file download.

using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Threading.Tasks;
using FileUploadDownloadApp.Models;
using Microsoft.AspNetCore.Hosting;

public class FileController : Controller
{
    private readonly IWebHostEnvironment _environment;
    public FileController(IWebHostEnvironment environment)
    {
        _environment = environment;
    }
    // GET: File/Upload
    public IActionResult Upload()
    {
        return View();
    }
    // POST: File/Upload
    [HttpPost]
    public async Task<IActionResult> Upload(FileUploadViewModel model)
    {
        if (model.File != null && model.File.Length > 0)
        {
            // Define the upload folder
            string uploadPath = Path.Combine(_environment.WebRootPath, "uploads");
            // Create the folder if it doesn't exist
            if (!Directory.Exists(uploadPath))
            {
                Directory.CreateDirectory(uploadPath);
            }
            // Generate the file path
            string filePath = Path.Combine(uploadPath, model.File.FileName);
            // Save the file to the specified location
            using (var stream = new FileStream(filePath, FileMode.Create))
            {
                await model.File.CopyToAsync(stream);
            }
            ViewBag.Message = "File uploaded successfully!";
        }
        return View();
    }
    // GET: File/ListFiles
    public IActionResult ListFiles()
    {
        string uploadPath = Path.Combine(_environment.WebRootPath, "uploads");
        if (!Directory.Exists(uploadPath))
        {
            return View(new List<string>());
        }
        var files = Directory.GetFiles(uploadPath).Select(Path.GetFileName).ToList();
        return View(files);
    }
    // GET: File/Download?filename=example.txt
    public IActionResult Download(string filename)
    {
        if (string.IsNullOrEmpty(filename))
        {
            return Content("Filename is not provided.");
        }
        string filePath = Path.Combine(_environment.WebRootPath, "uploads", filename);
        if (!System.IO.File.Exists(filePath))
        {
            return Content("File not found.");
        }
        byte[] fileBytes = System.IO.File.ReadAllBytes(filePath);
        return File(fileBytes, "application/octet-stream", filename);
    }
}

Breakdown

  • Upload: Saves uploaded files to the /uploads directory in wwwroot.
  • ListFiles: Displays a list of uploaded files.
  • Download: Allows downloading files from the server by providing the file name as a query parameter.


4. Creating Views
Upload View (Upload. cshtml)
@model FileUploadViewModel
<h2>Upload File</h2>
<form asp-action="Upload" enctype="multipart/form-data" method="post">
    <div class="form-group">
        <input type="file" asp-for="File" class="form-control" />
    </div>
    <button type="submit" class="btn btn-primary">Upload</button>
</form>
@if (ViewBag.Message != null)
{
    <p>@ViewBag.Message</p>
}


List Files View (ListFiles.cshtml)
@model List<string>
<h2>Uploaded Files</h2>
<table class="table">
    <thead>
        <tr>
            <th>File Name</th>
            <th>Download</th>
        </tr>
    </thead>
    <tbody>
    @foreach (var file in Model)
    {
        <tr>
            <td>@file</td>
            <td>
                <a asp-action="Download" asp-route-filename="@file" class="btn btn-success">Download</a>
            </td>
        </tr>
    }
    </tbody>
</table>

5. Navigation in Layout
To make file upload and download pages easily accessible, add links to these views in the main layout file (_Layout. cshtml).
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - FileUploadDownloadApp</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/FileUploadDownloadApp.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">FileUploadDownloadApp</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-controller="Home" asp-action="Upload">Upload File</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-controller="Home" asp-action="ListFiles">List Files</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2024 - FileUploadDownloadApp - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>


6. Running and Testing the Application
Once you've added the controller, views, and navigation links, run the application.

  • Upload Files: Navigate to /File/Upload to upload files.
  • List Files: After uploading, go to /File/ListFiles to see all uploaded files.
  • Download Files: Click the "Download" button to download the files.

7. Security and Best Practices
When implementing file upload and download functionality, security should be a top priority.File Size Limitations: Enforce limits on file size to prevent large files from overwhelming the server.services.Configure<FormOptions>(options => options.MultipartBodyLengthLimit = 10485760); // 10MBValidate File Types: Only allow certain file types by checking the file extension or MIME type.var allowedExtensions = new[] { ".jpg", ".png", ".pdf" };
var extension = Path.GetExtension(model.File.FileName);
if (!allowedExtensions.Contains(extension))
{
    ModelState.AddModelError("File", "Unsupported file type.");
}

Sanitize File Names: Remove any unwanted characters from file names before saving them.var safeFileName = Path.GetFileNameWithoutInvalidChars(model.File.FileName);Limit Upload Folder Access: Restrict access to the upload folder to prevent unauthorized access. Only allow authenticated users to download files if necessary.

8. Output


Conclusion
In order to manage file upload and download, we constructed a straightforward ASP.NET Core MVC application in this tutorial. To keep the application safe, we went over the fundamentals of building models, controllers, and views as well as security recommended practices. By incorporating features like progress bars, database storage for file information, or even Azure blob storage integration for managing larger files in cloud environments, you may further develop the application with this knowledge.



About HostForLIFE.eu

HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2016 Hosting, ASP.NET Core 2.2.1 Hosting, ASP.NET MVC 6 Hosting and SQL 2017 Hosting.


Tag cloud

Sign in