WHAT'S NEW?
Loading...

Create your own custom login with MVC 4

Here we go again with a new tutorial to show you how to create a customized login using MVC 4 with Microsoft Visual Studio 2010. In this post, I will try to explain you how to develop different views, controllers, models, one database and of course, how all these elements interacts between them.

I have used MVC in older posts but I did not expend too much time explaing you how it works. MVC bornt as a software design pattern for implementing user interfaces. It provides a very useful architecture which splits between: the user interface (View), the logic and bridge between the user and the data (Controller) and finally the data (Model). Although originally developed for desktop computing, Model View Controller has been widely adopted as an architecture for World Wide Web. MVC 5 is the last template version released by Microsoft, but there are not too much differents with version 4. For the views, we are going to use Razor (CSHTML), the Microsoft dynamic view engine released in 2010. It is a new way to create your interfaces easier to use than ASPX, here you can check the differences beteween them.

Here below I show you all the steps to have your own login app:

  • Create the solution in Visual Studio: first of all, we need to create our project in VS2010. If you can't find the ASP.NET MVC4 Web Application template as showed in the image below, probably you need to download from Microsoft site. Remeber you need Service Pack 1 of VS2010. Write a name for your project and press OK.

In the following window, select a Basic template, which contains an specific structure of MVC 4. The view engine should be Razor and optionally create a unit test project.



  • Add a new database: we also need a DB to check the credentials of the user in the authenticasion phase. Right click on App_Data folder and select New item.


  • Creating Home controller: this controller is in charge of show the first window called: Index. In the controller creation window write HomeController in name and select "Empty MVC controller" in scaffolding options. Scaffolding allows you to create the controllers and views automatically based on a model class of our solution. The full CRUD action methods will be generated in the Controller and the necessary views will be generated too. Even if the database is not created, will be build on the fly by Code First. 

  • Creating Home view: create the view from the HomeController method just right click on it: Add view.

Call it Index, use Razos as View engine and select the master page _Layout.cshtml. Later, we will modify this master page to contains serveral action links: register, log in and log out, depends on the status of the user.


  • Creating the model: this user model is required to handle user information. Right click on Models, Add, New Item..., Code, Class and name it User.cs:

using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Data.SqlClient;

namespace My_MVC4_Test_application.Models
{
    public class User
    {
        [Required]
        [Display(Name = "User name")]
        public string UserName { get; set; }

        [Required]
        [DataType(DataType.Password)]
        [Display(Name="Password")]
        public string Password { get; set; }

        [Display(Name = "Remember on this computer")]
        public bool RememberMe { get; set; }

        /// 
        /// Checks if user with given password exists in the database
        /// 
        /// User name
        /// User password
        /// 
        public bool IsValid(string _username, string _password)
        {
            string connectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename='C:\YOUR PATH\db.mdf';Integrated Security=True;User Instance=True";
            using (var cn = new SqlConnection(connectionString))
            {
                string _sql = @"SELECT [Username] FROM [dbo].[System_Users] " +
                    @"WHERE [Username] = @u AND [Password] = @p";
                var cmd = new SqlCommand(_sql, cn);
                cmd.Parameters
                    .Add(new SqlParameter("@u", SqlDbType.NVarChar))
                    .Value = _username;
                cmd.Parameters
                    .Add(new SqlParameter("@p", SqlDbType.NVarChar))
                    .Value = Helpers.SHA1.Encode(_password);
                cn.Open();
                var reader = cmd.ExecuteReader();
                if (reader.HasRows)
                {
                    reader.Dispose();
                    cmd.Dispose();
                    return true;
                }
                else
                {
                    reader.Dispose();
                    cmd.Dispose();
                    return false;
                }
            }
        }
    }
}

Some Data Annotations are in our class:

  • Required - Specifies that a data field value is required.
  • Display(Name) - Gets or sets a value that is used for display in the UI.
  • DataType(DataType.Password) - Specifies an alternative type for a data field.

Remember to check the connectionString and write the path of your computer. Here in the code is set as: C:\YOUR PATH\db.mdf. You will need to check the web.config file to validate the connection string.
  • Creating a Helper: You probably noticed that there is one line in red because of an error. There is no method or class created for it. This Helper is in charge of encrypt the password of our users using SHA1. Right click on our solution, New project, Windows, class library and name it Helpers. Create a new class inside and call it SHA1.cs and paste the code below:

