Friday, June 6, 2014

ASP.NET MVC TUTORIAL VOLUME IV


Lesson 85 - Enable client side validation in asp.net mvc

Suggested Lessons 
Lesson 82 - Creating custom validation attribute
Lesson 83 - RegularExpression attribute 
Lesson 84 - Compare attribute
Validation attributes in asp.net mvc provides both client and server side validation. There are 2 simple steps to enable client side validation in asp.net mvc.
Step 1: Enable ClientValidation and UnobtrusiveJavaScript in web.config file.
<appSettings>
  
<add key="ClientValidationEnabled" value="true" />
  
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings> 

Step 2: Include a reference to the following javascript files. In real time, the references to the javascript files are included in the master page. This avoids the need to reference them on each and every view where we need validation. The order in which the script files are referenced is also important. jquery.validate is dependant on jquery and /jquery.validate.unobtrusive is dependant on jquery.validate, so they should be referenced in the following order. Otherwise, client side validation will not work. In short, JavaScript is parsed "top-down", so all dependencies need to be referenced before the dependant reference.
<script src="~/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="~/Scripts/jquery.validate.min.js" type="text/javascript"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>
With these 2 changes, validation should now happen on the client without a round trip to the server. If the client disables javascript in the browser, then client side validation does not work, but server side validation will continue to work as normal.
Lesson 86 - ValidationSummary in asp.net mvc
Suggested Lessons 
In this Lesson, we will discuss displaying all validation errors at one place using validation summary html helper. A red asterisk (start) should be displayed next to every field that has failed the validation. The output should be as shown below.
 

 We will be working with the example that we discussed in Lesson 85. Please check Lesson 85, before proceeding.

First of all, the validation error messages should be displayed in red color. On the "Edit" view, include a reference to Site.css style sheet.
<link href="~/Content/Site.css" rel="stylesheet" type="text/css" />

In site.css there are 3 CSS classes that control the display of validation error messages. Adjust the styles of these classes according to your needs.
field-validation-error
input.input-validation-error
validation-summary-errors

To display all errors at one place, use ValidationSummary() HTML helper. 
@Html.ValidationSummary(
false, "Please fix the following errors and then submit the form")

To display an asterisk, next to the field that has failed validation, modfiy ValidationMessageFor() html helper as shown below.
@Html.ValidationMessageFor(model => model.Name, 
"*")

At this point, next to the field that has failed the validation message, a star symbol will be displayed instead of the detailed error message. All the detailed error messages will be displayed using validation summary.

Lesson 87 - What is Unobtrusive JavaScript

Suggested Lessons 
What is Unobtrusive JavaScript?
Unobtrusive JavaScript, is a JavaScript that is separated from the web site’s html markup. There are several benefits of using Unobtrusive JavaScript. Separation of concerns i.e the HTML markup is now clean without any traces of javascript. Page load time is better. It is also easy to update the code as all the Javascript logic is present in a separate file. We also get, better cache support, as all our JavaScript is now present in a separate file, it can be cached and accessed much faster.
Example:
We want to change the backgroundColor of "Save" button on "Edit" view to "Red" on MouseOver and to "Grey" on MouseOut.
First let's look at achieving this using obtrusive javascript.
Step 1: Implement MouseOver() and MouseOut() functions
<script type="text/javascript" language="javascript">
    
function MouseOver(controlId) {
        
var control = document.getElementById(controlId);
        control.style.backgroundColor = 
'red'
    }

    
function MouseOut(controlId) {
        
var control = document.getElementById(controlId);
        control.style.backgroundColor = 
'#d3dce0'
    }
</script>

Step 2: Associate the javascript functions with the respective events.
<input id="btnSubmit" type="submit" value="Save"
    
onmouseover="MouseOver('btnSubmit')" onmouseout="MouseOut('btnSubmit')" />

Now let's look at making this javascript unobtrusive, using jQuery
Step 1: Right click on the "Scripts" folder in "Soultion Explorer", and add a jScript file with name = "CustomJavascript.js"

Step 2: Copy and paste the following code in CustomJavascript.js file.
$(
function () {
    $(
"#btnSubmit").mouseover(function () {
        $(
"#btnSubmit").css("background-color", "red");
    });

    $(
"#btnSubmit").mouseout(function () {
        $(
"#btnSubmit").css("background-color", "#d3dce0");
    });
});

Step 3: Add a reference to CustomJavascript.js file in Edit view.
<script src="~/Scripts/CustomJavascript.js" type="text/javascript"></script>

Step 4: Remove the following obtrusive Javascript from "Edit" view
<script type="text/javascript" language="javascript">
    
