Tuesday, 16 October 2012

ASP.NET MVC 3: CREATING A SIMPLE SIGN-UP FORM


In this article I'm going to demonstrate how to create a simple sign-up form using ASP.NET MVC 3. So basically in this demo you will learn the following:

How to insert data to the database with Entity Framework
How to validate the Form using Data Annotations
How to Authenticate users after sign up using FormsAuthentication

Note that before you continue reading this article be sure that you have the basic understanding about ASP.NET MVC in general. You can refer the following links below to learn more about ASP.NET MVC:

http://msdn.microsoft.com/en-us/library/dd381412%28VS.98%29.aspx
http://www.asp.net/mvc/whatisaspmvc



STEP 1. Adding a new ASP.NET MVC project

Let's go ahead and fire up Visual Studio 2010 and then select File -> New Project -> ASP.NET MVC 3 Web Application. See the screen shot below for more clearer view:



Now click OK and on the next form select Empty Template -> select Razor as the View engine and then click OK to generate the default files.


STEP 2: Setting up the Model

In this demo, I'm going to use Entity framework as our Data Access mechanism sothat we can program against the conceptual application model instead of progamming directly against  our database.

Add the following folders under the Models folder:

    DB
    ObjectManager
    ViewModel

The application structure would like something like below:




We will create our Entity Model (EDMX) in the DB folder. To do this right click on the "DB" folder and select Add -> New Item -> Data -> ADO.NET Entity Data Model. 



Noticed that I named the entity as "SampleModel" just for the purpose of this demo. You may want to name it to a more appropriate name based on your requirements but for this example let's just use "SampleModel". Now click Add to continue and on the next step select "Generate from database" and click Next. On the next step you can connect or browse to the database that you want to use in the application and test the connection string by clicking on the "Test Connection" button and if it succeeds then you can continue by clicking OK and then Next.

Note that in this example I created a simple database called "DeveloperReport.mdf" and added it into the application's App_Data folder and use it as our database. See the screen shot below:




On the next step we can add the table(s), views or stored procedures that we want to use in the application by selecting the checkbox. See below screenshot: 



Noticed that I've only selected the "SysUser" table. This is because we are going to use this table for doing insert and we don't need anything else. Now click on Finish button to generate the entity model for you. See the screenshot below: 



What happend there is that EF will automatically generates the Business object for you within the Entity Data Model(EDM) that we have just created and let you query against it.The EDM is the main gateway by which you retrieve objects from the database and resubmit changes.


STEP 3: Adding the ViewModel Class

Just to recap Entity Framework will generate the business objects and manage Data Access within the application. As a result, the class SysUser is automatically created by EF and it features all the fields in the database table as properties of the class.

I don't want to use this class direclty in the View so I decided to create a separate class that just holds the properties I need in the View. Now let's add a the UserView class by right-clicking on the "ViewModels" folder then select Add -> Class. Here's the code block for the "UserView.cs" class.
using System.ComponentModel.DataAnnotations;

namespace MVCDemo.Models.ViewModels {
    public class UserView {
        [Required]
        [Display(Name = "First Name")]
        public string FirstName { get; set; }

        [Required]
        [Display(Name = "Last Name")]
        public string LastName { get; set; }

        [Required]
        [Display(Name = "Contact Number")]
        public string ContactNumber { get; set; }

        [Required]
        [Display(Name = "Login ID")]
        public string LoginID { get; set; }

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


Noticed that I added the Required and DisplayName attributes for each property in the UserView class. This attributes is called Data Annotations. Data annotations are attribute classes that live in the System.ComponentModel.DataAnnotations namespace that you can use to to decorate classes or properties to enforce pre-defined validation rules.

I'll use this validation technique because I want to keep a clear separation of concerns by using the MVC pattern and couple that with data annotations in the model, then your validation code becomes much simpler to write, maintain, and test.

For more information about Data Annotations then you can refer this link: http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx. And of course you can find more examples about it by doing a simple search at google /bing 


STEP 4: Adding the UserManager Class

The next step that we are going to do is to create the User manager class that would handle the (CRUD operations) create,update,fetch and delete operations of a certain table. The purpose of this class is to separate the actual data opertions from our controller and to have a central class for handling insert,update,fetch and delete operations. But please note that in this example I'm only be doing the insert part in which a user can add new data from the View to the database. I'll talk about how to do update,fetch and delete with MVC in my next article. So this time we'll just focus on the insertion part first.

Now right click on the "Model" folder and add a new class by selecting Add -> Class and since we are going to manipulate the SysUser table then we will name the class as "UserManager". Here's the code block for the "UserManager.cs" class:

using System.Linq;
using MVCDemo.Models.DB;
using MVCDemo.Models.ViewModels;

namespace MVCDemo.Models.ObjectManager {
    public class UserManager {

        private DeveloperReportEntities dre = new DeveloperReportEntities();

        public void Add(UserView user) {
            DB.SysUser sysUser = new DB.SysUser();
            sysUser.SysUserLoginID = user.LoginID;
            sysUser.SysPassword = user.Password;
            sysUser.FirstName = user.FirstName;
            sysUser.LastName = user.LastName;
            sysUser.ContactNumber = user.LastName;

            dre.AddToSysUsers(sysUser);
            dre.SaveChanges();
        }