using System;

namespace Helpers
{
    public class SHA1
    {
        public static string Encode(string value)
        {
            var hash = System.Security.Cryptography.SHA1.Create();
            var encoder = new System.Text.ASCIIEncoding();
            var combined = encoder.GetBytes(value ?? "");
            return BitConverter.ToString(hash.ComputeHash(combined)).ToLower().Replace("-", "");
        }
    }
}

Finally you just need to make a reference from our main project to this new one. Right click on our web site project, Add reference, Project and select Helpers.
  • Creating User controller: the UserController.cs tries to manage who wants to log in or log out. Create a new controller as we did before and paste the following code:

using System.Web.Mvc;
using System.Web.Security;

namespace My_MVC4_Test_application.Controllers
{
    public class UserController : Controller
    {
        //
        // GET: /User/

        public ActionResult Index()
        {
            return View();
        }

        [HttpGet]
        public ActionResult Login()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Login(Models.User user)
        {
            if (ModelState.IsValid)
            {
                if (user.IsValid(user.UserName, user.Password))
                {
                    FormsAuthentication.SetAuthCookie(user.UserName, user.RememberMe);
                    return RedirectToAction("Index", "Home");
                }
                else ModelState.AddModelError("", "Login data is incorrect!");
            }
            return View(user);
        }

        public ActionResult Logout()
        {
            FormsAuthentication.SignOut();
            return RedirectToAction("Index", "Home");
        }
    }
}

The Login method is overloaded depending if it recives our User model or not. Both methods have different Http request to know if we get info from the server or we post info to the server.

ModelState.IsValid check if any of the model errors have been added to the ModelState.

The FormsAuthentication method creates a cookie for the user when the authentication is correct.

RedirectToAction method needs the method and the controller which contains that method.
  • Creating Login view: now is the part for the login view. Right click over Login method name and click on Add view. Remember to add layout template as before. Paste this code in the view:
@model My_MVC4_Test_application.Models.User
@{
    ViewBag.Title = "Login";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
@using (Html.BeginForm())
{
    @Html.ValidationSummary(true, "Login failed. Check your login details.");
    
Login
@Html.LabelFor(u => u.UserName)
@Html.TextBoxFor(u => u.UserName) @Html.ValidationMessageFor(u => u.UserName)
@Html.LabelFor(u => u.Password)
@Html.PasswordFor(u => u.Password) @Html.ValidationMessageFor(u => u.Password)
@Html.CheckBoxFor(u => u.RememberMe) @Html.LabelFor(u => u.RememberMe)
}

This view is a CSHTML (c sharp html) file because we selected Razor as our engine and, as you probably know, is a mix between HTML and C#.

@model directive provides a cleaner and more concise way to reference strongly-typed models from view files.

ViewBag.Title sets a name in the title bar of this view. Maybe you think, why this is not in the controller? Is because we need it in the master page layout:
@ViewBag.Title
Next is the @using (Html.BeginForm()) clause, used to create the typical form in HTML: <form action="/Customer/Form" method="post">, between brakets are the different fields to login in the system.

@Html.ValidationSummary(true) provides a summary of all the errors produced in the page.
The <fieldset> tag draws a box around the related elements.
Legend defines a caption for the fieldset element.

  • Customize your layout: this master page will share his content with all the views which inherits from it. The idea is to show different action links depending if the user is logged or not. Here the code:
    
        
            
            
            @ViewBag.Title
            @Styles.Render("~/Content/css")
            @Scripts.Render("~/bundles/modernizr")
        
        
            
    @if (Request.IsAuthenticated) { @Html.Encode(User.Identity.Name) @Html.ActionLink("Sign Out", "Logout", "User") } else { @Html.ActionLink("Register", "Register", "User") | @Html.ActionLink("Sign In", "Login", "User") }
    @RenderBody() @Scripts.Render("~/bundles/jquery") @RenderSection("scripts", required: false)

Finally, I want to show you an overview of our applications, this is how it looks:

References:   1. - Design patterns.   2. - http://www.codeproject.com/Articles/482546/Creating-a-custom-user-login-form-with-NET-Csharp   3. - Razor

0 comments:

Post a Comment