function MouseOver(controlId) {
        
var control = document.getElementById(controlId);
        control.style.backgroundColor = 
'red'
    }

    
function MouseOut(controlId) {
        
var control = document.getElementById(controlId);
        control.style.backgroundColor = 
'#d3dce0'
    }
</script>

Also, remove "onmouseover" and "onmouseout" events from the button control.
<input id="btnSubmit" type="submit" value="Save"
    
onmouseover="MouseOver('btnSubmit')" onmouseout="MouseOut('btnSubmit')" />

Lesson 88 - Unobtrusive validation in asp.net mvc

Suggested Lessons 
Client side validation in asp.net mvc is unobtrusive. To turn on client side validation and unobtrusive JavaScript, make sure the following 2 keys under appSettings element within web.config file are turned on. This will turn on client side validation and unobtrusive JavaScript for the entire application.
<appSettings>
  
<add key="ClientValidationEnabled" value="true" />
  
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>

Is it possible to turn these features on/off using code?
Yes, the features can be enabled or disabled in Application_Start() event handler in Global.asax as shown below. This will turn on client side validation and unobtrusive JavaScript for the entire application.
protected void Application_Start()
{
    
HtmlHelper.UnobtrusiveJavaScriptEnabled = true;
    
HtmlHelper.ClientValidationEnabled = true;
}

Is it possible to turn these features on/off for a specific view?
Yes, include the following code, on a view where you want to enable/disable these features.
@{
    Html.EnableClientValidation(
true);
    Html.EnableUnobtrusiveJavaScript(
true);
}

How is Unobtrusive validation implemented in asp.net mvc?
Using "data" attributes. For example, if we use "Required" attribute, on Name property and if we enable client side validation and unobtrusive JavaScript, then the generated HTML for "Name" field is as shown below.
<input class="text-box single-line"
      
data-val="true"
      
data-val-required="The Name field is required." 
      
id="Name" 
      
name="Name"
      
type="text" 
      
value="Sara Nan" />

data-val=”true”, indicates that the unobtrusive validation is turned on for this element.
data-val-required="The Name field is required.", indicates that the "Name" field is required and the associated error message will be displayed if the validation fails. These data attributes are used by jQuery validation plugin for client side validation.

Lesson 89 - Remote validation in asp.net mvc


Sometimes, to check if a field value is valid, we may need to make a database call.A classic example of this is the user registration page. To register a user, we need a unique username. So, to check, if the username is not taken already, we have to make a call to the server and check the database table. RemoteAttribute is useful in situations like this. 
Example: When a user provides a username that already exists, the associated validation error message should be displayed immediately as shown below. 
remote validation in asp.net mvc 

Step 1: Create tblUsers table
Create table tblUsers
(
 [Id] 
int primary key identity,
 [FullName] 
nvarchar(50),
 [UserName] 
nvarchar(50),
 [Password] 
nvarchar(50)
)

Step 2: Create an ado.net entity data model using table tblUsers. Upon creating the entity model, change the name of the entity from to User. Save changes and build the solution.

Step 3: Add HomeController with the following settings
1. controller Name = HomeController
2. Template = MVC controller with read/write actions and views, using Entity Framework
3. Model Class = User (MVCDemo.Models)
4. Data context class = SampleDBContext (MVCDemo.Models)
5. Views = Razor

Step 4: Copy and paste the following function in HomeController. This is the method which gets called to perform the remote validation. An AJAX request is issued to this method. If this method returns true, validation succeeds, else validation fails and the form is prevented from being submitted. The parameter name (UserName) must match the field name on the view. If they don't match, model binder will not be able bind the value with the parameter and validation may not work as expected.
public JsonResult IsUserNameAvailable(string UserName)
{
    
return Json(!db.Users.Any(x => x.UserName == UserName),
                                         
JsonRequestBehavior.AllowGet);
}

Step 5: Right click on the Models folder and a class file with name = User.cs. Copy and paste the following code. Notice that the name of the method (IsUserNameAvailable) and the controller name (Home) and error message are passed as arguments to Remote Attribute
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace MVCDemo.Models
{
    [
MetadataType(typeof(UserMetaData))]
    
public Lessonial class User
    {
    }

    
public class UserMetaData
    {
        [
Remote("IsUserNameAvailable", "Home", ErrorMessage="UserName already in use.")]
        
public string UserName { get; set; }
    }
}

Step 6: Include references to the following css and script files in Create.cshtml view.jQuery, jquery.validate and jquery.validate.unobtrusive script files are required for remote validation to work.
<link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
<script src="~/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="~/Scripts/jquery.validate.min.js" type="text/javascript"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js" type="text/javascript"></script>