        public bool IsUserLoginIDExist(string userLogIn) {
            return (from o in dre.SysUsers where o.SysUserLoginID == userLogIn select o).Any();
        }
    }
}


STEP 4: Adding the Controllers

Since our model is already set then let's go ahead and add the "AccountController". To do this just right click on the "Controllers" folder and select Add -> Controller. Since our aim is to create a simple sign-up form then name the controller as "AccountController" and then click Add to generate the "AccountController" class for you.

Now here's the code block for the "AccountController":

using System.Web.Mvc;
using System.Web.Security;
using MVCDemo.Models.ViewModels;
using MVCDemo.Models.ObjectManager;

namespace MVCDemo.Controllers
{
    public class AccountController : Controller
    {
        // GET: /Account/SignUp
        public ActionResult SignUp() {
            return View("SignUp");
        }

        // POST: /Account/SignUp
        [HttpPost]
        public ActionResult SignUp(UserView user) {
            try {
                if (ModelState.IsValid) {
                    UserManager userManager = new UserManager();
                    if (!userManager.IsUserLoginIDExist(user.LoginID)) {
                        userManager.Add(user);
                        FormsAuthentication.SetAuthCookie(user.FirstName, false);
                        return RedirectToAction("Welcome", "Home");
                    }
                    else {
                        ModelState.AddModelError("", "LogID already taken");
                    }
                }
            }
            catch {
                return View(user);
            }

            return View(user);
        }
    }
}

The AccountController has two main methods. The first one is the "SignUp" which returns the "SignUp.cshtml" View. The second one also named as "SignUp" but it is decorated with the "[HttpPost]" attribute. This attribute specifies that the overload of the "SignUp" method can be invoked only for POST requests.

The second method is responsible for inserting new entry to the database and automatically authenticate the users using FormsAuthentication.SetAuthCookie() method. this method creates an authentication ticket for the supplied user name and adds it to the cookies collection of the response, or to the URL if you are using cookieless authentication. After authenticating, we then redirect the users to the Welcome.cshtml page.

Now add another Controller and name it as "HomeController". This controller would be our controller for our default page. We will create the "Index" and the "Welcome" View for this controller in the next step. Here's the code for the "HomeController" class:
using System.Web.Mvc;

namespace MVCDemo.Controllers
{
    public class HomeController : Controller
    {
        // GET: /Home/
        public ActionResult Index()
        {
            return View();
        }

        [Authorize]
        public ActionResult Welcome() {
            return View();
        }

    }
}

Noticed that we have two ActionResult method in the "HomeController". The "Index" method serve as our default redirect page and the "Welcome" method will be the page where we redirect the users after they have successfully registered. We also decorated it with the "[Authorize]" attribute so that this method will only be available for the logged-in users. 

STEP 5: Adding the Views

First let's add the following folders below under the "Views" folder:

    Home
    Account

Note: The reason for this is that the folder name should match the name of the Controllers you've created. So if you have HomeController then you should have a "Home" folder within your View.

Now under the "Home" folder add a new View. To do this just right click on the "Home" folder and select Add -> View. Name the view as "Index" and click Add to generate the Web Page (.cshtml). Here's the mark-up of the Index.cshtml:
@{
    ViewBag.Title = "Welcome";
}

<h2>Welcome</h2>

@Html.ActionLink("Click here to sign-up", "SignUp", "Account")

As you can see there's no fancy about the mark-up above except that it contains the ActionLink which redirect you to the "SignUp" view within the "Account" folder. Now add again another View under the "Home" folder and name the view as "Welcome". The reason why we add the Welcome.cshtml view is because we will redirect the user in this page after they successfully signed up and nothing more. Here's the mark-up of the Welcome.cshtml:
@{
    ViewBag.Title = "Welcome";
}

<h2>Hi <b>@Context.User.Identity.Name</b>! Welcome to my website!</h2>
Now under the "Account" folder add a new view and name it as "SignUp" and check the checkbox that says "create a strongly-typed views and in the Model class dropdownlist select "UserView" and then in the Scaffold template select "Create" and finally click Add to generate the Web Page for you. Take a look at the screen shot below for more clearer view of what I am talking about:





And here's the generated mark up of the SignUp.cshtml:
@model MVCDemo.Models.ViewModels.UserView

@{
    ViewBag.Title = "SignUp";
}

<h2>Sign-Up</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>UserView</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.FirstName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.FirstName)
            @Html.ValidationMessageFor(model => model.FirstName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.LastName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.LastName)
            @Html.ValidationMessageFor(model => model.LastName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.ContactNumber)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.ContactNumber)
            @Html.ValidationMessageFor(model => model.ContactNumber)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.LoginID)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.LoginID)
            @Html.ValidationMessageFor(model => model.LoginID)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Password)
        </div>
        <div class="editor-field">
            @Html.PasswordFor(model => model.Password)
            @Html.ValidationMessageFor(model => model.Password)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Return to Home page","Index", "Home")
</div>

The mark-up above is a strongly-type view. This strongly typed approach enables better compile-time checking of your code and richer IntelliSense in the Visual Studio editor. By including a @model statement at the top of the view template file, you can specify the type of object that the view expects. In this case it uses the MVCDemo.Models.ViewModels.UserView.

The View structure would like something like below:
 

STEP : Running the Application

Running the page will give you the following outputs:

On initial load:



After clicking on the Sign-Up link:



Sample screen shot that shows the validation



Completing the form



After successfully registered


No comments:

Post a Comment

What should you required to learn machine learning

  To learn machine learning, you will need to acquire a combination of technical skills and domain knowledge. Here are some of the things yo...