class Program
{
static int workingCounter = 0;
static int workingLimit = 10;
static int processedCounter = 0;
static void Main(string[] args)
{
string[] files = Directory.GetFiles("C:\\Temp");
int checkCount = files.Length;
foreach (string file in files)
{
//wait for free limit...
while (workingCounter >= workingLimit)
{
Thread.Sleep(100);
}
workingCounter += 1;
ParameterizedThreadStart pts = new ParameterizedThreadStart(ProcessFile);
Thread th = new Thread(pts);
th.Start(file);
}
//wait for all threads to complete...
while (processedCounter< checkCount)
{
Thread.Sleep(100);
}
Console.WriteLine("Work completed!");
}
static void ProcessFile(object file)
{
try
{
Console.WriteLine(DateTime.Now.ToString() + " recieved: " + file + " thread count is: " + workingCounter.ToString());
//make some sleep for demo...
Thread.Sleep(2000);
}
catch (Exception ex)
{
//handle your exception...
string exMsg = ex.Message;
}
finally
{
Interlocked.Decrement(ref workingCounter);
Interlocked.Increment(ref processedCounter);
}
}
}
User Registration And Login Form With E-Mail Notification In MVC
In this article, we will cover the User Registration and login form. Also, we will send an email notification for user verification and password recovery functionality with OTP.
- Registration form
- Password Encryption
- Email notification
- Generate User verification link
- Login form
- Forget Password
- Generate OTP
- Change Password
So let's do it with a database table script as below.
Step 1
- CREATE TABLE [dbo].[UserM](
- [UserId] [int] IDENTITY(1,1) NOT NULL,
- [FirstName] [varchar](50) NOT NULL,
- [LastName] [varchar](50) NOT NULL,
- [Email] [nvarchar](50) NOT NULL,
- [Password] [nvarchar](250) NOT NULL,
- [EmailVerification] [bit] NULL,
- [ActivetionCode] [uniqueidentifier] NULL,
- [OTP] [nvarchar](4) NULL,
- CONSTRAINT [PK_UserM] PRIMARY KEY CLUSTERED
- (
- [UserId] ASC
- )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
- ) ON [PRIMARY]
- GO
Step 2
Step 3
Step 4
Step 5
Now, click on the Finish button.
The generated model will look like below.
Note
If Entity framework is not found in your project, you can download it from the NuGet Package Manager.
After that, we will add a class for User Registration to the Models folder.
Select and name the class as below.
After this, we will set up a property for registration.
- namespace UserRegistration.Models
- {
- public class UserRegistration
- {
- public string FirstName { get; set; }
- public string LastName { get; set; }
- public string Email { get; set; }
- public string Password { get; set; }
- public string ConfirmPassword { get; set; }
- }
- }
Here, we wish to use the server side validation. So, we'll require System.ComponentModel.DataAnnotations.
Now, let us set up the Validation property as below.
- public class UserRegistration
- {
- [Required(AllowEmptyStrings = false, ErrorMessage = "First Name is requierd")]
- public string FirstName { get; set; }
- [Required(AllowEmptyStrings = false, ErrorMessage = "Last Name is requierd")]
- public string LastName { get; set; }
- [Required(AllowEmptyStrings = false, ErrorMessage = "Email ID is requierd")]
- public string Email { get; set; }
- [Required(AllowEmptyStrings = false, ErrorMessage = "Password is requierd")]
- [DataType(DataType.Password)]
- [MinLength(6, ErrorMessage = "Need min 6 character")]
- public string Password { get; set; }
- [Required(AllowEmptyStrings = false, ErrorMessage = "Confirm Password is requierd")]
- [DataType(DataType.Password)]
- [Compare("Password", ErrorMessage = "Confirm Password should match with Password")]
- public string ConfirmPassword { get; set; }
- }
Confirm the password parameters shown here. These should be just for password confirmation which we will not save in the database.
Encrypt Password
For security, the password is always saved in an encrypted format. So, we'll add a class which will change the password into encryption format. Add this class in the Models folder.
Select and name the class as below.
The class will look like this.
We will add a return static method to make this class static.
Code snippet
- namespace UserRegistration.Models
- {
- public static class encryptPassword
- {
- public static string textToEncrypt(string paasWord)
- {
- return Convert.ToBase64String(System.Security.Cryptography.SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(paasWord)));
- }
- }
- }
Now, we will add a controller for registration.
Select and add an empty controller as below.
Name the controlled and click on the "Add" button.
The added controller will look like below.
After this, use a model class for this controller and add a View.
When clicking on the Add View, you will see the following dialog box.
Select "Create" for the template field. After that, select the Model class as below.
Code snippet: User Registration
- @model UserRegistration.Models.UserRegistration
- @{
- ViewBag.Title = "Index";
- }
- <h2>User Registration</h2>
- @using (Html.BeginForm())
- {
- @Html.AntiForgeryToken()
- <div class="form-horizontal">
- <hr />
- @Html.ValidationSummary(true, "", new { @class = "text-danger" })
- <div class="form-group">
- @Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class = "control-label col-md-2" })
- <div class="col-md-10">
- @Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @class = "form-control" } })
- @Html.ValidationMessageFor(model => model.FirstName, "", new { @class = "text-danger" })
- </div>
- </div>
- <div class="form-group">
- @Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = "control-label col-md-2" })
- <div class="col-md-10">
- @Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class = "form-control" } })
- @Html.ValidationMessageFor(model => model.LastName, "", new { @class = "text-danger" })
- </div>
- </div>
- <div class="form-group">
- @Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" })
- <div class="col-md-10">
- @Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } })
- @Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
- </div>
- </div>
- <div class="form-group">
- @Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" })
- <div class="col-md-10">
- @Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control" } })
- @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" })
- </div>
- </div>
- <div class="form-group">
- @Html.LabelFor(model => model.ConfirmPassword, htmlAttributes: new { @class = "control-label col-md-2" })
- <div class="col-md-10">
- @Html.EditorFor(model => model.ConfirmPassword, new { htmlAttributes = new { @class = "form-control" } })
- @Html.ValidationMessageFor(model => model.ConfirmPassword, "", new { @class = "text-danger" })
- </div>
- </div>
- <div class="form-group">
- <div class="col-md-offset-2 col-md-10">
- <input type="submit" value="Create" class="btn btn-default" />
- </div>
- </div>
- </div>
- }
- <script src="~/Scripts/jquery-1.10.2.min.js"></script>
- <script src="~/Scripts/jquery.validate.min.js"></script>
- <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
Now, run the project.
Here, you will find a registration form with validation. Now, we will see how it will insert records in the database.
First, set up the database entity connection.
Then, add a POST method as below and add an object that will pass the data inside this method. Add a return static method which converts the password into an encrypted format.
- #region Registration post method for data save
- [HttpPost]
- public ActionResult Index(UserM objUsr)
- {
- // email not verified on registration time
- objUsr.EmailVerification = false;
- //it generate unique code
- objUsr.ActivetionCode = Guid.NewGuid();
- //password convert
- objUsr.Password = UserRegistration.Models.encryptPassword.textToEncrypt(objUsr.Password);
- objCon.UserMs.Add(objUsr);
- objCon.SaveChanges();
- return View();
- }
- #endregion
Live debugging screen
Here, you can see that the activation code is generating and password conversion is also found.
Below is the record that we have set.
Check If Email Exists Or Not
When we have created the registration form with e-mail ID, the email id must be unique. So, whenever we are registering, it is necessary to check whether e-mail id is there in our database or not.
For that, we will use the below code.
- #region Check Email Exists or not in DB
- public bool IsEmailExists(string eMail)
- {
- var IsCheck = objCon.UserMs.Where(email => email.Email == eMail).FirstOrDefault();
- return IsCheck != null;
- }
- #endregion
Then, this method is put in the Action method as follows so can check before saving the data,
If getting an e-mail, you will have to make a few changes in the VIEW to give information as follows,
- @Html.ValidationMessage("EmailExists", new { @class = "text-danger" })
Now the e-mail ID is already registered so try to re-register,
Live debugging screen,
Here, you get the message that you are trying to register an e-mail id that is already registered.
Email Notification
Now, we will see how to send an email after it is registered. When we mail, we will send a verification link with the email. Adjust the method.
Code: SendEmailToUser
- public void SendEmailToUser(string emailId, string activationCode)
- {
- var GenarateUserVerificationLink = "/Register/UserVerification/" + activationCode;
- var link = Request.Url.AbsoluteUri.Replace(Request.Url.PathAndQuery, GenarateUserVerificationLink);
- var fromMail = new MailAddress("rakeshchavda404@gmail.com", "Rakesh"); // set your email
- var fromEmailpassword = "*******"; // Set your password
- var toEmail = new MailAddress(emailId);
- var smtp = new SmtpClient();
- smtp.Host = "smtp.gmail.com";
- smtp.Port = 587;
- smtp.EnableSsl = true;
- smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
- smtp.UseDefaultCredentials = false;
- smtp.Credentials = new NetworkCredential(fromMail.Address, fromEmailpassword);
- var Message = new MailMessage(fromMail, toEmail);
- Message.Subject = "Registration Completed-Demo";
- Message.Body = "<br/> Your registration completed succesfully." +
- "<br/> please click on the below link for account verification" +
- "<br/><br/><a href=" + link + ">" + link + "</a>";
- Message.IsBodyHtml = true;
- smtp.Send(Message);
- }
After the data is saved, call this method.
Then, add a Registration View to display the message.
The message can be shown as below after adding the View.
Code snippet
- @{
- ViewBag.Title = "Registration";
- }
- <h2>Registration Complete</h2>
- <div class="alert-success">
- <strong>Message: </strong> @ViewBag.Message
- </div>
After the registration is successful, the message will appear like this.
The code for verification is mentioned below.
Code: UserVerification
- #region Verification from Email Account.
- public ActionResult UserVerification(string id)
- {
- bool Status = false;
- objCon.Configuration.ValidateOnSaveEnabled = false; // Ignor to password confirmation
- var IsVerify = objCon.UserMs.Where(u => u.ActivetionCode == new Guid(id)).FirstOrDefault();
- if (IsVerify != null)
- {
- IsVerify.EmailVerification = true;
- objCon.SaveChanges();
- ViewBag.Message = "Email Verification completed";
- Status = true;
- }
- else
- {
- ViewBag.Message = "Invalid Request...Email not verify";
- ViewBag.Status = false;
- }
- return View();
- }
- #endregion
Now, add the HTML view for controller.
- @{
- ViewBag.Title = "UserVerification";
- }
- <h2>User Verification Process</h2>
- <div class="danger alert-danger">
- <strong>Message..!!</strong> @ViewBag.Message, please click here to Login @Html.ActionLink("Login", "Login", "Register")
- </div>
It will be redirected to the browser when clicking on the verification link.
Live debug
In the table, see the verification flag has changed after verification,
User Login Form
Now, let's get a user login process.
Add a class for the login process and set the property of the login.
Set Class properties
- using System;
- using System.Collections.Generic;
- using System.ComponentModel.DataAnnotations;
- using System.Linq;
- using System.Web;
- namespace UserRegistration.Models
- {
- public class UserLogin
- {
- [Display(Name = "User Email ID")]
- [Required(AllowEmptyStrings = false, ErrorMessage = "User Email Id Required")]
- public string EmailId { get; set; }
- [Display(Name = "Password")]
- [DataType(DataType.Password)]
- [Required(AllowEmptyStrings = false, ErrorMessage = "Password Required")]
- public string Password { get; set; }
- [Display(Name = "Remember Me")]
- public bool Rememberme { get; set; }
- }
- }
Now, add an HTML View for users to login. Select "Create" for the template.
Then, select a Model class for user login and click on the Add button.
Login View code snippet
- @model UserRegistration.Models.UserLogin
- @{
- ViewBag.Title = "Login";
- }
- <h2>Login</h2>
- @using (Html.BeginForm())
- {
- @Html.AntiForgeryToken()
- <div class="form-horizontal">
- <hr />
- @Html.ValidationSummary(true, "", new { @class = "text-danger" })
- <div class="form-group">
- @Html.LabelFor(model => model.EmailId, htmlAttributes: new { @class = "control-label col-md-2" })
- <div class="col-md-10">
- @Html.EditorFor(model => model.EmailId, new { htmlAttributes = new { @class = "form-control" } })
- @Html.ValidationMessageFor(model => model.EmailId, "", new { @class = "text-danger" })
- </div>
- </div>
- <div class="form-group">
- @Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" })
- <div class="col-md-10">
- @Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control" } })
- @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" })
- </div>
- </div>
- <div class="form-group">
- @Html.LabelFor(model => model.Rememberme, htmlAttributes: new { @class = "control-label col-md-2" })
- <div class="col-md-10">
- <div class="checkbox">
- @Html.EditorFor(model => model.Rememberme)
- @Html.ValidationMessageFor(model => model.Rememberme, "", new { @class = "text-danger" })
- </div>
- </div>
- </div>
- <div class="form-group">
- <div class="col-md-offset-2 col-md-10">
- <input type="submit" value="Create" class="btn btn-default" />
- </div>
- </div>
- </div>
- }
- <div>
- @Html.ActionLink("Back to List", "Index")
- </div>
- <script src="~/Scripts/jquery-1.10.2.min.js"></script>
- <script src="~/Scripts/jquery.validate.min.js"></script>
- <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
Now, run the code and check it.
Here, you can see that the login form works nicely with validation.
Now, we will add a login POST method. Inside this method, we will check whether the user is appropriate or not; and generate a cookie for checkbox- Remember Me.
Login Code Snippet
- [HttpPost]
- public ActionResult Login(UserLogin LgnUsr)
- {
- var _passWord = UserRegistration.Models.encryptPassword.textToEncrypt(LgnUsr.Password);
- bool Isvalid = objCon.UserMs.Any(x => x.Email == LgnUsr.EmailId && x.EmailVerification == true &&
- x.Password == _passWord);
- if (Isvalid)
- {
- int timeout = LgnUsr.Rememberme ? 60 : 5; // Timeout in minutes, 60 = 1 hour.
- var ticket = new FormsAuthenticationTicket(LgnUsr.EmailId, false, timeout);
- string encrypted = FormsAuthentication.Encrypt(ticket);
- var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encrypted);
- cookie.Expires = System.DateTime.Now.AddMinutes(timeout);
- cookie.HttpOnly = true;
- Response.Cookies.Add(cookie);
- return RedirectToAction("Index", "UserDash");
- }
- else
- {
- ModelState.AddModelError("", "Invalid Information... Please try again!");
- }
- return View();
- }
The authorized user should be redirected to the homepage after successfully logged in.
So, we will add the user Home Controller as follows,
Here, we will use the Authorize attribute for security purposes.
Now, we will add an empty View.
Add a logout button to the View.
View Code snippet
- @{
- ViewBag.Title = "Index";
- }
Hello, @HttpContext.Current.User.Identity.Name
- <h2>Welcome....</h2>
- @if (Request.IsAuthenticated)
- {
- <a href='@Url.Action("LogOut", "Register")' onclick='navigate(this.href);'>
- <input style="float: right;" type="button" value='Logout' />
- </a>
- }
Check it now with the browser.
Live debug screen: for cookie generation.
You can see here that the user has been successfully logged in and the cookie generated is found in the browser.
Now, we need a logout code for application log out. For logout, add a logout method in the controller, as shown below.
Logout code
- [Authorize]
- public ActionResult LogOut()
- {
- FormsAuthentication.SignOut();
- return RedirectToAction("Login", "Register");
- }
For a login process, we use a form authentication mode, so need few changes as below in web.config. Here you can see set an authentication mode and set default login URL.
- <authentication mode="Forms">
- <forms cookieless="UseCookies" loginUrl="Register/Login"></forms>
- </authentication>
Forget Password
Now, let's see how to develop a method for "Forgot Password" functionality.
First, add a class.
Then, set the e-mail property for password recovery.
Code snippet
- using System.ComponentModel.DataAnnotations;
- namespace UserRegistration.Models
- {
- public class ForgetPassword
- {
- [Display(Name = "User Email ID")]
- [Required(AllowEmptyStrings = false, ErrorMessage = "User Email Id Required")]
- public string EmailId { get; set; }
- }
- }
Then, add a method for the "forget password" functionality.
Code snippet
- public ActionResult ForgetPassword()
- {
- return View();
- }
Then, create the HTML view using the above method.
VIEW Code Snippet
- @model UserRegistration.Models.ForgetPassword
- @{
- ViewBag.Title = "ForgetPassword";
- }
- <h2>ForgetPassword</h2>
- @using (Html.BeginForm())
- {
- @Html.AntiForgeryToken()
- <div class="form-horizontal">
- <hr />
- @Html.ValidationSummary(true, "", new { @class = "text-danger" })
- <div class="form-group">
- @Html.LabelFor(model => model.EmailId, htmlAttributes: new { @class = "control-label col-md-2" })
- <div class="col-md-10">
- @Html.EditorFor(model => model.EmailId, new { htmlAttributes = new { @class = "form-control" } })
- @Html.ValidationMessageFor(model => model.EmailId, "", new { @class = "text-danger" })
- @Html.ValidationMessage("EmailNotExists", new { @class = "text-danger" })
- </div>
- </div>
- <div class="form-group">
- <div class="col-md-offset-2 col-md-10">
- <input type="submit" value="Create" class="btn btn-default" />
- </div>
- </div>
- </div>
- }
- <div>
- @Html.ActionLink("Back to List", "Index")
- </div>
- <script src="~/Scripts/jquery-1.10.2.min.js"></script>
- <script src="~/Scripts/jquery.validate.min.js"></script>
- <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
Now, we will add a POST method to set the "forget password". Using this method, we will generate the OTP and then send an email to the user with password change URL. Inside this method, we will also check whether the user's mail id is correct or not.
Adjust first post method,
Code snippet
- [HttpPost]
- public ActionResult ForgetPassword(ForgetPassword pass)
- {
- var IsExists = IsEmailExists(pass.EmailId);
- if (!IsExists)
- {
- ModelState.AddModelError("EmailNotExists", "This email is not exists");
- return View();
- }
- var objUsr = objCon.UserMs.Where(x => x.Email == pass.EmailId).FirstOrDefault();
- // Genrate OTP
- string OTP = GeneratePassword();
- objUsr.ActivetionCode = Guid.NewGuid();
- objUsr.OTP = OTP;
- objCon.Entry(objUsr).State = System.Data.Entity.EntityState.Modified;
- objCon.SaveChanges();
- ForgetPasswordEmailToUser(objUsr.Email, objUsr.ActivetionCode.ToString(), objUsr.OTP);
- return View();
- }
The following methods are used to generate OTP.
Code snippet
- public string GeneratePassword()
- {
- string OTPLength = "4";
- string OTP = string.Empty;
- string Chars = string.Empty;
- Chars = "1,2,3,4,5,6,7,8,9,0";
- char[] seplitChar = { ',' };
- string[] arr = Chars.Split(seplitChar);
- string NewOTP = "";
- string temp = "";
- Random rand = new Random();
- for (int i = 0; i < Convert.ToInt32(OTPLength); i++)
- {
- temp = arr[rand.Next(0, arr.Length)];
- NewOTP += temp;
- OTP = NewOTP;
- }
- return OTP;
- }
The following methods are used to mail with OTP and change URL.
In the login.cshtml page, make a small change for page redirection.
- @Html.ActionLink("Registration", "Index") ||
- @Html.ActionLink("Reset Passward", "ForgetPassword")
Let’s execute the project and check.
Now, click "Reset Password".
Then click on the Reset button.
After that, check the email.
Thus, you can see the URL and OTP in the mail.
Change Password
Add a class and then set the "change password" property for password recovery.
Code snippet
- using System.ComponentModel.DataAnnotations;
- namespace UserRegistration.Models
- {
- public class ChangePassword
- {
- [Required(AllowEmptyStrings = false, ErrorMessage = "OTP is requierd")]
- public string OTP { get; set; }
- [Required(AllowEmptyStrings = false, ErrorMessage = "Password is requierd")]
- [DataType(DataType.Password)]
- [MinLength(6, ErrorMessage = "Need min 6 char")]
- public string Password { get; set; }
- [Required(AllowEmptyStrings = false, ErrorMessage = "Confirm Password is requierd")]
- [DataType(DataType.Password)]
- [Compare("Password", ErrorMessage = "Confirm Password should match with Password")]
- public string ConfirmPassword { get; set; }
- }
- }
Now, add a method inside the controller for "change password" and for using this method, add an HTML view.
- @model UserRegistration.Models.ChangePassword
- @{
- ViewBag.Title = "ChangePassword";
- }
- <h2>ChangePassword</h2>
- @using (Html.BeginForm())
- {
- @Html.AntiForgeryToken()
- <div class="form-horizontal">
- <h4>ChangePassword</h4>
- <hr />
- @Html.ValidationSummary(true, "", new { @class = "text-danger" })
- <div class="form-group">
- @Html.LabelFor(model => model.OTP, htmlAttributes: new { @class = "control-label col-md-2" })
- <div class="col-md-10">
- @Html.EditorFor(model => model.OTP, new { htmlAttributes = new { @class = "form-control" } })
- @Html.ValidationMessageFor(model => model.OTP, "", new { @class = "text-danger" })
- </div>
- </div>
- <div class="form-group">
- @Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" })
- <div class="col-md-10">
- @Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control" } })
- @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" })
- </div>
- </div>
- <div class="form-group">
- @Html.LabelFor(model => model.ConfirmPassword, htmlAttributes: new { @class = "control-label col-md-2" })
- <div class="col-md-10">
- @Html.EditorFor(model => model.ConfirmPassword, new { htmlAttributes = new { @class = "form-control" } })
- @Html.ValidationMessageFor(model => model.ConfirmPassword, "", new { @class = "text-danger" })
- </div>
- </div>
- <div class="form-group">
- <div class="col-md-offset-2 col-md-10">
- <input type="submit" value="Change Password" class="btn btn-default" />
- </div>
- </div>
- </div>
- }
- <div>
- @Html.ActionLink("Login", "Login")
- </div>
- <script src="~/Scripts/jquery-1.10.2.min.js"></script>
- <script src="~/Scripts/jquery.validate.min.js"></script>
- <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
Now, click on the change password URL to open the mail.
So, the following screen will open.
Now, change your password here by setting up the OTP found in the mail.