Step 7: Make sure ClientValidation and UnobtrusiveJavaScript are enabled in web.config
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />

Lesson 90 - Remote validation in mvc when javascript is disabled

Please check Lesson 89 from asp.net mvc tutorial, before proceeding.
Out of the box, Remote attribute only works when JavaScript is enabled. If the end user, disables JavaScript on his/her machine then the validation does not work. This is because RemoteAttribute requires JavaScript to make an asynchronous AJAX call to the server side validation method. As a result, the user will be able to submit the form, bypassing the validation in place. This why it is always important to have server side validation.

 

To make server side validation work, when JavaScript is disabled, there are 2 ways
1. Add model validation error dynamically in the controller action method
2. Create a custom remote attribute and override IsValid() method

In this Lesson, we will discuss, adding model validation error dynamically in the controller action method. We will continue with the example, that we worked with in Lesson 89. Modify the Create action method that is decorated with [HttpPost] attribute as shown below.
[
HttpPost]
public ActionResult Create(User user)
{
    
// Check if the UserName already exists, and if it does, add Model validation error
    
if (db.Users.Any(x => x.UserName == user.UserName))
    {
        ModelState.AddModelError(
"UserName", "UserName already in use");
    }
    
if (ModelState.IsValid)
    {
        db.Users.AddObject(user);
        db.SaveChanges();
        
return RedirectToAction("Index");
    }

    
return View(user);
}

At this point, disable JavaScript in the browser, and test your application. Notice that, we don't get client side validation, but when you submit the form, server side validation still prevents the user from submitting the form, if there are validation errors.

However, delegating the responsibility of performing validation, to a controller action method violates separation of concerns within MVC. Ideally all validation logic should be in the Model. Using validation attributes in mvc models, should be the preferred method for validation. In our next Lesson, we will discuss, creating a custom remote attribute and overriding IsValid() method.

Lesson 91 - Create a custom remote attribute and override IsValid() method

Please check Lesson 90 from asp.net mvc tutorial, before proceeding.
Out of the box, Remote attribute only works when JavaScript is enabled. If the end user, disables JavaScript on his/her machine then the validation does not work. This is because RemoteAttribute requires JavaScript to make an asynchronous AJAX call to the server side validation method. As a result, the user will be able to submit the form, bypassing the validation in place. This why it is always important to have server side validation.
To make server side validation work, when JavaScript is disabled, there are 2 ways
1. Add model validation error dynamically in the controller action method - Discussed inLesson 90
2. Create a custom remote attribute and override IsValid() method

In this Lesson, we will discuss, creating a custom remote attribute
Step 1: Right click on the project name in solution explorer and a folder with name = "Common"

Step 2: Right click on the "Common" folder, you have just added and add a class file with name = RemoteClientServer.cs

Step 3: Copy and paste the following code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;
using System.Reflection;

namespace MVCDemo.Common
{
    
public class RemoteClientServerAttribute : RemoteAttribute
    {
        
protected override ValidationResult IsValid(object value, ValidationContextvalidationContext)
        {
            
// Get the controller using reflection
            
Type controller = Assembly.GetExecutingAssembly().GetTypes()
                .FirstOrDefault(type => type.Name.ToLower() == string.Format(
"{0}Controller",
                    
this.RouteData["controller"].ToString()).ToLower());
            
if (controller != null)
            {
                
// Get the action method that has validation logic
                
MethodInfo action = controller.GetMethods()
                    .FirstOrDefault(method => method.Name.ToLower() ==
                        
this.RouteData["action"].ToString().ToLower());
                
if (action != null)
                {
                    
// Create an instance of the controller class
                    
object instance = Activator.CreateInstance(controller);
                    
// Invoke the action method that has validation logic
                    
object response = action.Invoke(instance, new object[] { value });
                    
if (response is JsonResult)
                    {
                        
object jsonData = ((JsonResult)response).Data;
                        
if (jsonData is bool)
                        {
                            
return (bool)jsonData ? ValidationResult.Success :
                                
new ValidationResult(this.ErrorMessage);
                        }
                    }
                }
            }

            
return ValidationResult.Success;
            
// If you want the validation to fail, create an instance of ValidationResult
            // return new ValidationResult(base.ErrorMessageString);
        }

        
public RemoteClientServerAttribute(string routeName)
            : 
base(routeName)
        {
        }

        
public RemoteClientServerAttribute(string action, string controller)
            : 
base(action, controller)
        {
        }

        
public RemoteClientServerAttribute(string action, string controller,
            
string areaName) : base(action, controller, areaName)
        {
        }
    }
}

