Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

How to design login screen in MVC3?

0.00/5 (No votes)
15 Dec 2013 1  
Kick start to mvc project by creating login screen.
Introduction

This is the quick start to the MVC project. Login form is the first part of every project. There are several ways to create login functionality. I will demonstrate one of them and build basic MVC3 project structure so you can enhanced based on your project requirement.

Answer

Let's look at the project structure. I have create MVC3 empty project. I have database name Student in App_Data folder. I have created ADO.NET entity data model name Student_db.edmx as my Model in Model folder of MVC.

Add controller Home and create action name index. Create index View. Index is the startup page of our website. Open Global.asax contain RegisterRoutes method as fellow.

         public static void RegisterRoutes(RouteCollection routes)<br />        {<br />            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");<br />            routes.MapRoute(<br />                "Default", // Route name<br />                "{controller}/{action}", // URL with parameters<br />                new { controller = "Home", action = "Index"} // Parameter defaults<br />                ,new[] {"LoginScreenDemo.Controllers"}<br />            );<br />        } 

RegisterRoutes is static method which get called in Application_Start event. RegisterRoutes accept RouteCollection object as parameter and call MapRoute method of RouteCollection class. MapRoute method has overload that accept route name, url with parameters and default parameter to url. Controller Home and action Index is specified as the default parameter to url this set our startup page.

I have designed indexpage as fellow.

LogIn is anchor tag which navigate to the Login page.

I have designed login page as fellow.

Here is trick, on click of the LogIn link instead of navigating to the login page we will display login page as popup as fellow.

Let's look at the IndexView closely.

I have use ajax helper method to create LogIn action link. On click on LogIn link it call to the controller action asynchronously and render the return view into the updateTargetControllId.

I have set updateTargetControllId to the id of div tag hence the return partial view get render inside the div. I have use JQuery plugin name bpopup to display div as popup.

Ajax Helper method to use Ajax helper method you need to add following Jquery into you page. I have chosen min version due to its lightweight nature.

<script src="@Url.Content("../../Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script><br /><script src="@Url.Content("../../Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>    

You can use ajax helper method by using @Ajax. syntax. I have perform Ajax call using LogIn action link.

<li class="nav"><br /> @Ajax.ActionLink("Login", "Login", new { area="" }, new AjaxOptions() { UpdateTargetId = "loginView" }, new { id = "lnkLogin", @class="nav" })<br /></li>    <br />  <h2>Home Page</h2><br />  <h2>Some site description!!!!</h2><br /><br /><br /><div id="loginView" class="white_content"><br /></div>   

I have added css class nav to provide menu item look to the action link. Action link LogIn call to the Home controller Login action and render the return partial view into the div with id loginView.

  <div id="loginView" class="white_content"><br /></div> 

Login View Login View consist of form contain the label and textbox for username and password with button to submit the form . I have created Login as the partial view as it is get render into the Index View. Login is a partial strongly type View of type ViewModel class. For each strongly type View I have created ViewModel class. A ViewModel represents data that you want to displayed on your view/page.

@model LoginScreenDemo.ViewModel.LoginVM

<div id="pnl_Login">
  
        @using (Ajax.BeginForm("Login", "Home", new { area = "" }
            , new AjaxOptions { UpdateTargetId = "error_message", OnSuccess = "RedirectToUrl", OnFailure = "OnFailuar", OnBegin = "validateForm" }, new { method = FormMethod.Post }))
        {
              <table border="0">
            <tr>
                <td>
                    @Html.LabelFor(Model => Model.LoginName)
                </td>
                <td>
                    @Html.TextBoxFor(Model => Model.LoginName)
                </td>
                <td>
                    @Html.ValidationMessageFor(Model => Model.LoginName, "*")
                </td>
            </tr>
            <tr>
                <td>
                    @Html.LabelFor(Model => Model.Password)
                </td>
                <td>
                    @Html.PasswordFor(Model => Model.Password)
                </td>
                <td>
                    @Html.ValidationMessageFor(Model => Model.Password, "*")<br />
                </td>
            </tr>
            <tr>
                <td>
                    &nbsp;
                </td>
                <td>
                    <input type="submit" value="Login" />&nbsp;
                    <input type="button" value="Cancle" class="loginClose" />
                </td>
                <td>
                    &nbsp;
                </td>
            </tr>
                </table>
    <div id="error_message">
        @Html.ValidationSummary(true)
    </div>
        }

</div>

Javascript to handle AjaxForm OnSuccess and OnFailuar methods. 

<script>
    function RedirectToUrl(Result) {
        if (Result == 1)
            window.open("/Home/SiteMap", "_self");
        else
            $("#loginView").html(Result);
    }
    function OnFailuar(exMessage) {
        $("#error_message").html(exMessage);
    }
    function validateForm() {
       
    } 
</script>  

Object of ViewModel get filled into the controller action method and pass to the View. Controller action method perform call to its Manager class (Business class) to fill the ViewModel object.

Each strongly type View is of type ViewModel class and have a Action Method. Action Method transfer ViewModel object to the View. Action method call method of it's Manager class method to fill ViewModel object. Manager Class interact with the database i.e. with the entity model and provide mapping between one or more entity object to the ViewModel Object. 

LoginManager class [Manager Class] contain the logic to interact with database and return the result.

 public class LoginManager:BaseManager
    {
        public string RollName {get;set;}

        public bool ValidateLogin(LoginVM loginContext)
        {
            var result= (from login in studentContext.tblLogins
             where login.LoginName == loginContext.LoginName && login.Password == loginContext.Password
             select new { login.Role, login.LoginName}).FirstOrDefault();
            if (result.LoginName == null)
            { 
                return false;
            }
            RollName = result.Role;
            return true;
        }

        public string  GetRole(string userName)
        {
            return (from login in studentContext.tblLogins
                    where login.LoginName ==userName
                        select  login.Role).FirstOrDefault();
        }
    }  

In general Manager class contain the function to fetch data, insert data and update data. 

Fetch data function will fetch the data from database and fill the ViewModel object and return to the action method. Where insert and update perform the insert and update on the database in our case using entity framework.

LoginVM class [ViewModel class] each View is directly map with the ViewModel or with IEnumerable<ViewModel> to provide collection of ViewModel in View. Each strongly type View is of type ViewModel or IEnumerable<ViewModel>. ViewModel contain property that are related to one or more entities form the entity set. Like LoginName might be present in entity class tblNameMaster where Password might be present in entity class tblRecordMaster. Where tblNameMaster and tblRecordMaster are directly map with database table object schema. 

Note :- In code first approach you can create entity and form the entity you will generate database schema.

     public class LoginVM:BaseVM
    {
        [Required(ErrorMessage="Please enter valid user name.")]
        public string LoginName { get; set; }

        [Required(ErrorMessage="Please enter valid password.")]
        public string Password { get; set; }

    } 

LoginVM class use using System.ComponentModel.DataAnnotations namespace to provide validation for the property LoginName and Password for time being I have use the data annotation Required() attribute to indicate that LoginName and Password can not be kept null. If you look at the Login view you will notice the following code. 

@Html.ValidationMessageFor(Model =>Model.LoginName, "*")
@Html.ValidationMessageFor(Model=> Model.Password, "*")
@Html.ValidationSummary(true)   

@Html.VlaidationMessageFor helper classes help us to provide the inline validation message for.

@ValidationSummary method displays a list of all validation messages on the page.

When the View is rendered, the validation messages and validation summary are displayed based on the Errors property of the ModelState object.

Following are the JavaScript that help us to provide client side validation message.

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

Jquery.validate.min.js contain the validation logic where the jquery.validate.unobtrusive.js remove inline jquery code and provide some nice attribute to call it. If you notice the web.config of the project you will notice following keys that help to enable client side validation.

 <appSettings>
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  </appSettings>  

Please read following codeproject articulate to get more knowledge about the validation in MVC.

http://www.codeproject.com/Articles/249452/ASP-NET-MVC3-Validation-Basic

User put credential into the login popup. Valid user will be redirect to the Sitemap page. If user is invalid appropriate message get display. Once user login let’s identify role of the user. Based on the role provided to user, user will grant permission to access page. If user do not have permission to access page he will get redirect to the login page. I have use custom role base form authentication.

I have added following code to web.config to enable form authentication. 

    <authentication mode="Forms">
      <forms loginUrl="/Home/Index" timeout="2880" />
    </authentication> 

Login URL indicate URL where user will redirect if he is not authenticated.

I have also overridden the method FormsAuthentication_OnAuthenticate in the Global.asax file.

   protected void FormsAuthentication_OnAuthenticate(Object sender, FormsAuthenticationEventArgs e)
        {
            if (FormsAuthentication.CookiesSupported == true)
            {
                if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
                {
                    try
                    {
                        //let us take out the username now                
                        string username = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;
                        string roles = string.Empty;
                        LoginScreenDemo.Business.LoginManager loginManager = new Business.LoginManager();
                        roles = loginManager.GetRole(username);
                        //Let us set the Pricipal with our user specific details
                        e.User = new System.Security.Principal.GenericPrincipal(
                                  new System.Security.Principal
                        .GenericIdentity(username, "Forms"), roles.Split(';'));
                    }
                    catch (Exception)
                    {
                        //somehting went wrong
                        //log error
                    }
                }
            }  

I have created GenericPrincipal object and set our user specific details (Username and Role) into it. Please go through the following article on how to create custom form authentication in MVC. http://www.codeproject.com/Articles/578374/AplusBeginner-27splusTutorialplusonplusCustomplusF

I have created two areas [organizer and monitor] that indicate the student role in the project. You can create area by selecting project name, right click -> Add -> Area, and assign a name to the new area, when the area creation ends, we see a new folder called Areas, and within this folder you can see a folder with the name of your area. Area content same file structure as you project has you can visualize area as the child project within you parent MVC project.

Lot time we face situation where we want to navigate to different section from one parent section. For better user experience let’s create parent section as the View and all the related section as the Partial View and render them into parent section based on the requirement.

@{
    Layout = "~/Views/Shared/_Layout1.cshtml";
 
    ViewBag.Title = "Monitor";
}
<h2>
    Moniter Task.</h2>
<div class="nav">
    <ul class="nav">
        <li class="nav">
            @Html.ActionLink("Site Map", "SiteMap", "Home", new { area = "" }, new { @class = "nav" })
        </li>
        <li class="nav">
            @Ajax.ActionLink("Task1", "Task1", "Home", new { Area = "Moniter" }, new AjaxOptions { UpdateTargetId = "body_content" }, new { @class = "nav" })
        </li>
        <li class="nav">
            @Ajax.ActionLink("Task2", "Task2", "Home", new { Area = "Moniter" }, new AjaxOptions { UpdateTargetId = "body_content" }, new { @class = "nav" })
        </li>
    </ul>
</div>
<div id="body_content">
</div> 
Notice the area Monitor it contain parent view as the Index View. Index view contain navigation bar to the page related to the Monitor task. For better UI experience instead of navigating to the related pages I have created Partial View and PartialViewResult. where navigation link is the @ajax.actionlink that render the Partial View into the same page.

On the click of the task1 link, ajax actionlink call to the Partial View action task1 and get Partial View as return. It render Partial View inside the element having id specified as the update target control id. 

Using the same logic I have created other area controller action. When you are developing actual project you will have complex logic instead of this simple "Task One Begin.." message inside you Partial View.

Please look into the attached code for more clearity. Hope this will kick start your application development.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here