Step 4: Open "User.cs" file, that is present in "Models" folder. Decorate "UserName"property with RemoteClientServerAttribute.

RemoteClientServerAttribute is in MVCDemo.Common namespace, so please make sure you have a using statement for this namespace.
public class UserMetadata
{
    [
RemoteClientServer("IsUserNameAvailable", "Home",
        ErrorMessage=
"UserName already in use")]
    
public string UserName { get; set; }
}

Disable JavaScript in the browser, and test your application. Notice that, we don't get client side validation, but when you submit the form, server side validation still prevents the user from submitting the form, if there are validation errors.

Lesson 92 - Ajax with asp.net mvc

Suggested Lessons 
Lesson 89 - Remote validation in asp.net mvc
Lesson 90 - Remote validation in mvc when javascript is disabled 
Lesson 91 - Create a custom remote attribute and override IsValid() method

 

ASP.NET AJAX enables a Web application to retrieve data from the server asynchronously and to update portions of the existing page. So these, Lessonial page updates make web application more responsive and hence improves user experience. 

 

In this Lesson, let's discus using Ajax.ActionLink helper. By the end of this Lesson, we should be able to load either
1. All students or
2. Top 3 students or
3. Bottom 3 students
depending on the link we have clicked.
ajax with asp.net mvc 

Here are the steps to achieve this
Step 1: Sql script to create and populate table tblStudents
Create table tblStudents
(
 Id 
int identity primary key,
 Name 
nvarchar(50),
 TotalMarks 
int
)

Insert into tblStudents values ('Mark', 900)
Insert into tblStudents values ('Pam', 760)
Insert into tblStudents values ('John', 980)
Insert into tblStudents values ('Ram', 990)
Insert into tblStudents values ('Ron', 440)
Insert into tblStudents values ('Able', 320)
Insert into tblStudents values ('Steve', 983)
Insert into tblStudents values ('James', 720)
Insert into tblStudents values ('Mary', 870)
Insert into tblStudents values ('Nick', 680)

Step 2: Create an ado.net entity data model using table tblStudents. Upon creating the entity model, change the name of the entity to Student. Save changes and build the solution, so that the Student entity class gets compiled.

Step 3: Add "Shared" folder (if it doesn't already exists) in "Views" folder. Right click on"Shared" folder and add a Lessonial view, with name = _Student.cshtml.
@model 
IEnumerable<MVCDemo.Models.Student>

<table style="border:1px solid black; background-color:Silver">
<tr>
    
<th>
        @Html.DisplayNameFor(model => model.Name)
    
</th>
    
<th>
        @Html.DisplayNameFor(model => model.TotalMarks)
    
</th>
</tr>

@
foreach (var item in Model)
{
    
<tr>
        
<td>
            @Html.DisplayFor(modelItem => item.Name)
        
</td>
        
<td>
            @Html.DisplayFor(modelItem => item.TotalMarks)
        
</td>
    
</tr>
}
</table>

Step 4: Right click on the "Controllers" folder and add a controller with the following settings
1. Controller Name = HomeController
2. Template = Empty MVC controller

Copy and paste the following code. Please make sure to include MVCDemo.Models namespace.
public class HomeController : Controller
{
    // Create an instance of DatabaseContext class
    
DatabaseContext db = new DatabaseContext();

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

    // Return all students
    
public LessonialViewResult All()
    {
        
List<Student> model = db.Students.ToList();
        
return LessonialView("_Student", model);
    }

    // Return Top3 students
    
public LessonialViewResult Top3()
    {
        
List<Student> model = db.Students.OrderByDescending(x => x.TotalMarks).Take(3).ToList();
        
return LessonialView("_Student", model);
    }

    // Return Bottom3 students
    
public LessonialViewResult Bottom3()
    {
        
List<Student> model = db.Students.OrderBy(x => x.TotalMarks).Take(3).ToList();
        
return LessonialView("_Student", model);
    }
}

Step 5: Right click on the "Views" folder and add a folder with name = "Home". Right click on the "Home" folder and add a view with Name = "Index".
Points to remember:
a) For AJAX to work, jquery and jquery.unobtrusive-ajax javascript files need to be referenced. Reference to jquery.unobtrusive-ajax.js file should be after jquery.js reference.
b) Ajax.ActionLink() html helper has several overloaded versions. We have used the following version
ActionLink(
string linkText, string actionName, AjaxOptions ajaxOptions);
First parameter : is the link text that we see on the user interface
Second parameter : is the name of the action method that needs to be invoked, when the link is cicked.
Third parameter : is the ajaxOptions object.

<div style="font-family:Arial">

<script src="~/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js" type="text/javascript"></script>

<h2>Students</h2>

@Ajax.ActionLink(
"All", "All",
    
new AjaxOptions 
    {
      HttpMethod = 
"GET", // HttpMethod to use, GET or POST
      UpdateTargetId = 
"divStudents", // ID of the HTML element to update
      InsertionMode = 
InsertionMode.Replace // Replace the existing contents
    })

<span style="color:Blue">|</span>

@Ajax.ActionLink(
"Top 3", "Top3",
    
new AjaxOptions 
    {
      HttpMethod = 
"GET"// HttpMethod to use, GET or POST
      UpdateTargetId = 
"divStudents"// ID of the HTML element to update
      InsertionMode = 
InsertionMode.Replace // Replace the existing contents
    })

<span style="color:Blue">|</span>

@Ajax.ActionLink(
"Bottom 3", "Bottom3",
    
new AjaxOptions 
    {
      HttpMethod = 
"GET"// HttpMethod to use, GET or POST
      UpdateTargetId = 
"divStudents"// ID of the HTML element to update
      InsertionMode = 
InsertionMode.Replace // Replace the existing contents
    })

<br /><br />
<div id="divStudents">
</div>
</div>

Lesson 93 - What is Ajax and why should we use it

In this Lesson, we will discuss
1. What is AJAX
2. Advantages and disadvantages of using AJAX
3. Applications that are currently using AJAX.
4. When to use AJAX
What is AJAX
AJAX stands for Asynchronous JavaScript And XML. AJAX enable web applications to retrieve data from the server asynchronously. Web application using AJAX enables Lessonial page updates, ie. only the related section of the page is updated, without reloading the entire page.

Advantages of AJAX
1. AJAX applications are non blocking. As AJAX requests are asynchronous, the user doesn't have to wait for the request processing to complete. Even while the request is still being processed by the server, the application remains responsive and the user can interact with the application. When the request processing is complete, the user interface is automatically updated. This is not the case with, synchronous requests. The user interface is blocked and the user cannot do anything else until the request has completed processing.
2. Better performance and reduced network traffic. AJAX enables an application to send and receive only the data that is required. As a result, there is reduced traffic between the client and the server and better peofrmance.
3. No screen flicker. An AJAX response consists of only the data that is relevant to the request. As a result, only a portion of the page is updated avoiding full page refresh and screen flickers.
Disadvantages of AJAX:
1. AJAX requests cannot be bookmarked easily
2. AJAX relies on JavaScript. If JavaScript is disabled, AJAX application won't work.
3. Harder to debug
4. Search Engine like Google, Bing, Yahoo etc cannot index AJAX pages.
Applications using AJAX
1. Many web sites like Google, bing, youtube, yahoo use AJAX to implement AutoComplete feature.
2. Gmail use AJAX to implement AutoSave feature
3. Gmail use AJAX to implement RemoteValidation i.e to validate if a user name is already in use, when creating a gmail account. We discussed remote validation in Lessons 89, 90 &91.
4. Facebook use AJAX, to load data as you keep scrolling down.

AJAX is generally used to implement features like 
1. AutoComplete
2. AutoSave
3. Remote validation etc

Lesson 94 - Providing visual feedback using LoadingElementId AjaxOption

This is continuation to Lesson 93, Please check Lesson 93 from the ASP.NET MVC tutorialbefore proceeding with this Lesson.
One problem with Lessonial page updates is that, they donot provide any visual feedback if the request is taking a long time to process. With full page postbacks, we don't have this problem, because the entire page is posted to the server and hence the user knows something is happening.
For example, let's say a request in an ajax enabled application takes 10 seconds to complete. When the user clicks the button and if we don't provide him with any visual feedback that the request is being processed, the user may think the website is not working and he may click the button again. So, it is very important that we provide some visual feedback. To achieve this here are the steps.

Step 1: Right click on the project name in solution explorer, and a folder with name = Images. Download and paste the following animated GIF image, in the Images folder.
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglSBVZySXK2Ryl_Eyy_2ThA_oSGypmQzLKHOzcNwdCeIH-r9Sp4QBQO0aX3cxwFDINmZFpCG5Ixz5gdZxlAJ21XrM50SFZs6fLRwFbUc4_myr-nGrSZvPWt2lJqviS3zI5ZLjSIUS3MvvB/s1600/spinner.gif 

Please note: You can create animated GIF images using the following website.
http://spiffygif.com

Step 2: Place the following DIV tag on the view, where you want the image to show up when request is still being processed.
<div id="divloading" style="display:none;">
   
<img src="~/Images/spinner.gif"/>
</div>

Step 3: Modify the Ajax.ActionLink() html helper method on the view as shown below. Notice that, we have set LoadingElementId = "divloading"
@Ajax.ActionLink(
"All", "All",
    
new AjaxOptions 
    {
      HttpMethod = 
"GET",
      UpdateTargetId = 
"divStudents",
      InsertionMode = 
InsertionMode.Replace,
      LoadingElementId = 
"divloading"
    })

Step 4: The controller action method in our example, completes in no time. So the image never shows up. To introduce some latency include, System.Threading.
Thread.Sleep(1000); statement in the controller action method. The duration for the sleep method is in milliseconds. We have specified 1000 mill-seconds, so the thread is going to sleep for 1 second.
public LessonialViewResult All()
{
    System.Threading.
Thread.Sleep(1000);
    
List<Student> model = db.Students.ToList();
    
return LessonialView("_Student", model);
}

Now run the application and notice that image shows up, while the request is still being processed. When request processing completes and when the response is received, the loading image disappears and the UI is automatically updated, with the data received. 

Lesson 95 - OnBegin, OnComplete, OnSuccess and OnFailure properties of AjaxOptions class

This is continuation to Lesson 94, Please check Lesson 94 from the ASP.NET MVC tutorialbefore proceeding with this Lesson.

Using the following 4 properties of the AjaxOptions class, we can associate JavaScript functions that get called on the client at different stages of an AJAX request/response cycle.
1. OnBegin - The associated JavaScript function is called before the action method is invoked
2. OnComplete - The associated JavaScript function is invoked after the response data has been instantiated but before the page is updated.
3. OnSuccess - The associated JavaScript function is invoked after the page is updated.
4. OnFailure - The associated JavaScript function is invoked if the page update fails.
We will continue with the example that we discussed in Lesson 94
1. When you click on "All" link, all the students will be loaded into the <div> element that has got 
id=divStudents.
2. At the moment, when you click on "Top 3" link, the data from the previous request is still present in "divStudents". Only when "Top 3" students become available,"divStudents" is updated with new data.
3. Our application requirement is to clear, "divStudents" element content, as soon as we click on any AJAX link and before the associated action method is invoked.

To achieve this, let's use "OnBegin" property of AjaxOptions class.
Step 1: The following JavaScript function, finds the "divStudents" and clear it's contents
function ClearResults()
{
    $(
"#divStudents").empty();
}

Step 2: Associate ClearResults() function with "OnBegin" property of AjaxOptions class.
@Ajax.ActionLink(
"All", "All",
    
new AjaxOptions 
    {
      HttpMethod = 
"GET",
      UpdateTargetId = 
"divStudents",
      InsertionMode = 
InsertionMode.Replace,
      LoadingElementId = 
"divloading",
      OnBegin = 
"ClearResults"
    })

Please Note:
OnBegin property can also be used to cancel the invocation of the action method. The JavaScript function that is associated with "OnBegin" property is invoked before the action method is invoked. So if that associated JavasSript function returns false, then the action method will not be invoked. Your JavaScript function may look something like this.
function Validate()
{
    
if (condition)
    {
        
return true;
    }
    
else 
    {
        
return false;
    }
}

Let's now discuss an example of using "OnSuccess" property. Immediately after the page is updated with students data, we want to dispay the total number of rows retrieved using JavaScript alert.
OnSuccess ajaxoptions example 

To achieve this, let's use "OnSuccess" property of AjaxOptions class.
Step 1: Set id attribute for the table element in "_Student.cshtml" Lessonial view
<table id="tableStudents" style="border:1px solid black; background-color:Silver">

Step 2: The following JavaScript function counts the total number of rows.
function CountRows()
{
    alert(($(
"#tableStudents tr").length - 1) + 'rows retrieved');
}

Step 3: Associate CountRows() function with "OnSuccess" property of AjaxOptions class.
@Ajax.ActionLink(
"All", "All",
    
new AjaxOptions 
    {
      HttpMethod = 
"GET",
      UpdateTargetId = 
"divStudents",
      InsertionMode = 
InsertionMode.Replace,
      LoadingElementId = 
"divloading",
      OnSuccess = 
"CountRows"
    })

Lesson 96 - LoadingElementDuration property of AjaxOptions class

This is continuation to Lesson 95, Please check Lesson 95 from the ASP.NET MVC tutorialbefore proceeding with this Lesson.

LoadingElementDuration property is used to control the animaion duration of LoadingElement. The value for LoadingElementDuration property must be specified in milliseconds. By default, the LoadingElement fades in and fades out.

 

But I noticed that, irrespective of whatever duration you set, the LoadingElement was fading in and out at the same speed. I have done some research on google and came across the following stackoverflow article which explained the fix for the issue.
http://stackoverflow.com/questions/8928671/asp-net-mvc-3-loadingelementduration-not-working

To fix the issue, we need to parse the duration to integer. Open "jquery.unobtrusive-ajax.js" and change the following line
FROM
duration = element.getAttribute(
"data-ajax-loading-duration") || 0;
TO
duration = parseInt(element.getAttribute(
"data-ajax-loading-duration")) || 0;

After you have made the change, reference "jquery.unobtrusive-ajax.js" file in the "Index"view
<script src="~/Scripts/jquery.unobtrusive-ajax.js" type="text/javascript"></script>

Finally set, LoadingElementDuration and test your application
@Ajax.ActionLink(
"All", "All",
    
new AjaxOptions 
    {
      HttpMethod = 
"GET",
      UpdateTargetId = 
"divStudents",
      InsertionMode = 
InsertionMode.Replace,
      LoadingElementId = 
"divloading",
      OnBegin = 
"ClearResults",
      OnSuccess = 
"CountRows",
      LoadingElementDuration = 2000
    }) 

Lesson 97 - Implement autocomplete textbox functionality in mvc

Suggested Lessons 
Lesson 94 - Providing visual feedback using LoadingElementId AjaxOption
Lesson 95 - OnBegin, OnComplete, OnSuccess and OnFailure properties of AjaxOptions class 
Lesson 96 - LoadingElementDuration property of AjaxOptions class 

 

In this Lesson, we will discuss implementing auto-complete functionality in an asp.net mvc application using jQuery Autocomplete Widget
autocomplete in mvc 

 

Step 1: We will be using tblStudents table in this demo. Please find the sql script below, to create and populate this table with some data.
Create Table tblStudents
(
 ID 
int identity primary key,
 Name 
nvarchar(50),
 Gender 
nvarchar(20),
 TotalMarks 
int
)

Insert into tblStudents values('Mark Hastings','Male',900)
Insert into tblStudents values('Pam Nicholas','Female',760)
Insert into tblStudents values('John Stenson','Male',980)
Insert into tblStudents values('Ram Gerald','Male',990)
Insert into tblStudents values('Ron Simpson','Male',440)
Insert into tblStudents values('Able Wicht','Male',320)
Insert into tblStudents values('Steve Thompson','Male',983)
Insert into tblStudents values('James Bynes','Male',720)
Insert into tblStudents values('Mary Ward','Female',870)
Insert into tblStudents values('Nick Niron','Male',680)

Step 2: Create an ado.net entity data model using table tblStudents. Change the name of the generated entity from tblStudent to Student.

Step 3: Download autocomplete widget from http://jqueryui.com/download. The following folders and files will be downloded.
autocomplete widget files 

Step 4: Open "js" folder copy "jquery-1.9.1.js" and "jquery-ui-1.10.3.custom.min.js"files and paste them in the "Scripts" folder of you mvc project. Now open "css" folder. This folder will be present in "ui-lightness" folder. Copy "images" folder and "jquery-ui-1.10.3.custom.min.css" file and paste them in "Content" folder in your mvc project. If you are following along, at this point your solution explorer should look as shown below.
jquery javascript files required for implementing autocomplete feature in mvc 

Step 5: Right click on the "Controllers" folder and add "Home" controller. Copy and paste the following code. Please make sure to include "MVCDemo.Models"namespace.
public class HomeController : Controller
{
    
public ActionResult Index()
    {
        
DatabaseContext db = new DatabaseContext();
        
return View(db.Students);
    }

    [
HttpPost]
    
public ActionResult Index(string searchTerm)
    {
        
DatabaseContext db = new DatabaseContext();
        
List<Student> students;
        
if (string.IsNullOrEmpty(searchTerm))
        {
            students = db.Students.ToList();
        }
        
else
        {
            students = db.Students
                .Where(s => s.Name.StartsWith(searchTerm)).ToList();
        }
        
return View(students);
    }

    
public JsonResult GetStudents(string term)
    {
        
DatabaseContext db = new DatabaseContext();
        
List<string> students = db.Students.Where(s => s.Name.StartsWith(term))
            .Select(x => x.Name).ToList();
        
return Json(students, JsonRequestBehavior.AllowGet);
    }
}

Step 6: Right click on the "Index" action method in the "HomeController" and add"Index" view. Copy and paste the following code.
@model 
IEnumerable<MVCDemo.Models.Student>

<
link href="~/Content/jquery-ui-1.10.3.custom.min.css" rel="stylesheet" type="text/css" />
<script src="~/Scripts/jquery-1.9.1.js" type="text/javascript"></script>
<script src="~/Scripts/jquery-ui-1.10.3.custom.min.js" type="text/javascript"></script>

<script type="text/javascript">
    $(
function () {
        $(
"#txtSearch").autocomplete({
            source: '@Url.Action(
"GetStudents")',
            minLength: 1
        });
    });
</script>

<div style="font-family:Arial">

@
using (@Html.BeginForm())
{
    
<b>Name: </b>
    @Html.TextBox(
"searchTerm", null, new { id = "txtSearch" })
    
<input type="submit" value="Search" />
}

<table border="1">
    
<tr>
        
<th>
            @Html.DisplayNameFor(model => model.Name)
        
</th>
        
<th>
            @Html.DisplayNameFor(model => model.Gender)
        
</th>
        
<th>
            @Html.DisplayNameFor(model => model.TotalMarks)
        
</th>
    
</tr>

@
foreach (var item in Model)
{
    
<tr>
        
<td>
            @Html.DisplayFor(modelItem => item.Name)
        
</td>
        
<td>
            @Html.DisplayFor(modelItem => item.Gender)
        
</td>
        
<td>
            @Html.DisplayFor(modelItem => item.TotalMarks)
        
</td>
    
</tr>
}
</table>
</div> 

Lesson 98 - What is JavaScript minification


What is JavaScript minification?
JavaScript minification is the process of reducing the size of JavaScript file, by removing comments, extra white spaces, new line characters and using shorter variable names.
What are the advantages of JavaScript minification?
As the minified JavaScript files are very small, they will be downloaded much faster and consumes less bandwidth. Search engines like google considers page load time as one of the parameters to rank the pages.

Is any of the functionality lost because of minification?
No, the functionality will be exactly the same as before.

Are there any tools available to minify JavaScript?
There are lot of free tools available on the web. Just GOOGLE by using "Minify JavaScript" search term.

What is the difference between jquery.js and jquery.min.js?
jquery.min.js is the minified version, where as jquery.js is the non-minified version. In your production website always use minified files as they download faster and consumes less bandwidth.

What is the downside of JavaScript minification?
They are harder to read and debug. However, for development and debugging we can use non-minified versions. Just before deployment, minify and use the minified versions on the production environment.

Lesson 99 - What is CDN - Content Delivery Network

CDN stands for Content Delivery Network. CDN is a network of computers that exist all over the world. For a web application there are 2 ways we can make the jQuery library available
1. Have a copy of the jQuery library on your web server and reference it
<script src="~/Scripts/jquery-1.7.1.min.js" type="text/javascript">
</script>
2. Reference the jQuery library from a CDN. (Microsoft, Google, or jQuery)
<script src="http://code.jquery.com/jquery-1.7.1.min.js" type="text/javascript">
</script>

Google CDN: http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js
Microsoft CDN: http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js
Jquery CDN: http://code.jquery.com/jquery-1.7.1.min.js

Benefits or advantages of using a CDN:
1. Caching benefits - If other web sites use jquery and if the user has already visited those websites first, jquery file is cached. If the user then visits your website, the cached jquery file is used without having the need to download it again.

2. Speed benefits - The jquery file from the nearest geographical server will be downloaded.

3. Reduces network traffic - As the jQuery file is loaded from a CDN, this reduces the network traffic to your web server.

4. Parallelism benefit - There is a limitation on how many components can be downloaded in parallel. This limitation is per  hostname. For example,
1. If the browser allows only 2 components to be downloaded in parallel per hostname and
2. If a web page requires 4 components and
3. If all of them are hosted on a single host and
4. If 2 components take 1 second to download
Then to download all the 4 components, it is going to take 2 seconds.

However, if 2 of the components are hosted on a different host(server), then all the 4 components can be downloaded in parallel and in 1 second.

Lesson 100 - What if CDN is down


Suggested Lessons 
Lesson 97 - Implement autocomplete textbox functionality in mvc
Lesson 98 - What is JavaScript minification 
Lesson 99 - What is CDN - Content Delivery Network

 

In this Lesson we will disccuss
1. What if CDN is down?
2. How to fallback from CDN to use local copy of Jquery?

There are several benefits of referencing a resource from a CDN. We discussed these inLesson 99 of asp.net mvc tutorial.

 

A CDN is an external resource and beyond our control. So, what if, CDN is down? How can we fall back from CDN to use local copy of Jquery.

The following code checks if jQuery is loaded and if it isn't, the jquery script will be loaded from our web server.
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" 
        
type="text/javascript">
</script>

<script type="text/javascript">
    
window.jQuery || document.write('<script src="/MVCDemo/Scripts/jquery-1.7.1.min.js">\x3C/script>')
</script>

No comments:

Post a Comment