Você está na página 1de 162

Introduction to ASP.

NET MVC
ASP.NET MVC is a new web application framework from Microsoft. MVC stands for Model-View-Controller, a pattern thats becoming
increasingly popular with web development frameworks. ASP.NET MVC is an alternative and a complement to Web Forms, which means
you wont be dealing with pages and controls, postbacks or view state, or complicated ASP.NET event life cycle.
Basically, MVC is a framework methodology that divides an application's implementation into three component roles: models, views,
and controllers. Hence in Asp.net MVC you need to play with controllers, actions, and views.

MVC Pattern
The Model-View-Controller (MVC) pattern is an adaptation of a pattern generated from the Smalltalk community in the 1970s by Trygve
Reenskaug. It was popularized for use on the web with the advent of Ruby on Rails in 2003.

1.

Model

Models in a MVC based application are the components of the application that are responsible for maintaining state. Often this state is persisted
inside a database for example: we might have a Product class that is used to represent order data from the Products table inside SQL.

2.

View

Views in a MVC based application are the components responsible for displaying the application's user interface. Typically this UI is created off of
the model data for example: we might create an Product "Edit" view that surfaces textboxes, dropdowns and checkboxes based on the current
state of a Product object.

3.

Controller

Controllers in a MVC based application are the components responsible for handling end user interaction, manipulating the model, and ultimately
choosing a view to render to display UI. In a MVC application the view is only about displaying information - it is the controller that handles and
responds to user input and interaction.

ASP.NET MVC Web Application Advantages


The ASP.NET MVC Framework is a new framework and have the following advantages over Web Forms approach (means over ASP.Net):

1.

Separation of concern

In ASP.NET MVC the application is divided to Model, View and Controller parts which make it easier to manage the application complexity.

2.

TDD

The ASP.NET MVC framework brings better support to test-driven development.

3.

Extensible and pluggable

ASP.NET MVC framework components were designed to be pluggable and extensible and therefore can be replaced or customized easier then
Web Forms.

4.

Full control over application behavior

ASP.NET MVC framework doesnt use View State or server based forms like Web Forms. This gives the application developer more control over
the behaviors of the application and also reduces the bandwidth of requests to the server.

5.

ASP.NET features are supported

ASP.NET MVC framework is built on top of ASP.NET and therefore can use most of the features that ASP.NET include such as the providers
architecture, authentication and authorization scenarios, membership and roles, caching, session and more.

6.

URL routing mechanism

ASP.NET MVC framework supports a powerful URL routing mechanism that helps to build a more comprehensible and searchable URLs in your
application. This mechanism helps to the application to be more addressable from the eyes of search engines and clients and can help in search
engine optimization.

The ASP.NET MVC simplifies the complex parts of ASP.net Web Forms without any compromise of the power and flexibility of ASP.NET
platform. ASP.net MVC implements Model-View-Controller UI pattern for web application development that lets you allows to develop
applications in a loosely couples manner. MVC pattern is separating the application in three parts- Model, View and Controller.

Setting default submit button in MVC3 razor using jQuery


In Asp.net MVC, sometimes we required to post the form on Enter key press. Asp.net MVC has no default button property like Asp.net.
However, we can achieve this functionality by using jQuery in MVC.

Set Form DefaultButton Property using jQuery


1.

<script type="text/javascript"> $(document).ready(function (){ $("#MyForm").keypress(function (e) { kCode


= e.keyCode || e.charCode //for cross browser

2.

if (kCode == 13) { var defaultbtn = $(this).attr("DefaultButton");

3.

$("#" + defaultbtn).click();

4.

return false;

5.

6.

});

7.

});

8.

</script>

9.

@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { DefaultButton = "SubmitButton", id =


"MyForm" }))

10. {
11.

@Html.TextBox("txtname")

12.

<span>Please Enter value and then press Enter Key</span><br />

13.

<input type="submit" name="btnSubmit" id="SubmitButton" value="Submit" />

14. }

Summary
In this article I try to explain the default submit behavior of form in MVC. I hope you will refer this article for your need. I would like to
have feedback from my blog readers. Please post your feedback, question, or comments about this article.

ViewData vs ViewBag vs TempData vs Session


In ASP.NET MVC there are three ways - ViewData, ViewBag and TempData to pass data from controller to view and in next request. Like
WebForm, you can also use Session to persist data during a user session. Now question is that when to use ViewData, VieBag,
TempData and Session. Each of them has its own importance. In this article, I am trying to explain the differences among these four.

ViewData
1.

ViewData is a dictionary object that is derived from ViewDataDictionary class.


1.

public ViewDataDictionary ViewData { get; set; }

2.

ViewData is a property of ControllerBase class.

3.

ViewData is used to pass data from controller to corresponding view.

4.

Its life lies only during the current request.

5.

If redirection occurs then its value becomes null.

6.

Its required typecasting for getting data and check for null values to avoid error.

ViewBag
1.

ViewBag is a dynamic property that takes advantage of the new dynamic features in C# 4.0.

2.

Basically it is a wrapper around the ViewData and also used to pass data from controller to corresponding view.
1.

public Object ViewBag { get; }

3.

ViewBag is a property of ControllerBase class.

4.

Its life also lies only during the current request.

5.

If redirection occurs then its value becomes null.

6.

It doesnt required typecasting for getting data.

TempData
1.

TempData is a dictionary object that is derived from TempDataDictionary class and stored in short lives session.
1.

public TempDataDictionary TempData { get; set; }

2.

TempData is a property of ControllerBase class.

3.

TempData is used to pass data from current request to subsequent request (means redirecting from one page to another).

4.

Its life is very short and lies only till the target view is fully loaded.

5.

Its required typecasting for getting data and check for null values to avoid error.

6.

It is used to store only one time messages like error messages, validation messages. To persist data with TempData refer this
article: Persisting Data with TempData

Session
1.

Session is an object that is derived from HttpSessionState class.


1.

public HttpSessionState Session { get; }

2.

Session is a property of HttpContext class.

3.

Session is also used to pass data within the ASP.NET MVC application and Unlike TempData, it never expires.

4.

Session is valid for all requests, not for a single redirect.

5.

Its also required typecasting for getting data and check for null values to avoid error.

Summary
In this article I try to explain the difference between ViewData, ViewBag and TempData. I hope you will refer this article for your need. I
would like to have feedback from my blog readers. Please post your feedback, question, or comments about this article.

Understanding ViewModel in ASP.NET MVC


In ASP.NET MVC, ViewModel is a class that contains the fields which are represented in the strongly-typed view. It is used to pass data
from controller to strongly-typed view.

Key Points about ViewModel


1.

ViewModel contain fields that are represented in the view (for LabelFor,EditorFor,DisplayFor helpers)

2.

ViewModel can have specific validation rules using data annotations or IDataErrorInfo.

3.

ViewModel can have multiple entities or objects from different data models or data source.

ViewModel Example
Designing ViewModel
1.

public class UserLoginViewModel

2.

3.

[Required(ErrorMessage = "Please enter your username")]

4.

[Display(Name = "User Name")]

5.

[MaxLength(50)]

6.

public string UserName { get; set; }

7.

[Required(ErrorMessage = "Please enter your password")]

8.

[Display(Name = "Password")]

9.

[MaxLength(50)]

10.

public string Password { get; set; }

11. }

Presenting the viewmodel in the view


1.
2.

@model MyModels.UserLoginViewModel
@{

3.

ViewBag.Title = "User Login";

4.

Layout = "~/Views/Shared/_Layout.cshtml";

5.

6.

@using (Html.BeginForm())

7.

8.

<div class="editor-label">

9.

@Html.LabelFor(m => m.UserName)

10. </div>
11. <div class="editor-field">
12.

@Html.TextBoxFor(m => m.UserName)

13.

@Html.ValidationMessageFor(m => m.UserName)

14. </div>
15. <div class="editor-label">
16.

@Html.LabelFor(m => m.Password)

17. </div>
18. <div class="editor-field">
19.

@Html.PasswordFor(m => m.Password)

20.

@Html.ValidationMessageFor(m => m.Password)

21. </div>
22. <p>
23.

<input type="submit" value="Log In" />

24. </p>
25. </div>
26. }

Working with Action


1.

public ActionResult Login()

2.

3.

return View();

4.

5.

[HttpPost]

6.

public ActionResult Login(UserLoginViewModel user)

7.

8.

// To acces data using LINQ

9.

DataClassesDataContext mobjentity = new DataClassesDataContext();

10.

if (ModelState.IsValid)

11. {
12. try
13.

14.

var

mobjentity.tblUsers.Where(m

=>

m.UserName

==

user.UserName

&&

m.Password

==

user.Password).ToList();
15.

if (q.Count > 0)

16.

17.

return RedirectToAction("MyAccount");

18.

19.

else

20.

21.

ModelState.AddModelError("", "The user name or password provided is incorrect.");

22.

23.

24.

catch (Exception ex)

25.

26.

27.

28.

return View(user);

29. }

Some Tips for using ViewModel


1.

In ViewModel put only those fields/data that you want to display on the view/page.

2.

Since view reperesents the properties of the ViewModel, hence it is easy for rendering and maintenance.

3.

Use a mapper when ViewModel become more complex.

In this way, ViewModel help us to organize and manage data in a strongly-typed view with more flexible way than complex objects like
models or ViewBag/ViewData objects.

Summary
In this article I try to expose the ViewModel with example. I hope you will refer this article for your need. I would like to have feedback
from my blog readers. Please post your feedback, question, or comments about this article.

MVC Data Annotations for Model Validation


Data validation is a key aspect for developing web application. In Asp.net MVC, we can easily apply validation to web application by
using

Data

Annotation

attribute

classes

to

model

class.

Data

Annotation

attribute

classes

are

present

in

System.ComponentModel.DataAnnotations namespace and are availlable to Asp.net projects like Asp.net web application & website,
Asp.net MVC, Web forms and also to Entity framework orm models.
Data Annotations help us to define the rules to the model classes or properties for data validation and displaying suitable messages to
end users.

Data Annotation Validator Attributes


1.

DataType

Specify the datatype of a property

2.

DisplayName

specify the display name for a property.

3.

DisplayFormat

specify the display format for a property like different format for Date proerty.

4.

Required

Specify a property as required.

5.

ReqularExpression

validate the value of a property by specified regular expression pattern.

6.

Range

validate the value of a property with in a specified range of values.

7.

StringLength

specify min and max length for a string property.

8.

MaxLength

specify max length for a string property.

9.

Bind

specify fields to include or exclude when adding parameter or form values to model properties.

10.

ScaffoldColumn
5

specify fields for hiding from editor forms.

Designing the model with Data Annotations


1.
2.

using System.ComponentModel;

3.

using System.ComponentModel.DataAnnotations;

4.

using System.Web.Mvc;

5.

namespace Employee.Models

6.

7.

[Bind(Exclude = "EmpId")]

8.

public class Employee

9.

10.

[ScaffoldColumn(false)]

11.

public int EmpId { get; set; }

12.
13.

[DisplayName("Employee Name")]

14.

[Required(ErrorMessage = "Employee Name is required")]

15.

[StringLength(100,MinimumLength=3)]

16.

public String EmpName { get; set; }

17.
18.

[Required(ErrorMessage = "Employee Address is required")]

19.

[StringLength(300)]

20.

public string Address { get; set; }

21.
22.

[Required(ErrorMessage = "Salary is required")]

23.

[Range(3000, 10000000,ErrorMessage = "Salary must be between 3000 and 10000000")]

24.

public int Salary{ get; set; }

25.
26.

[Required(ErrorMessage = "Please enter your email address")]

27.

[DataType(DataType.EmailAddress)]

28.

[Display(Name = "Email address")]

29.

[MaxLength(50)]

30.

[RegularExpression(@"[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}",

ErrorMessage

"Please

enter

correct

email")]
31.

public string Email { get; set; }

32.

33. }
Once we have define validation to the model by using data annotations, these are automatically used by Html Helpers in views. For
client side validation to work, please ensure that below two <SCRIPT> tag references are in the view.
1.
2.

<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>

Presenting the model in the view


1.
2.

@model Employee.Models
@{

3.

ViewBag.Title = "Employee Details";

4.

Layout = "~/Views/Shared/_Layout.cshtml";

5.

6.

@using (Html.BeginForm())

7.

8.

<div class="editor-label">

9.

@Html.LabelFor(m => m.EmpName)

10.

</div>

11.

<div class="editor-field">

12.

@Html.TextBoxFor(m => m.EmpName)

13.

@Html.ValidationMessageFor(m => m.EmpName)

14.

</div>

15.

<div class="editor-label">

16.

@Html.LabelFor(m => m.Address)

17.

</div>

18.

<div class="editor-field">

19.

@Html.TextBoxFor(m => m.Address)

20.

@Html.ValidationMessageFor(m => m.Address)

21.

</div>

22.

<div class="editor-label">

23.

@Html.LabelFor(m => m.Salary)

24.

</div>

25.

<div class="editor-field">

26.

@Html.TextBoxFor(m => m.Salary)

27.

@Html.ValidationMessageFor(m => m.Salary)

28.

</div>

29.

<div class="editor-label">

30.

@Html.LabelFor(m => m.Email)

31.

</div>

32.

<div class="editor-field">

33.

@Html.TextBoxFor(m => m.Email)

34.

@Html.ValidationMessageFor(m => m.Email)

35.

</div>

36.

<p> <input type="submit" value="Save" />

37.

</p>

38. }

Partial View in Asp.net MVC3 Razor


A partial view is like as user control in Asp.Net Web forms that is used for code re-usability. Partial views helps us to reduce code
duplication. Hence partial views are reusable views like as Header and Footer views.
We can use partial view to display blog comments, product category, social bookmarks buttons, a dynamic ticker, calendar etc. For
understanding the different rendering ways of partial view refer the article RenderPartial vs RenderAction vs Partial vs Action in MVC
Razor

Creating A Partial View


A partial view has same file extension(.cshtml) as regular view. To create a partial view do right click on shared folder (\Views\Shared) in
solution explorer and click on "Add New View" option and then give the name for partial view and also checked the Create a partial view
option as shown in fig.

Note
1.

It is best practice to create partial view in the shared folder and partial view name is preceded by "_", but it is not mandatory. The "_"
before view name specify that it is a reusable component i.e. partial view.

Rendering Partial View


A partial view is rendered by using the ViewUserControl class that is inherited/derived from the ASP.NET UserControl class. The Partial,
RenderPartial, RenderAction helper methods are used to render partial view in mvc3 razor.
1.
2.

<div> @Html.Partial("_Comments") </div>


<div> @{Html.RenderPartial("_Comments");} </div>

The main difference between above two methods is that the Partial helper method renders a partial view into a string while
RenderPartial method writes directly into the response stream instead of returning a string.
1.

<div> @{Html.RenderAction("_Category","Home");} </div>

Note
1.

Partial or RenderPartial methods are used when a model for the page is already populated with all the information. For example in a
blog to show an article comment we would like to use Partial or RenderPartial methods since an article information are already populated in the
model.

2.

RenderAction method is used when some information is need to show on multiple pages. Hence partial view should have its own model.
For example to category list of articles on each and every page we would like to use RenderAction method since the list of category is populated
by different model.

Render Partial View Using jQuery


Sometimes we need to load a partial view with in a popup on run time like as login box, then we can use jQuery to make an AJAX
request and render a Partial View into the popup. In order to load a partial view with in a div we need to do like as:
1.

<script type="text/jscript">

2.

$('#divpopup').load('/shared/_ProductCategory);

3.

</script>

Summary
I hope you will enjoy this tips and tricks while programming with Asp.Net MVC. I would like to have feedback from my blog readers. Your
valuable feedback, question, or comments about this article are always welcome.

Inline CSS and Styles with Html Helpers in MVC3 Razor


In Asp.net, we can custom the look and feel of a server controls by using CSS class,id and inline css. Similarly, we can change the style
of Html Helpers in MVC razor. I this article, I am going to explain how can change the style of a Html Helpers by using CSS.

CSS Class
1.
2.

.inputclass
{

3.

width:100px;

4.

height:25px;

5.

Apply CSS Class to Html Helpers


Suppose above css class is defined in the external style sheet. Now you want to apply this class to html helpers then we need to add
class name by using @class like as :
1.
2.

@Html.TextBox("Name", new { @class="inputclass" })


@Html.TextBoxFor(model => model.Name, new { @class="inputclass" })

Apply Inline CSS to Html Helpers


We can also add inline css to html helpers by using style like as :
1.
2.

@Html.TextBoxFor(model => model.Name, new { style="width:100px;height:25px" })


@Html.TextBox("Name", new { style="width:100px;height:25px" })

What do you think?


I hope you will enjoy these tricks while programming with MVC Razor. I would like to have feedback from my blog readers. Your valuable
feedback, question, or comments about this article are always welcome.

Enable jQuery Intellisense support to MVC3 Razor


JQuery intellisense support helps a lot while programming with jQuery. By default Visual Studio doesn't provide us the jQuery
intellisense support. We can enable the jQuery intellisense support in Visual Studio with MVC Razor by adding vsdoc.js file to your view
like as :
1.

@if (false)

2.

3.

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

4.

The above if-statement prevents the rendering of script tag into the html source code and it used only by the Visual Studio for jQuery
intellisense support. To check jQuery intellisense type the $ or $( between your $(document).ready(function() function and you can see
the intellisense as shown in fig.

Note
1.

In MVC Razor, there is no central place to add the reference to the vsdoc.js file. We need to add this code line to each every view
separately to enable the IntelliSense support for jQuery.

10

Understading Controllers and Actions in MVC Razor


Asp.net MVC Controllers are responsible for controlling the flow of the application execution. When you make a request (means request
a page) to MVC applications , a controller is responsible for returning the response to that request. A controller can have one or more
actions. A controller action can return different types of action results to a particular request.

Controller
Basically, the controller Receives input like as form values, query strings values etc. from users via the View and perform required
operations on the user's inputs with the help of Model and passing the results back to the View. Actually, controllers are classes that
have methods or action results and these actions results are called by the routing system to process a particular request.

Creating a Controller
For creating a controller, do right-click on the Controller folder in your mvc application and select the menu option Add, Controller. After
selection the Add Controller dialog is being displayed as shown in fig. Now enter your controller name before Controller word.

11

In this way you have successfully created your controller as shown in fig.

12

Controller Actions and Helper Methods


Controller actions are methods defined in the controller class and responsible to perform required operations on the user's inputs like as
form values, query strings values etc. with the help of Model and passing the results back to the View. Asp.net MVC has the following
Built-in ActionResults Type and Helper methods :

1.

ViewResult

Returns a ViewResult which renders the specified or default view by using controller View() helper method.

2.

PartialViewResult

Returns a PartialViewResult which renders the specified or default partial view (means a view without its layout) by using controller PartialView()
helper method.

3.

RedirectResult

Returns a RedirectResult which Issues an HTTP 301 or 302 redirection to a specific URL by using controller Redirect() helper method.

4.

RedirectToRouteResult

Returns a RedirectToRouteResult which Issues an HTTP 301 or 302 redirection to an action method or specific route entry by using controller
RedirectToAction(), RedirectToActionPermanent(), RedirectToRoute(), RedirectToRoutePermanent() helper methods.

5.

ContentResult

Returns a ContentResult which renders raw text like as "Hello, DotNet Tricks!" by using controller Content() helper method.

6.

JsonResult

Returns a JsonResult which serializes an object in JSON format ( like as "{ "Message": Hello, World! }") and renders it by using controller Json()
helper method.

7.

JavaScriptResult

Returns a JavaScriptResult which renders a snippet of JavaScript code like as "function hello() { alert(Hello, World!); }" by using controller
JavaScript() helper method. This is used only in AJAX scenarios.

8.

FileResult

Returns a FileResult which renders the contents of a file like as PDF, DOC, Excel etc. by using controller File() helper method.

9.

EmptyResult

Returns no result returned by an action. This has no controller helper method.

10.

HttpNotFoundResult

Returns an HttpNotFoundResult which renders a 404 HTTP Status Code response by using controller HttpNotFound() helper method.

11.

HttpUnauthorizedResult

Returns an HttpUnauthorizedResult which renders a 401 HTTP Status Code(means "not authorized") response. This has no controller helper
method. This is used for authentication (forms authentication or Windows authentication) to ask the user to log in.

13

12.

HttpStatusCodeResult

Returns an HttpStatusCodeResult which renders a specified HTTP code response. This has no controller helper method.

Difference between Asp.Net WebForm and Asp.Net MVC


Asp.net framework is a part of .net platform for building, deploying and running web applications. Now, we can develop a web
application by using Asp.Net Web Form and Asp.Net MVC. In this article, I am going to expose the main difference between Asp.Net Web
Form and Asp.Net MVC.

Difference between Asp.Net MVC and Web Forms

Removing the Web Form View Engine for better performance of Razor
View Engine
By default MVC is configured to resolve a view by searching the views that match the Web Form view engine's naming conventions first.
After that MVC begins search for the views that match the Razor view engine's naming conventions as shown in below fig.

14

So, If are not using ASPX views in your MVC applications then the checking four unused locations first for every return View() and
Html.RenderPartial is quite wasteful and time consuming. After removing Web Form engine, Razor View Engine will be almost twice as
fast with the Web Form engine.

Removing the Web Form (ASPX) view engine


Removing the Web Form view engine is easy in MVC. We can remove all the view engines and add only Razor view engine by using
Application_Start event of Global.asax.cs file like as:
1.

protected void Application_Start()

2.

3.

//Remove All Engine

4.

ViewEngines.Engines.Clear();

5.

//Add Razor Engine

6.

ViewEngines.Engines.Add(new RazorViewEngine());

7.

...

8.

After removing all the view engines and register only Razor view engine, now MVC try to resolve a view by searching the views that
match the Razor view engine's naming conventions only as shown in fig.

You can also make your custom View Engine. For help refer the article Custom Razor View Engine for C# and VB

Note
1.

After removing Web Form engine, Razor View Engine will be almost twice as fast with the Web Form engine.

2.

Use this when you are sure that you will use only Razor views. It will be helpful to you.

3.

If you are using both type of views (ASPX & Razor), don't implement this.

15

Asp.net MVC Request Life Cycle


While programming with Asp.net MVC, you should be aware of the life of an Asp.net MVC request from birth to death. In this article, I am
going to expose the Asp.net MVC Request Life cycle. There are seven main steps that happen when you make a request to an Asp.net
MVC web applications. For more details refer Detailed ASP.NET MVC Pipeline

1.

Routing

Asp.net Routing is the first step in MVC request cycle. Basically it is a pattern matching system that matches the requests URL against the
registered URL patterns in the Route Table. When a matching pattern found in the Route Table, the Routing engine forwards the request to the
corresponding IRouteHandler for that request. The default one calls the MvcHandler. The routing engine returns a 404 HTTP status code against
that request if the patterns is not found in the Route Table.

When application starts at first time, it registers one or more patterns to the Route Table to tell the routing system what to do with any requests
that match these patterns. An application has only one Route Table and this is setup in the Global.asax file of the application.
1.

public static void RegisterRoutes(RouteCollection routes)

2.
3.

{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

4.

routes.MapRoute( "Default", // Route name

5.

"{controller}/{action}/{id}", // URL with parameters

6.

new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults

7.
8.

2.

);
}

MvcHandler

The MvcHandler is responsible for initiating the real processing inside ASP.NET MVC. MVC handler implements IHttpHandler interface and further
process the request by using ProcessRequest method as shown below:
1.

protected internal virtual void ProcessRequest(HttpContextBase httpContext)

2.

3.

SecurityUtil.ProcessInApplicationTrust(delegate {

4.

IController controller;

5.

IControllerFactory factory;

6.

this.ProcessRequestInit(httpContext, out controller, out factory);

7.

try

16

8.

9.

controller.Execute(this.RequestContext);

10.

11.

finally

12.

13.

factory.ReleaseController(controller);

14.

15.

});

16. }

3.

Controller

As shown in above code, MvcHandler uses the IControllerFactory instance and tries to get a IController instance. If successful, the Execute
method is called. The IControllerFactory could be the default controller factory or a custom factory initialized at the Application_Start event,
as shown below:
1.

protected void Application_Start()

2.

3.

AreaRegistration.RegisterAllAreas();

4.

RegisterRoutes(RouteTable.Routes);

5.
6.

4.

ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());
}

Action Execution

Once the controller has been instantiated, Controller's ActionInvoker determines which specific action to invoke on the controller. Action to be
execute is chosen based on attributes ActionNameSelectorAttribute (by default method which have the same name as the action is chosen)
and ActionMethodSelectorAttribute(If more than one method found, the correct one is chosen with the help of this attribute).

5.

View Result

The action method receives user input, prepares the appropriate response data, and then executes the result by returning a result type. The
result type can be ViewResult, RedirectToRouteResult, RedirectResult, ContentResult, JsonResult, FileResult, and EmptyResult.

6.

View Engine

The first step in the execution of the View Result involves the selection of the appropriate View Engine to render the View Result. It is handled
by IViewEngine interface of the view engine. By default Asp.Net MVC uses WebForm and Razor view engines. You can also register your own
custom view engine to your Asp.Net MVC application as shown below:
1.

protected void Application_Start()

2.

3.

//Remove All View Engine including Webform and Razor

4.

ViewEngines.Engines.Clear();

5.

//Register Your Custom View Engine

6.

ViewEngines.Engines.Add(new CustomViewEngine());

7.
8.

7.

//Other code is removed for clarity


}

View

Action method may returns a text string,a binary file or a Json formatted data. The most important Action Result is the ViewResult, which renders
and returns an HTML page to the browser by using the current view engine.

Handling multiple submit buttons on the same form - MVC Razor


Sometimes you required to have more than one submit buttons on the same form in mvc razor. In that case, how will you handle the
click event of different buttons on your form?
In this article, I am going to expose the various ways for handling multiple buttons on the same form. Suppose you have a user signup
form like as below:

17

In the above fig. we have Save, Submit & Cancel buttons. Suppose on Save button click you are saving data in the tempUser table & on
Submit button you are saving data in RegUser table and more over on Cancel button click you are returning to home page. For handling
all of the above buttons click we have the three methods as mention below:

Method 1 - Submit the form for each button


In this way each submit button will post the form to server but provides the different values - Save, Submit and NULL respectively for
the commands. On the basis of command name we can implement our own logic in the controller's action method.

MultipleCommand.cshtml
1.
2.

@using (Html.BeginForm("MultipleCommand", "Home", FormMethod.Post, new { id = "submitForm" }))


{

3.

<fieldset>

4.

<legend>Registration Form</legend>

5.

<ol>

6.

<li>

7.

@Html.LabelFor(m => m.Name)

8.

@Html.TextBoxFor(m => m.Name, new { maxlength = 50 })

9.

@Html.ValidationMessageFor(m => m.Name)

10.

</li>

11.

<li>

12.

@Html.LabelFor(m => m.Address)

13.

@Html.TextAreaFor(m => m.Address, new { maxlength = 200 })

14.

@Html.ValidationMessageFor(m => m.Address)

15.

</li>

16.

<li>

17.

@Html.LabelFor(m => m.MobileNo)

18.

@Html.TextBoxFor(m => m.MobileNo, new { maxlength = 10 })

19.

@Html.ValidationMessageFor(m => m.MobileNo)

20.

</li>

21.

</ol>

22.

<button type="submit" id="btnSave" name="Command" value="Save">Save</button>

23.

<button type="submit" id="btnSubmit" name="Command" value="Submit">Submit</button>

24.

<button

type="submit"

id="btnCancel"

name="Command"

value="Cancel"

onclick="$

('#submitForm').submit()">Cancel (Server Side)</button>


25.

</fieldset>

26. }

18

Action Method in Controller

Method 2 - Introducing Second From


We can also introduce the second form for handling Cancel button click. Now, on Cancel button click we will post the second form and
will redirect to the home page.

MultipleCommand.cshtml
1.
2.

@using (Html.BeginForm("MultipleCommand", "Home", FormMethod.Post, new { id = "submitForm" }))


{

3.

<fieldset>

4.

<legend>Registration Form</legend>

5.

<ol>

6.

<li>

7.

@Html.LabelFor(m => m.Name)

8.

@Html.TextBoxFor(m => m.Name, new { maxlength = 50 })

9.

@Html.ValidationMessageFor(m => m.Name)

10.

</li>

11.

<li>

12.

@Html.LabelFor(m => m.Address)

13.

@Html.TextAreaFor(m => m.Address, new { maxlength = 200 })

14.

@Html.ValidationMessageFor(m => m.Address)

15.

</li>

16.

<li>

17.

@Html.LabelFor(m => m.MobileNo)

18.

@Html.TextBoxFor(m => m.MobileNo, new { maxlength = 10 })

19.

@Html.ValidationMessageFor(m => m.MobileNo)

20.

</li>

21.

</ol>

22.

<button type="submit" id="btnSave" name="Command" value="Save">Save</button>

23.

<button type="submit" id="btnSubmit" name="Command" value="Submit">Submit</button>

24.

<button

type="submit"

id="btnCancelSecForm"

name="Command"

value="Cancel"

onclick="$

('#cancelForm').submit()"> Cancel (Server Side by Second Form)</button>


25.

</fieldset>

26. }
27. @using (Html.BeginForm("MultipleButtonCancel", "Home", FormMethod.Post, new { id = "cancelForm" })) { }

19

Action Method in Controller

Method 3 - Introducing Client Side Script


We can also use javascript or jquery for handling Cancel button click. Now, on Cancel button click we will directly redirect to the home
page. In this way, there is no server side post back and this is the more convenient way to handle the cancel button click.

MultipleCommand.cshtml
1.

<button type="submit" id="btnSave" name="Command" value="Save">Save</button>

2.

<button type="submit" id="btnSubmit" name="Command" value="Submit">Submit</button>

3.

<button

name="ClientCancel"

type="button"

onclick="

document.location.href

('#cancelUrl').attr('href');">Cancel (Client Side)</button>


4.

<a id="cancelUrl" href="@Html.AttributeEncode(Url.Action("Index", "Home"))" style="display:none;"></a>

CRUD Operations using jQuery dialog, Entity Framework and ASP.NET


MVC
This article will demonstrate, how to create an Asp.Net MVC application with CRUD (Create, Read, Update, Delete) Operations using
jQuery and Entity Framework code first. suppose you have following data model and DataContext classes in EF.
1.

public class User

2.

3.

public int UserID { get; set; }

4.

[Required(ErrorMessage = "Please Enter Your Name")]

5.

public string Name { get; set; }

6.

[Required(ErrorMessage = "Please Enter Your Address")]

7.

public string Address { get; set; }

8.

[Required(ErrorMessage = "Please Enter Your Contact No")]

9.

public string ContactNo { get; set; }

10.

11.
12.

public class DataContext : DbContext

13.

14.

public DataContext()

15.

: base("DefaultConnection")

16.

17.
18.

19.
20.

public DbSet<User> Users { get; set; }

21.

Now migrate your data model class into SQL Server database by using EF code first database migration. For more help refer this
link Understanding Entity Framework Code First Migrations

Create Operation

20

Read Operation

Update Operation
21

Delete Operation

22

Making jQuery dialogs for CRUD Operations


1.

@model IEnumerable<jQuery_CRUD.DAL.User>

2.

@{

3.

ViewBag.Title = "Index";

4.
5.

}
<script src="~/Scripts/jquery-1.8.2.min.js"></script>

6.

<script src="~/Scripts/jquery-ui-1.8.24.min.js"></script>

7.

<link href="~/Content/themes/base/jquery-ui.css" rel="stylesheet" />

8.

<script>

9.

$(document).ready(function () {

10.

var url = "";

11.

$("#dialog-alert").dialog({

12.

autoOpen: false,

13.

resizable: false,

14.

height: 170,

15.

width: 350,

16.

show: { effect: 'drop', direction: "up" },

17.

modal: true,

18.

draggable: true,

19.

open: function (event, ui) {

20.

$(".ui-dialog-titlebar-close").hide();

21.

},

22.

buttons: {

23.

"OK": function () {

24.

$(this).dialog("close");

25.
26.

},

27.

"Cancel": function () {

28.

$(this).dialog("close");

29.

30.

31.

});

32.
33.

if ('@TempData["msg"]' != "") {

34.

$("#dialog-alert").dialog('open');

35.

36.
37.

$("#dialog-edit").dialog({

38.

title: 'Create User',

39.

autoOpen: false,

40.

resizable: false,

41.

width: 400,

42.

show: { effect: 'drop', direction: "up" },

43.

modal: true,

44.

draggable: true,

45.

open: function (event, ui) {

46.

$(".ui-dialog-titlebar-close").hide();

47.

$(this).load(url);

23

48.

49.

});

50.
51.

$("#dialog-confirm").dialog({

52.

autoOpen: false,

53.

resizable: false,

54.

height: 170,

55.

width: 350,

56.

show: { effect: 'drop', direction: "up" },

57.

modal: true,

58.

draggable: true,

59.

open: function (event, ui) {

60.

$(".ui-dialog-titlebar-close").hide();

61.
62.

},

63.

buttons: {

64.

"OK": function () {

65.

$(this).dialog("close");

66.

window.location.href = url;

67.

},

68.

"Cancel": function () {

69.

$(this).dialog("close");

70.

71.

72.

});

73.
74.

$("#dialog-detail").dialog({

75.

title: 'View User',

76.

autoOpen: false,

77.

resizable: false,

78.

width: 400,

79.

show: { effect: 'drop', direction: "up" },

80.

modal: true,

81.

draggable: true,

82.

open: function (event, ui) {

83.

$(".ui-dialog-titlebar-close").hide();

84.

$(this).load(url);

85.

},

86.

buttons: {

87.

"Close": function () {

88.

$(this).dialog("close");

89.

90.

91.

});

92.
93.

$("#lnkCreate").live("click", function (e) {

94.

//e.preventDefault(); //use this or return false

95.

url = $(this).attr('href');

96.

$("#dialog-edit").dialog('open');

97.
98.

return false;

99.

});

100.
101. $(".lnkEdit").live("click", function (e) {
102. // e.preventDefault(); use this or return false
103. url = $(this).attr('href');
104. $(".ui-dialog-title").html("Update User");

24

105. $("#dialog-edit").dialog('open');
106.
107. return false;
108. });
109.
110. $(".lnkDelete").live("click", function (e) {
111. // e.preventDefault(); use this or return false
112. url = $(this).attr('href');
113. $("#dialog-confirm").dialog('open');
114.
115. return false;
116. });
117.
118. $(".lnkDetail").live("click", function (e) {
119. // e.preventDefault(); use this or return false
120. url = $(this).attr('href');
121. $("#dialog-detail").dialog('open');
122.
123. return false;
124. });
125.
126. $("#btncancel").live("click", function (e) {
127. $("#dialog-edit").dialog("close");
128. return false;
129. });
130. });
131. </script>
132. <div id="dialog-alert" style="display: none">
133. <p>
134. @TempData["msg"]!
135. </p>
136. </div>
137.
138. <div id="dialog-confirm" style="display: none">
139. <p>
140. <span class="ui-icon ui-icon-alert" style="float: left; margin: 0 7px 20px 0;"></span>
141. Are you sure to delete?
142. </p>
143. </div>
144.
145. <div id="dialog-edit" style="display: none">
146. </div>
147. <div id="dialog-detail" style="display: none">
148. </div>
149.
150. <h2>Users List</h2>
151.
152. <p>
153. @Html.ActionLink("Create New", "Create", null, new { id = "lnkCreate" })
154. </p>
155. <table>
156. <tr>
157. <th>
158. @Html.DisplayNameFor(model => model.Name)
159. </th>
160. <th>
161. @Html.DisplayNameFor(model => model.Address)

25

162. </th>
163. <th>
164. @Html.DisplayNameFor(model => model.ContactNo)
165. </th>
166. <th></th>
167. </tr>
168.
169. @foreach (var item in Model)
170. {
171. <tr>
172. <td>
173. @Html.DisplayFor(modelItem => item.Name)
174. </td>
175. <td>
176. @Html.DisplayFor(modelItem => item.Address)
177. </td>
178. <td>
179. @Html.DisplayFor(modelItem => item.ContactNo)
180. </td>
181. <td>
182. @Html.ActionLink("Edit", "Edit", new { id = item.UserID }, new { @class = "lnkEdit" }) |
183. @Html.ActionLink("Details", "Details", new { id = item.UserID }, new { @class = "lnkDetail" }) |
184. @Html.ActionLink("Delete", "Delete", new { id = item.UserID }, new { @class = "lnkDelete" })
185. </td>
186. </tr>
187. }
188.
189. </table>

Controller for handling CRUD Operations


1.

public class UserController : Controller

2.

3.

private DataContext db = new DataContext();

4.
5.

// GET: /User/

6.

public ActionResult Index()

7.

8.

return View(db.Users.ToList());

9.

10.
11.

// GET: /User/Details/5

12.

public ActionResult Details(int id = 0)

13.

14.

User user = db.Users.Find(id);

15.

if (user == null)

16.

17.

return HttpNotFound();

18.

19.

return View(user);

20.

21.
22.

// GET: /User/Create

23.

public ActionResult Create()

24.

25.

return PartialView();

26.

26

27.
28.

// POST: /User/Create

29.

[HttpPost]

30.

[ValidateAntiForgeryToken]

31.

public ActionResult Create(User user, string Command)

32.

33.

if (ModelState.IsValid)

34.

35.

db.Users.Add(user);

36.

db.SaveChanges();

37.

TempData["Msg"] = "Data has been saved succeessfully";

38.

return RedirectToAction("Index");

39.

40.
41.

return View(user);

42.

43.
44.

// GET: /User/Edit/5

45.

public ActionResult Edit(int id = 0)

46.

47.

User user = db.Users.Find(id);

48.

if (user == null)

49.

50.

return HttpNotFound();

51.

52.

return View(user);

53.

54.
55.

// POST: /User/Edit/5

56.

[HttpPost]

57.

[ValidateAntiForgeryToken]

58.

public ActionResult Edit(User user)

59.

60.

if (ModelState.IsValid)

61.

62.

db.Entry(user).State = EntityState.Modified;

63.

db.SaveChanges();

64.

TempData["Msg"] = "Data has been updated succeessfully";

65.

return RedirectToAction("Index");

66.

67.

return View(user);

68.

69.
70.

// GET: /User/Delete/5

71.

public ActionResult Delete(int id)

72.

73.

User user = db.Users.Find(id);

74.

db.Users.Remove(user);

75.

db.SaveChanges();

76.

TempData["Msg"] = "Data has been deleted succeessfully";

77.

return RedirectToAction("Index");

78.

79.
80.

protected override void Dispose(bool disposing)

81.

82.

db.Dispose();

83.

base.Dispose(disposing);

27

84.

85.

Server Side Model Validation in MVC Razor


Server side validations are required for ensuring that the received data is correct and valid. If the received data is valid then we do the
further processing with the data. Server side validations are very important before playing with sensitive information of a user.
Server-side validation must be done whether we validate the received data on the client side. User could disable script in his browser or
do something else to bypass client-side validation. In this case server-side validation must required to protect our data from dirty input.

Server-side model validation technique


In MVC Razor, we can validate a model server side by below two ways:
1.

Explicit Model Validation

2.

Model Validation with Data Annotations

Explicit Model Validation


Suppose, you want to validate the registration process of a user for which the Registration model and view are defined as below:

RegistrationModel.cs
1.
2.

public class RegistrationModel


{

3.

public string UserName { get; set; }

4.

public string Password { get; set; }

5.

public string ConfirmPassword { get; set; }

6.

public Country Country { get; set; }

7.

public City City { get; set; }

8.

public string Address { get; set; }

9.

public string MobileNo { get; set; }

10.

public bool TermsAccepted { get; set; }

11. }
12.
13. public class Country
14. {
15.

public int? ID { get; set; }

16.

public string Name { get; set; }

17. }
18.
19. public class City
20. {
21.

public int? ID { get; set; }

22.

public string Name { get; set; }

23.

public int? Country { get; set; }

24. }

ExplicitServer.cshtml
1.
2.
3.

@model Mvc4_Client_ServerSideValidation.Models.RegistrationModel
@{
ViewBag.Title = "Explicit Server Side Validation";

28

4.

5.

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

6.

<script type="text/jscript">

7.

$(function () {

8.

$('#Country_ID').change(function () {

9.

var id = $("#Country_ID :selected").val();

10.

if (id != "") {

11.

$.ajax({

12.

type: "GET",

13.

contentType: "application/json; charset=utf-8",

14.

url: '@Url.Action("CityList", "Home")',

15.

data: { "mCountry": id },

16.

dataType: "json",

17.

success: function (data) {

18.

var items = "";

19.

$.each(data, function (i, city) {

20.

items += "<option value='" + city.Value + "'>" + city.Text + "</option>";

21.

});

22.

$('#City_ID').html(items);

23.

},

24.

error: function (result) {

25.

alert('Service call failed: ' + result.status + ' Type :' + result.statusText);

26.

27.

});

28.

29.

else

30. {
31.

var items = '<option value="">Select</option>';

32.

$('#City_ID').html(items);

33.

} });

34.

});

35. </script>
36. <h2>Explicit Server Side Validation</h2> @using (Html.BeginForm())
37. {
38.

<fieldset>

39.

<ol>

40.

<li>

41.

@Html.LabelFor(m => m.UserName)

42.

@Html.TextBoxFor(m => m.UserName, new { maxlength = 50 })

43.

@Html.ValidationMessageFor(m => m.UserName)

44.

</li>

45.

<li>

46.

@Html.LabelFor(m => m.Password)

47.

@Html.PasswordFor(m => m.Password, new { maxlength = 50, value = ViewBag.Selpwd })

48.

@Html.ValidationMessageFor(m => m.Password)

49.

</li>

50.

<li>

51.

@Html.LabelFor(m => m.ConfirmPassword)

52.

@Html.PasswordFor(m => m.ConfirmPassword, new { maxlength = 50, value = ViewBag.Selconfirmpwd })

53.

@Html.ValidationMessageFor(m => m.ConfirmPassword)

54.

</li>

55.

<li>

56.

@Html.LabelFor(m => m.Country)

57.

@Html.DropDownListFor(m => m.Country.ID, new SelectList(ViewBag.Country, "ID", "Name"), new { style =


"width:310px" })

58.

@Html.ValidationMessageFor(m => m.Country)

59.

</li>

29

60.

<li>

61.

@Html.LabelFor(m => m.City)

62.

@Html.DropDownListFor(m

=>

m.City.ID,

new

SelectList(ViewBag.City,

"ID",

"Name"),

new

style

"width:310px" })
63.

@Html.ValidationMessageFor(m => m.City)

64.

</li>

65.

<li>

66.

@Html.LabelFor(m => m.Address)

67.

@Html.TextAreaFor(m => m.Address, new { maxlength = 200 })

68.

@Html.ValidationMessageFor(m => m.Address)

69.

</li>

70.

<li>

71.

@Html.LabelFor(m => m.MobileNo)

72.

@Html.TextBoxFor(m => m.MobileNo, new { maxlength = 10 })

73.

@Html.ValidationMessageFor(m => m.MobileNo)

74.

</li>

75.

<li>

76.

@Html.CheckBoxFor(m => m.TermsAccepted) I accept the terms & conditions

77.

@Html.ValidationMessageFor(m => m.TermsAccepted)

78.

</li>

79.

</ol>

80.

<input type="submit" value="Submit" />

81.

</fieldset>

82. }
Now let's see how we validate the model explicitly?. To validate a model explicitly we need to validate received data with in the action
method like as:
1.

[HttpPost]

2.

public ActionResult ExplicitServer(RegistrationModel mRegister)

3.

4.

//Write custom logic to validate RegistrationModel

5.

if (string.IsNullOrEmpty(mRegister.UserName))

6.

7.

ModelState.AddModelError("UserName", "Please enter your name");

8.

9.

if (!string.IsNullOrEmpty(mRegister.UserName))

10.

11.

Regex emailRegex = new Regex(".+@.+\\..+");

12.

if (!emailRegex.IsMatch(mRegister.UserName))

13.

ModelState.AddModelError("UserName", "Please enter correct email address");

14.

15.

if (string.IsNullOrEmpty(mRegister.Password))

16.

17.

ModelState.AddModelError("Password", "Please enter password");

18.

1.

if (string.IsNullOrEmpty(mRegister.ConfirmPassword))

2.

3.

ModelState.AddModelError("ConfirmPassword", "Please enter confirm password");

4.

5.

if (string.IsNullOrEmpty(mRegister.ConfirmPassword) && string.IsNullOrEmpty(mRegister.ConfirmPassword))

30

6.

7.

if (mRegister.ConfirmPassword != mRegister.Password)

8.

ModelState.AddModelError("ConfirmPassword", "Confirm password doesn't match");

9.

10.

if (mRegister.Country.ID == null || mRegister.Country.ID == 0)

11.

12.

ModelState.AddModelError("Country", "Please select Country");

13.

14.

if (mRegister.City.ID == null || mRegister.City.ID == 0)

15.

16.

ModelState.AddModelError("City", "Please select City");

17.

18.

if (string.IsNullOrEmpty(mRegister.Address))

19.

20.

ModelState.AddModelError("Address", "Please enter your address");

21.

22.

if (string.IsNullOrEmpty(mRegister.MobileNo))

23.

24.

ModelState.AddModelError("MobileNo", "Please enter your mobile no");

25.

26.

if (!mRegister.TermsAccepted)

27.

28.

ModelState.AddModelError("TermsAccepted", "You must accept the terms");

29.

30.

if (ModelState.IsValid)

31.

32.

return View("Completed");

31

33.

34.

else

35.

36.

ViewBag.Selpwd = mRegister.Password;

37.

ViewBag.Selconfirmpwd = mRegister.ConfirmPassword;

38.

BindCountry();

39.
40.

if (mRegister.Country != null)

41.

BindCity(mRegister.Country.ID);

42.

else BindCity(null);

43.
44.

return View();

45.

46.

How it works...
Afer running the project and navigating to ExplicitServer page you will get the below page. When you press the submit button on this
page then it will post the data to the server and the code written with in ExplicitServer action will validate the input data. If input data is
not valid then add error to model state by using method AddModelError() as shown above.

32

When all the validation will be passed then ModelState.IsValid returns true and you will be shown Completed view as shown in fig.

Model Validation with Data Annotations


The another and best way to validate a model by using Data Annotations. Data Annotations was introduced with .Net 3.5 SP1. It has a
set of attributes and classes defined in the System.ComponentModel.DataAnnotations assembly. Data Annotations allow us to decorate
model classes with metadata. This metadata describes a set of rules that are used to validate a property. For more help refer the article
MVC Data Annotation.
In RegistrationModel.cs, I have defined one more model class RegistrationMetaModel by using data annotation and for which the view is
defined as below:

RegistrationModel.cs
1.

public class RegistrationMetaModel

2.

3.

[Required(ErrorMessage = "Please Enter Email Address")]

4.

[Display(Name = "UserName (Email Address)")]

5.

[RegularExpression(".+@.+\\..+", ErrorMessage = "Please Enter Correct Email Address")]

33

6.

public string UserName { get; set; }

7.
8.

[Required(ErrorMessage = "Please Enter Password")]

9.

[StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]

10.

[DataType(DataType.Password)]

11.

[Display(Name = "Password")]

12.

public string Password { get; set; }

13.
14.

[Required(ErrorMessage = "Please Enter Confirm Password")]

15.

[StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]

16.

[DataType(DataType.Password)]

17.

[Display(Name = "Confirm password")]

18.

[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]

19.

public string ConfirmPassword { get; set; }

20.
21.

[Display(Name = "Country")] [ValidCountryAttribute(ErrorMessage = "Please Select Country")]

22.

public Country Country { get; set; }

23.
24.

[Display(Name = "City")]

25.

[ValidCityAttribute(ErrorMessage = "Please Select City")]

26.

public City City { get; set; }

27.
28.

[Required(ErrorMessage = "Please Enter Address")]

29.

[Display(Name = "Address")]

30.

[MaxLength(200)]

31.

public string Address { get; set; }

32.

34

33.

[Required(ErrorMessage = "Please Enter Mobile No")]

34.

[Display(Name = "Mobile")]

35.

[StringLength(10, ErrorMessage = "The Mobile must contains 10 characters", MinimumLength = 10)]

36.

public string MobileNo { get; set; }

37.
38.

[MustBeTrue(ErrorMessage = "Please Accept the Terms & Conditions")]

39.

public bool TermsAccepted { get; set; }

40.

41.
42.

public class MustBeTrueAttribute : ValidationAttribute

43.

44.

public override bool IsValid(object value)

45.

46.

return value is bool && (bool)value;

47.

48.

49.

public class ValidCountryAttribute : ValidationAttribute

50.

51.

public override bool IsValid(object value)

52.

53.

if (((Country)value).ID == null || ((Country)value).ID == 0)

54.

return false;

55.

else

56.

return true;

57.

58.

59.

public class ValidCityAttribute : ValidationAttribute

35

60.

61.

public override bool IsValid(object value)

62.

63.

if (((City)value).ID == null || ((City)value).ID == 0)

64.

return false;

65.

else

66.

return true;

67.

68.

ServerMeta.cshtml
1.

@model Mvc4_Model_ServerSideValidation.Models.RegistrationMetaModel

2.

@{

3.

ViewBag.Title = "Server Side Validation by Specifying Validation Rules Using Metadata";

4.

5.

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

6.

<script type="text/jscript">

7.

$(function ()

8.

9.

$('#Country_ID').change(function ()

10.

11.

var id = $("#Country_ID :selected").val();

12.

if (id != "")

13.

14.

$.ajax({

15.

type: "GET",

16.

contentType: "application/json; charset=utf-8",

17.

url: '@Url.Action("CityList", "Home")',

18.

data: { "mCountry": id },

36

19.

dataType: "json",

20.

beforeSend: function () {

21.

},

22.

success: function (data) {

23.

var items = "";

24.

$.each(data, function (i, city) {

25.

items += "<option value='" + city.Value + "'>" + city.Text + "</option>";

26.

});

27.

$('#City_ID').html(items);

28.

},

29.

error: function (result) {

30.

alert('Service call failed: ' + result.status + ' Type :' + result.statusText);

31.

32.

});

33.

34.

else {

35.

var items = '<option value="">Select</option>';

36.

$('#City_ID').html(items);

37.

38.

});

39.

});

40.

</script>

41.

<h2>Server Side Validation by Specifying Validation Rules Using Metadata</h2>

42.

@using (Html.BeginForm())

43.

44.

<fieldset>

45.

<ol>

37

46.

<li>

47.

@Html.LabelFor(m => m.UserName)

48.

@Html.TextBoxFor(m => m.UserName, new { maxlength = 50 })

49.

@Html.ValidationMessageFor(m => m.UserName)

50.

</li>

51.

<li>

52.

@Html.LabelFor(m => m.Password)

53.

@Html.PasswordFor(m => m.Password, new { maxlength = 50, value = ViewBag.Selpwd })

54.

@Html.ValidationMessageFor(m => m.Password)

55.

</li>

56.

<li>

57.

@Html.LabelFor(m => m.ConfirmPassword)

58.

@Html.PasswordFor(m => m.ConfirmPassword, new { maxlength = 50, value = ViewBag.Selconfirmpwd })

59.

@Html.ValidationMessageFor(m => m.ConfirmPassword)

60.

</li>

61.

<li>

62.

@Html.LabelFor(m => m.Country)

63.

@Html.DropDownListFor(m => m.Country.ID, new SelectList(ViewBag.Country, "ID", "Name", ViewBag.SelCountry), new { style = "width:310px"
})

64.

@Html.ValidationMessageFor(m => m.Country)

65.

</li>

66.

<li>

67.

@Html.LabelFor(m => m.City)

68.

@Html.DropDownListFor(m => m.City.ID, new SelectList(ViewBag.City, "ID", "Name", ViewBag.SelCity), new { style = "width:310px" })

69.

@Html.ValidationMessageFor(m => m.City)

70.

</li>

71.

<li>

72.

@Html.LabelFor(m => m.Address)

38

73.

@Html.TextAreaFor(m => m.Address, new { maxlength =200 })

74.

@Html.ValidationMessageFor(m => m.Address)

75.

</li>

76.

<li>

77.

@Html.LabelFor(m => m.MobileNo)

78.

@Html.TextBoxFor(m => m.MobileNo ,new { maxlength = 10 })

79.

@Html.ValidationMessageFor(m => m.MobileNo)

80.

</li>

81.

<li>

82.

@Html.CheckBoxFor(m => m.TermsAccepted) I accept the terms & conditions

83.

@Html.ValidationMessageFor(m => m.TermsAccepted)

84.

</li>

85.

</ol>

86.

<input type="submit" value="Submit" />

87.

</fieldset>

88.

Now let's see how we validate the model using data annotation?. To validate a model explicitly we need to validate received data with in
the action method by checking ModelState.IsValid property. If it is false then error message will be shown automatically against each
propety of model as shown below in fig.
1.

[HttpPost]

2.

public ActionResult ServerMeta(RegistrationMetaModel mRegister)

3.

4.

if (ModelState.IsValid)

5.

6.

return View("Completed");

7.

8.

else

9.

10.

ViewBag.Selpwd = mRegister.Password;

39

11.

ViewBag.Selconfirmpwd = mRegister.ConfirmPassword;

12.

BindCountry();

13.
14.

if (mRegister.Country != null)

15.

BindCity(mRegister.Country.ID);

16.

else

17.

BindCity(null);

18.

return View();

19.

20.

How it works...
After running the project and navigating to Data Annotation-Server-Side page you will get the below page. When you press the submit
button on this page then it will post the data to the server and the code written with in ServerMeta action will validate the input data by
checking ModelState.IsValid property. If input data is not valid then ModelState.IsValid will return false and shown error as shown below.

40

When all the validation will be passed then ModelState.IsValid returns true and you will be shown Completed view as shown in fig.

41

Difference Between Razor View Engine and ASPX View Engine


View Engine is responsible for rendering the view into html form to the browser. By default, Asp.net MVC support Web Form(ASPX) and
Razor View Engine. There are many third party view engines (like Spark, Nhaml etc.) that are also available for Asp.net MVC. Now,
Asp.net MVC is open source and can work with other third party view engines like Spark, Nhaml. In this article, I would like to expose the
difference between Razor & Web Form View Engine.

Razor View Engine VS Web Form(ASPX) View Engine

42

How to Enable and Disable Client-Side Validation in MVC


MVC3 & MVC4 supports unobtrusive client-side validation. In which validation rules are defined using attributes added to the generated
HTML elements. These rules are interpreted by the included JavaScript library and uses the attribute values to configure the jQuery
Validation library which does the actual validation work. In this article, I would like to demonstrate various ways for enabling or disabling
the client side validation.

Enable Client-Side Validation in MVC


For enabling client side validation, we required to include the jQuery min, validate & unobtrusive scripts in our view or layout page in
the following order.
1.

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

2.

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

3.

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

The order of included files as shown above, is fixed since below javascript library depends on top javascript library.

Enabling and Disabling Client-Side Validation at Application Level


We can enable and disable the client-side validation by setting the values of ClientValidationEnabled & UnobtrusiveJavaScriptEnabled
keys true or false. This setting will be applied to application level.
1.

<appSettings>

2.

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

3.

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

4.

</appSettings>

For client-side validation, the values of above both the keys must be true. When we create new project using Visual Studio in MVC3 or
MVC4, by default the values of both the keys are set to true.
We can also enable the client-side validation programmatically. For this we need to do code with in the Application_Start() event of the
Global.asax, as shown below.
1.

protected void Application_Start()

2.

3.

//Enable or Disable Client Side Validation at Application Level

4.

HtmlHelper.ClientValidationEnabled = true;

5.

HtmlHelper.UnobtrusiveJavaScriptEnabled = true;

6.

Enabling and Disabling Client-Side Validation for Specific View


We can also enable or disable client-side validation for a specific view. For this we required to enable or disable client side validation
inside a Razor code block as shown below. This option will overrides the application level settings for that specific view.
1.

@model MvcApp.Models.Appointment

2.

@{

3.

ViewBag.Title = "Make A Booking";

4.

HtmlHelper.ClientValidationEnabled = false;

5.

6.

...

Custom Validation for Cascading Dropdownlist in MVC Razor


This article will demonstrate, how to make and validate cascading dropdown list with in Asp.Net MVC4 Razor application using custom
server-side and client-side validation. In this article, you will learn how set selected value with in Dropdown list in MVC Razor.

43

How to do it..
Follow the following steps for making and validating cascading dropdown list in mvc razor.

Step 1 : Design Model


1.

using System;

2.

using System.Collections.Generic;

3.

using System.Linq;

4.

using System.Web;

5.

using System.ComponentModel.DataAnnotations;

6.

using System.Web.Mvc;

7.

using System.Text.RegularExpressions;

8.

namespace Mvc4_Validate_CascadingDropdown.Models

9.

10. public class RegistrationModel


11. {
12.

[Required(ErrorMessage = "Please Enter Email Address")]

13.

[Display(Name = "UserName (Email Address)")]

14.

[RegularExpression(".+@.+\\..+", ErrorMessage = "Please Enter Correct Email Address")]

15.

public string UserName { get; set; }

16.

[Display(Name = "Country")]

17.

public Country Country { get; set; }

18.

[Display(Name = "City")]

19.

public City City { get; set; }

20.

[Required(ErrorMessage = "Please Enter Address")]

21.

[Display(Name = "Address")]

22.

[StringLength(200)]

23.

public string Address { get; set; }

24.

25. // IClientValidatable for client side Validation


26.

public class MustBeSelectedAttribute : ValidationAttribute, IClientValidatable

27. {
28.

public override bool IsValid(object value) {

29.

if (value == null || (int)value == 0)

30.

return false;

31.

else return true;

32. }
33. // Implement IClientValidatable for client side Validation
34. public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
35. {
36. return new ModelClientValidationRule[]
37. {
38.

new ModelClientValidationRule { ValidationType = "dropdown", ErrorMessage = this.ErrorMessage } };

39. }
40. }
41.

public class Country

42.

43. [MustBeSelectedAttribute(ErrorMessage = "Please Select Country")]


44. public int? ID { get; set; }
45.

public string Name { get; set; }

46.

47.

public class City

48. {
49. [MustBeSelectedAttribute(ErrorMessage = "Please Select City")]
50. public int? ID { get; set; }
51. public string Name { get; set; }
52.

public int? Country { get; set; }

44

53. }
54. }

Step 2: Design View based on Model


1.

@model Mvc4_Validate_CascadingDropdown.Models.RegistrationModel

2.

@{ ViewBag.Title = "Validating Cascading Dropdownlist";

3.

4.

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

5.

<script src="../../Scripts/jquery.validate.min.js" type="text/javascript"></script>

6.

<script src="../../Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>

7.

<script type="text/jscript">

8.
9.
10.

//Custom jQuery validation unobtrusive script and adapters


jQuery.validator.unobtrusive.adapters.add("dropdown", function (options) {
if (options.element.tagName.toUpperCase() == "SELECT" && options.element.type.toUpperCase() == "SELECTONE") {

11.

options.rules["required"] = true;

12.

if (options.message) {

13.

options.messages["required"] = options.message;

14.

15.

16.

});

17.

$(function () {

18.

//get city list on changing of country dropdown list

19. $('#Country_ID').change(function () {
20.

var id = $("#Country_ID :selected").val();

21.

if (id != "") {

22.

$.ajax({

23.

type: "GET",

24.

contentType: "application/json; charset=utf-8",

25.

url: '@Url.Action("CityList", "Home")',

26.

data: { "mCountry": id },

27.

dataType: "json",

28.

beforeSend: function () {

29.

//alert(id);

30. },
31.

success: function (data) {

32.

var items = "";

33.

$.each(data, function (i, city) {

34.

items += "<option value='" + city.Value + "'>" + city.Text + "</option>";

35.

});

36.

// Fill City Dropdown list

37. $('#City_ID').html(items);
38.

},

39.

error: function (result) {

40.

alert('Service call failed: ' + result.status + ' Type :' + result.statusText);

41.

42.

});

43.

44.

else {

45.

var items = '<option value="">Select</option>';

46.

$('#City_ID').html(items);

47.

48.

});

49.

});

50. </script>
51. <h2>Custom Validation for Cascading Dropdown List</h2>

45

52. @using (Html.BeginForm())


53. {
54.

<fieldset> <legend>Custom Validation for Cascading Dropdown List</legend>

55. <ol> <li>


56. @Html.LabelFor(m => m.UserName)
57. @Html.TextBoxFor(m => m.UserName, new { maxlength = 50 })
58. @Html.ValidationMessageFor(m => m.UserName) </li>
59. <li>
60. @Html.LabelFor(m => m.Country)
61. @Html.DropDownListFor(m

=>

m.Country.ID,

new

SelectList(ViewBag.Country,

"ID",

"Name",

ViewBag.SelCountry), new { style = "width:310px" })


62. @Html.ValidationMessageFor(m => m.Country.ID)
63. </li>
64. <li>
65. @Html.LabelFor(m => m.City)
66. @Html.DropDownListFor(m => m.City.ID, new SelectList(ViewBag.City, "ID", "Name", ViewBag.SelCity), new
{ style = "width:310px" })
67. @Html.ValidationMessageFor(m => m.City.ID)
68. </li>
69. <li>
70.

@Html.LabelFor(m => m.Address)

71.

@Html.TextAreaFor(m => m.Address, new { maxlength = 200 })

72. @Html.ValidationMessageFor(m => m.Address)


73. </li>
74. </ol>
75.

<input type="submit" value="Submit" />

76. </fieldset>
77.

Design Controller Based on Model & View


1.

using System;

2.

using System.Collections.Generic;

3.

using System.Linq;

4.

using System.Web;

5.

using System.Web.Mvc;

6.

using Mvc4_Validate_CascadingDropdown.Models;

7.

using System.Text.RegularExpressions;

8.

namespace Mvc4_Validate_CascadingDropdown.Controllers {

9.

public class HomeController : Controller {

10.

#region Private Methods

11.

void BindCountry() {

12.

List<Country> lstCountry = new List<Country>

13. {
14. new Country { ID = null, Name = "Select" },
15. new Country { ID = 1, Name = "India" },
16. new Country { ID = 2, Name = "USA" } };
17.

ViewBag.Country = lstCountry;

18.

19.

//for server side

20.

void BindCity(int? mCountry) {

21.

try {

22.

if (mCountry != 0)

23. {
24. //below code is only for demo, you can pick city from database
25.

int index = 1;

26.

List<City> lstCity = new List<City>{

46

27. new City { Country = 0, ID=null, Name = "Select" },


28. new City { Country = 1, ID=index++, Name = "Delhi" },
29. new City { Country = 1, ID=index++, Name = "Lucknow" },
30. new City { Country = 1, ID=index++, Name = "Noida" },
31. new City { Country = 1, ID=index++, Name = "Guragon" },
32. new City { Country = 1, ID=index++, Name = "Pune" },
33. new City { Country = 2, ID=index++, Name = "New-York" },
34. new City { Country = 2, ID=index++, Name = "California" },
35.

new City { Country = 2, ID=index++, Name = "Washington" },

36. new City { Country = 2, ID=index++, Name = "Vermont" }, };


37.

var city = from c in lstCity

38.

where c.Country == mCountry || c.Country == 0

39.

select c;

40.

ViewBag.City = city;

41.

42.

else {

43.

List<City> City = new List<City> {

44. new City { ID = null, Name = "Select" } };


45.

ViewBag.City = City;

46.

47.

48.

catch (Exception ex) {

49.

50.

51.

#endregion

52.

//for client side using jquery

53.

public JsonResult CityList(int mCountry) {

54.

try {

55.

if (mCountry != 0) {

56. //below code is only for demo, you can pick city from database
57.

int index = 1;

58.

List<City> lstCity = new List<City>{

59. new City { Country = 0, ID=null, Name = "Select" },


60. new City { Country = 1, ID=index++, Name = "Delhi" },
61. new City { Country = 1, ID=index++, Name = "Lucknow" },
62. new City { Country = 1, ID=index++, Name = "Noida" },
63. new City { Country = 1, ID=index++, Name = "Guragon" },
64. new City { Country = 1, ID=index++, Name = "Pune" },
65. new City { Country = 2, ID=index++, Name = "New-York" },
66. new City { Country = 2, ID=index++, Name = "California" },
67. new City { Country = 2, ID=index++, Name = "Washington" },
68. new City { Country = 2, ID=index++, Name = "Vermont" }, };
69.

var city = from c in lstCity

70.

where c.Country == mCountry || c.Country == 0

71.

select c;

72.

return Json(new SelectList(city.ToArray(), "ID", "Name"), JsonRequestBehavior.AllowGet);

73.

74. }
75.

catch (Exception ex) {

76.

77.

return Json(null);

78. }
79.

public ActionResult Index()

80.

81.

return View();

82.

83.

public ActionResult CustomDropdown()

47

84.

85.

BindCountry();

86.

BindCity(0);

87.

return View();

88.

89.

[HttpPost]

90.

public ActionResult CustomDropdown(RegistrationModel mRegister)

91. {
92.

if (ModelState.IsValid)

93. {
94.

return View("Completed");

95.

96.

else

97. {
98.

ViewBag.SelCountry = mRegister.Country;

99.

BindCountry();

100.

ViewBag.SelCity = mRegister.City;

101.

if (mRegister.Country != null)

102.

BindCity(mRegister.Country.ID);

103.

else

104.

BindCity(null);

105.
106.

return View();
}

107.

108.

109.

How it works..
It's time to run the project and let's see the result as shown below :

48

49

Custom Validation for Checkbox in MVC Razor


This article will demonstrate, how to check whether checkbox is checked or not in Asp.Net MVC4 Razor application using custom serverside and client-side validation.

How to do it..
Follow the following steps for validating checkbox in mvc razor.

Step 1 : Making Custom Attribute


1.

public class RegistrationModel {

2.

[Required(ErrorMessage = "Please Enter Email Address")]

3.

[RegularExpression(".+@.+\\..+", ErrorMessage = "Please Enter Correct Email Address")]

4.

public string UserName { get; set; }

5.

[Required(ErrorMessage = "Please Enter Address")]

6.

[Display(Name = "Address")]

7.

public string Address { get; set; }

8.
9.

// Applying Custom Attribute


[MustBeTrue(ErrorMessage = "Please Accept the Terms & Conditions")]

10. public bool TermsAccepted { get; set; } }


11.

//Making Custom attribute for validating checkbox

12. // IClientValidatable for client side Validation


13. public class MustBeTrueAttribute : ValidationAttribute, IClientValidatable
14. {
15. public override bool IsValid(object value)
16. {
17. return value is bool && (bool)value;
18. }
19.

// Implement IClientValidatable for client side Validation

20. public

IEnumerable<ModelClientValidationRule>

GetClientValidationRules(ModelMetadata

metadata,

ControllerContext context)
21.

22.

return new ModelClientValidationRule[] {

23.

new ModelClientValidationRule { ValidationType = "checkboxtrue", ErrorMessage = this.ErrorMessage } };

24.

25. }

Step 2: Making Custom Validation using jQuery


1.

@model Mvc4_Model_ServerSideValidation.Models.RegistrationModel

2.

@{

3.

ViewBag.Title = "Validating CheckBox";

4.

5.

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

6.

<script src="../../Scripts/jquery.validate.min.js" type="text/javascript"></script>

7.

<script src="../../Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>

8.

<script type="text/jscript">

9.

//Custom jQuery validation unobtrusive script and adapters

10. jQuery.validator.unobtrusive.adapters.add("checkboxtrue", function (options)


11. {
12. if (options.element.tagName.toUpperCase() == "INPUT" && options.element.type.toUpperCase() == "CHECKBOX")
13.

14.

options.rules["required"] = true;

15.

if (options.message) {

16.

options.messages["required"] = options.message;

17.

18.

19.

}); </script>

50

20. <h2>Custom Validation for CheckBox </h2>


21. @using (Html.BeginForm())
22. {
23.

<fieldset>

24. <legend>Custom Validation for Cascading Dropdown List</legend>


25. <ol>
26. <li>
27. @Html.LabelFor(m => m.UserName)
28. @Html.TextBoxFor(m => m.UserName, new { maxlength = 50 })
29. @Html.ValidationMessageFor(m => m.UserName)
30. </li>
31. <li>
32. @Html.LabelFor(m => m.Address)
33. @Html.TextAreaFor(m => m.Address, new { maxlength = 200 })
34. @Html.ValidationMessageFor(m => m.Address)
35. </li>
36. <li>
37. @Html.CheckBoxFor(m => m.TermsAccepted)
38. @Html.ValidationMessageFor(m => m.TermsAccepted)
39. </li>
40. </ol>
41. <input type="submit" value="Submit" />
42. </fieldset>
43.

How it works..
Now, you have applied the custom validation to the checkbox. This validation works for client-side and server side.

MVC4 Registration form with Client and Server Side Validation


Since registration form is a common form, so I prefer it to demonstrate the basic validation in mvc4. I have already explained the
validation with data annotation and how to enable client side validation in mvc razor, now my focus is to develop registration form with
client side and server side validations.

How to do it...
Step1 : Designing Model
First of all we will design the RegistrationModel with data annotation which help us to validate the input data. Since we have no
attribute to validate drop down list and checkbox, so I have created custom attributes "MustBeSelected" and "MustBeTrue for validating
dropdownlist and checkbox respectively as shown below.
1.

public class RegistrationModel

2.

3.

[Required(ErrorMessage = "Please Enter Email Address")]

4.

[Display(Name = "UserName")]

5.

[RegularExpression(".+@.+\\..+", ErrorMessage = "Please Enter Correct Email Address")]

6.

public string UserName { get; set; }

7.
8.

[Required(ErrorMessage = "Please Enter Password")]

51

9.

[StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]

10.

[DataType(DataType.Password)]

11.

[Display(Name = "Password")]

12.

public string Password { get; set; }

13.
14.

[Required(ErrorMessage = "Please Enter Confirm Password")]

15.

[StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]

16.

[DataType(DataType.Password)]

17.

[Display(Name = "Confirm password")]

18.

[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]

19.

public string ConfirmPassword { get; set; }

20.
21.

[Display(Name = "Country")]

22.

public Country Country { get; set; }

23.
24.

[Display(Name = "City")]

25.

public City City { get; set; }

26.
27.

[Required(ErrorMessage = "Please Enter Address")]

28.

[Display(Name = "Address")]

29.

[StringLength(200)]

30.

public string Address { get; set; }

31.
32.

[Required(ErrorMessage = "Please Enter Mobile No")]

33.

[Display(Name = "Mobile")]

34.

[StringLength(10, ErrorMessage = "The Mobile must contains 10 characters", MinimumLength = 10)]

35.

public string MobileNo { get; set; }

36.
37.

[MustBeTrue(ErrorMessage = "Please Accept the Terms & Conditions")]

38.

public bool TermsAccepted { get; set; }

39. }
40.
41. public

class

MustBeTrueAttribute

ValidationAttribute,

IClientValidatable

//

IClientValidatable

for

client side Validation


42. {
43.

public override bool IsValid(object value)

44.

22.

return value is bool && (bool)value;

23.

24.

// Implement IClientValidatable for client side Validation

25.

public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)

26.

27.

return new ModelClientValidationRule[] { new ModelClientValidationRule { ValidationType = "checkbox", ErrorMessage = this.ErrorMessage } };

28.

29.

30.
31.

public class MustBeSelected : ValidationAttribute, IClientValidatable // IClientValidatable for client side Validation

52

32.

33.

public override bool IsValid(object value)

34.

35.

if (value == null || (int)value == 0)

36.

return false;

37.

else

38.

return true;

39.

40.

// Implement IClientValidatable for client side Validation

41.

public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)

42.

43.

return new ModelClientValidationRule[] { new ModelClientValidationRule { ValidationType = "dropdown", ErrorMessage = this.ErrorMessage } };

44.

45.

46.
47.

public class Country

48.

49.

[MustBeSelected(ErrorMessage = "Please Select Country")]

50.

public int? ID { get; set; }

51.

public string Name { get; set; }

52.

53.
54.

public class City

55.

56.

[MustBeSelected(ErrorMessage = "Please Select City")]

57.

public int? ID { get; set; }

58.

public string Name { get; set; }

53

59.

public int? Country { get; set; }

60.

61.
62.

As shown above, for creating custom attribute you need to inherit ValidationAttribute class and IClientValidatable interface for Server
Side and Client Side Validation.

Step2 : Designing View


Now design the strongly-typed view on the basis of Registration Model. We will also register the client side validation that we have
defined in model for the dropdownlist and checkbox by using jquery as shown below.
190. @model Mvc4_RegistrationForm.Models.RegistrationModel
191. <script type="text/jscript">
192. jQuery.validator.unobtrusive.adapters.add("dropdown", function (options) {
193. if (options.element.tagName.toUpperCase() == "SELECT" && options.element.type.toUpperCase() == "SELECT-ONE") {
194. options.rules["required"] = true;
195. if (options.message) {
196. options.messages["required"] = options.message;
197. }
198. }
199. });
200.
201. jQuery.validator.unobtrusive.adapters.add("checkbox", function (options) {
202. if (options.element.tagName.toUpperCase() == "INPUT" && options.element.type.toUpperCase() == "CHECKBOX") {
203. options.rules["required"] = true;
204. if (options.message) {
205. options.messages["required"] = options.message;
206. }
207. }
208. });
209.

54

210. $(function () {
211. $('#Country_ID').change(function () {
212. var id = $("#Country_ID :selected").val();
213. if (id != "") {
214. $.ajax({
215. type: "GET",
216. contentType: "application/json; charset=utf-8",
217. url: '@Url.Action("CityList", "Home")',
218. data: { "mCountry": id },
219. dataType: "json"
220. success: function (data) {
221. var items = "";
222. $.each(data, function (i, city) {
223. items += "<option value='" + city.Value + "'>" + city.Text + "</option>";
224. });
225. $('#City_ID').html(items);
226. },
227. error: function (result) {
228. alert('Service call failed: ' + result.status + ' Type :' + result.statusText);
229. }
230. });
231. }
232. else {
233. var items = '<option value="">Select</option>';
234. $('#City_ID').html(items);
235. }
236. });

55

237.
238. });
239.
240. </script>
241.
242. @using (Html.BeginForm())
243. {
244. lt;fieldset>
245. <legend></legend>
246. <ol>
247. <li>
248. @Html.LabelFor(m => m.UserName)
249. @Html.TextBoxFor(m => m.UserName, new { maxlength = 50 })
250. @Html.ValidationMessageFor(m => m.UserName)
251. </li>
252. <li>
253. @Html.LabelFor(m => m.Password)
254. @Html.PasswordFor(m => m.Password, new { maxlength = 50, value = ViewBag.Selpwd })
255. @Html.ValidationMessageFor(m => m.Password)
256. </li>
257. <li>
258. @Html.LabelFor(m => m.ConfirmPassword)
259. @Html.PasswordFor(m => m.ConfirmPassword, new { maxlength = 50, value = ViewBag.Selconfirmpwd })
260. @Html.ValidationMessageFor(m => m.ConfirmPassword)
261. </li>
262. <li>
263. @Html.LabelFor(m => m.Country)

56

264. @Html.DropDownListFor(m => m.Country.ID, new SelectList(ViewBag.Country, "ID", "Name", ViewBag.SelCountry), new { style = "width:310px"
})
265. @Html.ValidationMessageFor(m => m.Country.ID)
266. </li>
267. lt;li>
268. @Html.LabelFor(m => m.City)
269. @Html.DropDownListFor(m => m.City.ID, new SelectList(ViewBag.City, "ID", "Name", ViewBag.SelCity), new { style = "width:310px" })
270. @Html.ValidationMessageFor(m => m.City.ID)
271. </li>
272. <li>
273. @Html.LabelFor(m => m.Address)
274. @Html.TextAreaFor(m => m.Address, new { maxlength =200 })
275. @Html.ValidationMessageFor(m => m.Address)
276. </li>
277. <li>
278. @Html.LabelFor(m => m.MobileNo)
279. @Html.TextBoxFor(m => m.MobileNo ,new { maxlength = 10 })
280. @Html.ValidationMessageFor(m => m.MobileNo)
281. </li>
282. <li>
283. @Html.CheckBoxFor(m => m.TermsAccepted) I accept the terms & conditions
284. @Html.ValidationMessageFor(m => m.TermsAccepted)
285. </li>
286. </ol>
287. <input type="submit" value="Submit" />
288. </fieldset>
289. }

57

Step3 : Designing Controller


In the controller defined the methods for binding Country and City dropdown lists. I am not showing the methods here. Also handle the
submit button event. We should also check all the validation at server side by checking IsValid property of ModelState.
86.

public ActionResult RegistrationForm()

87.

88.

BindCountry();

89.

BindCity(0);

90.

return View();

91.

92.
93.

[HttpPost]

94.

public ActionResult RegistrationForm(RegistrationModel mRegister)

95.

96.

//This will check Server Side Validation by using data annotation

97.

if (ModelState.IsValid)

98.

99.

return View("Completed");

100. }
101. else
102. {
103. // To DO: if client validation failed
104. ViewBag.Selpwd = mRegister.Password; //for setting password value
105. ViewBag.Selconfirmpwd = mRegister.ConfirmPassword;
106. ViewBag.SelCountry = mRegister.Country; // for setting selected country
107. BindCountry();
108. ViewBag.SelCity = mRegister.City;// for setting selected city
109.
110. if (mRegister.Country != null)
111. BindCity(mRegister.Country.ID);

58

112. else
113. BindCity(null);
114.
115. return View();
116. }
117. }

How it works...
Now run the code and you will find that all the validations are working well as expected.

59

Routing in Asp.Net MVC with example


Basically, Routing is a pattern matching system that monitor the incoming request and figure out what to do with that request. At
runtime, Routing engine use the Route table for matching the incoming request's URL pattern against the URL patterns defined in the
Route table. You can register one or more URL patterns to the Route table at Application_Start event. MVC5 also supports attribute
routing, to know more refer Attribute Routing in ASP.NET MVC.

How to define route...


1.

public static void RegisterRoutes(RouteCollection routes)

2.

3.

routes.MapRoute(

4.

"Default", // Route name

5.

"{controller}/{action}/{id}", // Route Pattern

6.

new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Default values for above
defined parameters

7.
8.

);
}

9.
10. protected void Application_Start()
11. {
12.

RegisterRoutes(RouteTable.Routes);

13.

//To:DO

14. }
When the routing engine finds a match in the route table for the incoming request's URL, it forwards the request to the appropriate
controller and action. If there is no match in the route table for the incoming request's URL, it returns a 404 HTTP status code.

Note
Always remember route name should be unique across the entire application. Route name cant be duplicate.

How it works...

60

In above example we have defined the Route Pattern {controller}/{action}/{id} and also provide the default values for controller,action
and id parameters. Default values means if you will not provide the values for controller or action or id defined in the pattern then these
values will be serve by the routing system.
Suppose your webapplication is running on www.example.com then the url pattren for you application will be www.example.com/
{controller}/{action}/{id}. Hence you need to provide the controller name followed by action name and id if it is required. If you will not
provide any of the value then default values of these parameters will be provided by the routing system. Here is a list of URLs that
match and don't match this route pattern.

Matching URLs

Difference between Routing and URL Rewriting


Many developers compare routing to URL rewriting that is wrong. Since both the approaches are very much different. Moreover, both
the approaches can be used to make SEO friendly URLs. Below is the main difference between these two approaches.
1.

URL rewriting is focused on mapping one URL (new url) to another URL (old url) while routing is focused on mapping a URL to a
resource.

2.

Actually, URL rewriting rewrites your old url to new one while routing never rewrite your old url to new one but it map to the original
route.

Route Constraints in Asp.Net MVC with example


In previous article, I have described the Routing and how to create route in your application. Now the time is how to control the behavior
of a route. Basically route constraints is way to put some validation around the defined route.

Creating Route Constraints


Suppose we have defined the following route in our application and you want to restrict the incoming request url with numeric id
only.Now let's see how to do it with the help of regular expression.
1.

routes.MapRoute(

2.

"Default", // Route name

3.

"{controller}/{action}/{id}", // Route Pattern

4.

new

{ controller

= "Home", action

"Index", id

UrlParameter.Optional }

// Default values for

parameters
5.

);

Restrict to numeric id only


1.

routes.MapRoute(

2.

"Default", // Route name

3.

"{controller}/{action}/{id}", // Route Pattern

4.

new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Default values for


parameters

5.
6.

new { id = @"\d+" } //Restriction for id


);

61

Now for this route, routing engine will consider only those URLs which have only numeric id like as http://example.com/Admin/Product/1
else it will considers that url is not matched with this route.

Creating Route Constraint to a Set of Specific Values


Suppose you want to restrict the user for those URLs that have controller name with H prefix and action name should be only Index or
Contact. Now let's see how to do it with the help of regular expression.
1.

routes.MapRoute(

2.

"Default", // Route name

3.

"{controller}/{action}/{id}", // Route Pattern

4.

new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Default values for


parameters

5.
6.

new { controller = "^H.*", action = "^Index$|^Contact$" } //Restriction for controller and action
);

Now for this route, routing engine will consider only those URLs which have controller name with H prefix and action name should be
only

Index

or

Contact

like

as

http://example.com/Home/Index,

http://example.com/Home/Contact

and

http://example.com,http://example.com/Home else it will considers that url is not matched with this route.
You are little bit confused why it will consider the http://example.com,http://example.com/Home URLs ?. It will also consider both these
since route constraints is checked after the provided default values for controller and action. In above route default values for controller
and action are Home and Index so these two URLs will also be matched. Like this you can restrict the user according to your need.

Note
Always put more specific route on the top order while defining the routes, since routing system check the incoming URL pattern form
the top and as it get the matched route it will consider that. It will not checked further routes after matching pattern.

Resolve Ambiguous Controller Error by routes


In previous articles, I have described the Routing System and how to create Route Constraints in your application. Now the time is to
resolve the common error "multiple matching controllers were found" raised by the routing system when your application have more
than one controller with the same name in different namespace.

Raised Error
Suppose you have HomeController with in two namespaces : Mvc4_RouteConstraints & Mvc4_Route. You have also registered a Default
route for your application as shown below.
1.

routes.MapRoute(

2.

"Default", // Route name

3.

"{controller}/{action}/{id}", // Route Pattern

4.

new

{ controller

= "Home", action

"Index", id

UrlParameter.Optional }

// Default values for

parameters
5.

);

So when you will run your application then it will throw the error that the request for 'Home' has found the more than one matching
controllers as shown below fig.

62

How to resolve it...


We can resolve this error by setting priority of the controllers. Suppose in the application HomeCOntroller defined in the
Mvc4_RouteConstraints namespace has high priority than Mvc4_Route namespace controller. Let's do it.
1.

routes.MapRoute(

2.

"Default", // Route name

3.

"{controller}/{action}/{id}", // Route Pattern

4.

new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Default values for


parameters

5.
6.

new[] { "Mvc4_RouteConstraints"});
);

In above code, I have added the Mvc4_RouteConstraints namespace as a string which told the MVC framework to look in the
Mvc4_RouteConstraints namespace before looking anywhere else. Now, when you run your application, it will run successfully without
any error.
If you want to give preference to a controller with in one namespace and all other controllers should also resolved in another
namespace, you need to defined multiple routes as shown below.
1.

routes.MapRoute(

2.

"Default", // Route name

3.

"{controller}/{action}/{id}", // Route Pattern

4.

new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Default values for


parameters

5.
6.

new[] { "Mvc4_RouteConstraints"});
);

7.
8.

routes.MapRoute(

9.

"Default", // Route name

10.

"{controller}/{action}/{id}", // Route Pattern

11.

new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Default values for


parameters

12.

new[] { "Mvc4_Route"});

13. );

63

MVC Areas with example


Areas was introduced in Asp.net MVC2 which allow us to organize models, views, and controllers into separate functional sections of the
application, such as administration, billing, customer support, and so on. This is very helpful in a large web application, where all the
controllers, views, and models have a single set of folders and that become difficult to manage.
Each MVC area has its own folder structure which allow us to keep separate controllers, views, and models. This also helps the multiple
developers to work on the same web application without interfere to one another.

Registering Area
Before working with area, make sure you have registered your area with in the Application_Start method in Global.asax as shown below.
1.

protected void Application_Start()

2.

3.

//Register all application Areas

4.

AreaRegistration.RegisterAllAreas();

5.
6.

WebApiConfig.Register(GlobalConfiguration.Configuration);

7.

FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

8.

RouteConfig.RegisterRoutes(RouteTable.Routes);

9.

BundleConfig.RegisterBundles(BundleTable.Bundles);

10.
11. }

Note
Always remember the order of registering the Areas must be on top, so that all of the settings, filters and routes registered for the
applications will also apply on the Areas.

Creating Area
To add an area to an MVC application, right-click on the project item with in the Solution Explorer window and select Add>Area option as
shown below.

Now a new prompt will appear, with in give the name of the area like "Department" and click Add button. Now the new Department
Area has been cretaed as shown in below fig.

64

Now you have seen DepartmentAreaRegistration class has been created and in the RegisterArea method, a route for the area has been
defined as shown below.
1.

using System.Web.Mvc;

2.

namespace Mvc4Area.Areas.Department

3.

4.

public class DepartmentAreaRegistration : AreaRegistration

5.

6.

public override string AreaName

7.

8.

get

9.

10.

return "Department";

11.

12.

13.
14.

public override void RegisterArea(AreaRegistrationContext context)

15.

16.

context.MapRoute(

17.

"Department_default",

18.

"Department/{controller}/{action}/{id}",

19.

new { action = "Index", id = UrlParameter.Optional }

20.

);

21.

22.

23. }

Populating Area
Now you can create controllers, views, and models in the Department area like as below.

65

Asp.net MVC 4 performance optimization with bundling and minification


MVC4 and .Net Framework 4.5 offer bundling and minification techniques that reduce the number of request to the server and size of
requested CSS and JavaScript library, which improve page loading time.
System.Web.Optimization class offers the bundling and minification techniques that is exist with in the Microsoft.Web.Optimization dll.
Using this dll you can also use this technique with Asp.Net MVC3 and .Net Framework 4.0. Refer the article Bundling and minification in
MVC3 and Asp.Net 4.0 for more help.

What is Bundle?
A bundle is a logical group of files that is loaded with a single HTTP request. You can create style and script bundle for css and
javascripts respectively by calling BundleCollection class Add() method with in BundleConfig.cs file.

Creating Style Bundle


1.

bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.min.css",

2.

"~/Content/mystyle.min.css"));

Creating Script Bundle


1.

bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(

2.

"~/Scripts/jquery-1.7.1.min.js",

3.

"~/Scripts/jquery.validate.min.js",

4.

"~/Scripts/jquery.validate.unobtrusive.min.js"));

Above both the bundles are defined with in BundleConfig class as shown below:
1.

public class BundleConfig

2.

3.

public static void RegisterBundles(BundleCollection bundles)

4.

5.

bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.min.css",

6.

"~/Content/mystyle.min.css"));

7.
8.

bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(

9.

"~/Scripts/jquery-1.7.1.min.js",

10.

"~/Scripts/jquery.validate.min.js",

11.

"~/Scripts/jquery.validate.unobtrusive.min.js"));

12.

13. }

Creating Bundle using the "*" Wildcard Character


"*" wildcard character is used to combines the files that are in the same directory and have same prefix or suffix with its name. Suppose
you want to add all the scripts files that exist with in "~/Script" directory and have "jquery" as prefix then you can create bundle like
below:

66

1.

bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include("~/Scripts/jquery*.js"));

You can also add all the css that exist with in "~/Content" directory and have ".css" extension(as suffix) like below:
1.

bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/*.css"));

Registering Bundle
All bundles are registered with in Application_Start event of Global.asax file of you web application.
1.

protected void Application_Start()

2.

3.

BundleConfig.RegisterBundles(BundleTable.Bundles);

4.
5.

// Other Code is removed for clarity


}

Minification
Minification is technique for removing unnecessary characters (like white space, newline, tab) and comments from the JavaScript and
CSS files to reduce the size which cause improved load times of a webpage. There are so many tools for minifying the js and css files.
JSMin and YUI Compressor are two most popular tools for minifying the js and css files.
You can also add WebEssentials2012.vsix extension to your VS2012 for minifying the js and css files. This is a great extension for
VS2012 for playing with js and css.

Minification with VS2012 and WebEssentials 2012 extension


I would like to share how can you make minify version of you css file using WebEssentials extension and VS2012. This minify version will
updated automatically if you will make change in original css file.

67

Performance Optimization with Bundling and Minification


I have done a performance test on a MVC4 application with & without bundling and minification. I have noticed the below result.

Without Bundling and Minification


I have the below css and js files on the layout page and run the application in chrome browser and test no of request and loding time
using chrome developer tools as shown below.
1.

<link href="~/Content/Site.css" rel="stylesheet"/>

2.

<link href="~/Content/MyStyle.css" rel="stylesheet"/>

3.

<script src="~/Scripts/jquery-1.7.1.js"></script>

4.

<script src="~/Scripts/jquery-ui-1.8.20.js"></script>

5.

<script src="~/Scripts/jquery.validate.js"></script>

6.

<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>

68

In this test, I have seen, There are 7 request, total data size is 3.96KB and loading time is approximate 296ms.

With Bundling and Minification


I have run the above application with Bundling and Minification of css and js files and test no of request and loding time using chrome
developer tools as shown below.
1.

@Styles.Render("~/Content/css")

2.

@Scripts.Render("~/bundles/jquery")

In this test, I have seen, There are only 3 request, total data size is 2.67KB and loading time is approximate 80ms. In this way by using
bundling and minification you have reduced the total no of request, size and loading time.

Enabling Bundling and Minification in debug mode


Bundling and minification doesn't work in debug mode. So to enable this featues you need to add below line of code with in
Application_Start event of Global.asax.
1.

protected void Application_Start()

2.

3.

BundleConfig.RegisterBundles(BundleTable.Bundles);

4.

//Enabling Bundling and Minification

5.

BundleTable.EnableOptimizations = true;

6.
7.

// Other Code is removed for clarity


}

Busting Browser's Cache by Bundling


69

As you know browsers cache resources based on URLs. When a web page requests a resource, the browser first checks its cache to see
if there is a resource with the matched URL. If yes, then it simply uses the cached copy instead of fetching a new one from server.
Hence whenever you change the content of css and js files will not reflect on the browser. For this you need to force the browser for
refreshing/reloading.
But bundles automatically takes care of this problem by adding a hashcode to each bundle as a query parameter to the URL as shown
below. Whenever you change the content of css and js files then a new has code will be generated and rendered to the page
automatically. In this way, the browser will see a different url and will fetch the new copy of css and js.

70

How to see view with in Areas


Now, let's see how to view your Index view with the help of Page Inspector as shown below.

Bundling and minification in MVC3 and Asp.Net 4.0


You can also implement bundling and minification techniques with in Asp.net MVC3 and Asp.net 4.0. In previous article Asp.net MVC 4
performance optimization with bundling and minification, I have explained both the techniques, Now I would like to share you could you
achieve this functionality with .Net Framework 4.0.

How to do it in MVC3 and Asp.Net 4.0


Adding Refrences
First of all add the references of System.Web.Optimization.dll and WebGrease.dll to your MVC3 and Asp.Net 4.0 projects as shown
below. You can download the dll by using download link.

71

Creating Bundle
Now create the bundle for your css and js files with in the Global.asax file as shown below.
1.

public static void RegisterBundles(BundleCollection bundles)

2.

3.

//Creating bundle for your css files

4.

bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/mystyle.min.css",

5.

"~/Content/site.min.css"));

6.

//Creating bundle for your js files

7.

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(

8.

"~/Scripts/jquery-1.5.1.min.js",

9.

"~/Scripts/jquery.validate.min.js",

10.

"~/Scripts/jquery.validate.unobtrusive.min.js"));

11. }
Here, I have created the bundle of all required css and js files. You can also add your own css and js files with complete path using
Include method.

Registering Bundle
You need to register above created bundles with in Application_Start event of Global.asax like as
1.

protected void Application_Start()

2.

3.

RegisterBundles(BundleTable.Bundles);

4.
5.

// Other Code is removed for clarity


}

Adding Bundles to Layout Page in MVC3


Now you can add the above created style and script bundles to the Layout page or where you want to use as shown below:
1.

@System.Web.Optimization.Styles.Render("~/Content/css")

2.

@System.Web.Optimization.Scripts.Render("~/bundles/jquery")

72

Adding Bundles to Master Page in Asp.Net 4.0


Now you can add the above created style and script bundles to the Master page or where you want to use as shown below:

In

1.

<%: Styles.Render("~/Content/css") %>

2.

<%: Scripts.Render("~/bundles/jquery")%>

Asp.Net

4.0

you

also

required

to

add

System.Web.Optimization

namespace

and

assembly

Microsoft.AspNet.Web.Optimization.WebForms reference to the web.config file of your Asp.Net 4.0 project as shown below:
1.

<system.web>

2.

<compilation debug="true" targetFramework="4.0" />

3.

<pages>

4.

<namespaces>

5.

<add namespace="System.Web.Optimization" />

6.

</namespaces>

7.

<controls>

8.

<add

assembly="Microsoft.AspNet.Web.Optimization.WebForms"

namespace="Microsoft.AspNet.Web.Optimization.WebForms" tagPrefix="webopt" />


9.

</controls>

10.

</pages>

11. <!-- Other Code is removed for clarity -->


12. </sytem.web >
You need not to do any changes in web.config file of your MVC3 project.

Enabling Bundling and Minification in debug mode


Bundling and minification doesn't work in debug mode. So to enable this features you need to add below line of code with in
Application_Start event of Global.asax.
1.

protected void Application_Start()

2.

3.

BundleConfig.RegisterBundles(BundleTable.Bundles);

4.

//Enabling Bundling and Minification

5.

BundleTable.EnableOptimizations = true;

6.

// Other Code is removed for clarity

7.

How it works..
Now run your application and you will see that all the css and js files are converted to single css and js file as shown below:

Minification
Minification is technique for removing unnecessary characters (like white space, newline, tab) and comments from the JavaScript and
CSS files to reduce the size which cause improved load times of a webpage. There are so many tools for minifying the js and css files.
JSMin and YUI Compressor are two most popular tools for minifying the js and css files. Use these tools for minifiying your css and js files
and use in your application with ".min" suffix. So that you can easily identified that this is a minimize version of your css or js file.

Understanding Caching in Asp.Net MVC with example


Caching is a most important aspect of high-performance web application. Caching provides a way of storing frequently accessed data
and reusing that data. Practically, this is an effective way for improving web applications performance.

Advantage of Caching
73

1.

Reduce hosting server round-trips

When content is cached at the client or in proxies, it cause minimum request to server.

2.

Reduce database server round-trips

When content is cached at the web server, it can eliminate the database request.

3.

Reduce network traffic

When content is cached at the client side, it it also reduce the network traffic.

4.

Avoid time-consumption for regenerating reusable content

When reusable content is cached, it avoid the time consumption for regenerating reusable content.

5.

Improve performance

Since cached content reduce round-trips, network traffic and avoid time consumption for regenerating reusable content which cause a boost in
the performance.

Key points about Caching


1.

Use caching for contents that are accessed frequently.

2.

Avoid caching for contents that are unique per user.

3.

Avoid caching for contents that are accessed infrequently/rarely.

4.

Use the VaryByCustom function to cache multiple versions of a page based on customization aspects of the request such as cookies,
role, theme, browser, and so on.

5.

For efficient caching use 64-bit version of Windows Server and SQL Server.

6.

For database caching make sure your database server has sufficient RAM otherwise, it may degrade the performance.

7.

For caching of dynamic contents that change frequently, define a short cacheexpiration time rather than disabling caching.

Output Cache Filter


The OutputCache filter allow you to cache the data that is output of an action method. By default, this attribute filter cache the data till
60 seconds. After 60 sec, Asp.Net MVC will execute the action method again and cache the output again.

Enabling Output Caching


You can enable the output caching for an action method or controller by adding an [OutputCache] attribute as shown below:
1.

[OutputCache(Duration=20, VaryByParam="none")]

2.

public ActionResult Index()

3.

4.

ViewBag.Message = DateTime.Now.ToString();

5.
6.

return View();
}

The output of the Index() action method will be cached for 20 seconds. If you will not defined the duration, it will cached it for by default
cache duration 60 sec. You can see the cache effect by applying the break point on index method as shown below.

OutputCache Filter Parameter


74

Output Caching Location


By default, content is cached in three locations: the web server, any proxy servers, and the user's browser. You can control the content's
cached location by changing the location parameter of the OutputCache attribute to any of the following values: Any,
Client,Downstream, Server, None, or ServerAndClient.
By default, the location parameter has the value Any which is appropriate for most the scenarios. But some times there are scenarios
when you required more control over the cached data.
Suppose you want to cache the logged in use information then you should cached the data on client browser since this data is specific
to a user. If you will cached this data on the server, all the user will see the same information that is wrong.
You should cache the data on the server which is common to all the users and is sensitive.

Configure Cache Location


For configuring the cache location, you need to add the System.Web.UI namespace on your controller. You can cached the user's
personal information in his browser like as below.
1.

[OutputCache(Duration

7200,

Location

OutputCacheLocation.Client,

VaryByParam

"none",

NoStore

true)]
2.

public ActionResult Index()

3.

4.

ViewBag.Message = "Welcome : " + User.Identity.Name;

5.
6.

return View();
}

Understanding Model View Controller in Asp.Net MVC


The Model-View-Controller (MVC) pattern was introduced in 1970s. It is a software design pattern that splits an application into three
main aspects : Model, View and Controller. Moreover, MVC pattern forces a separation of concerns within an application for example,
separating data access logic and business logic from the UI.

Model - The "M" in "MVC"


The Model represents a set of classes that describes the business logic and data. It also defines business rules for how the data can be
changed and manipulated.
Moreover, models in Asp.Net MVC, handles the Data Access Layer by using ORM tools like Entity Framework or NHibernate etc. By
default, models are stored in the Models folder of the project.

75

The Model can be broken down into several different layers as given below:
1.

Objects or ViewModel Layer

This layer contains simple objects or complex objects which are used to specify strongly-typed view. These objects are used to pass data from
controller to strongly-typed view and vice versa. The classes for these objects can have specific validation rules which are defined by using data
annotations. Typically, these classes have those properties which you want to display on corresponding view/page.

2.

Data Access Layer

This layer provides objects to access and manipulate the database of your application. Typically, this layer is made by using ORM tools like Entity
Framework or NHibernate etc.

3.

Business Layer

This layer helps you to implement your business logic and validations for your application. This layer make use of Data Access Layer for
persisting data into database. Also, this layer is directly invoked by the Controller to do processing on input data and sent back to view.

View - The "V" in "MVC"


The View is responsible for transforming a model or models into UI. The Model is responsible for providing all the required business logic
and validation to the view. The view is only responsible for displaying the data, that is received from the controller as the result.
Moreover, views in Asp.Net MVC, handles the UI presentation of data as the result of a request received by a controller. By default,
views are stored in the Views folder of the project.

76

Controller - The "C" in "MVC"


The Controller is responsible for controlling the application logic and acts as the coordinator between the View and the Model. The
Controller receive input from users via the View, then process the user's data with the help of Model and passing the results back to the
View.
Moreover, controllers in Asp.Net MVC, respond to HTTP requests and determine the action to take based upon the content of the
incoming request. By default, controllers are stored in the Controllers folder of the project.

Controlling Session Behavior in Asp.Net MVC4


By default, Asp.Net MVC support session state. Session is used to store data values across requests. Whether you store some data
values with in the session or not Asp.Net MVC must manage the session state for all the controllers in your application that is time
consuming. Since, session is stored on server side and consumes server memory, hence it also affect your application performance.

Session Less Controller


If some of the controllers of your Asp.Net MVC application are not using session state features, you can disable session for those
controller and can gain slight performance improvement of your application. You can simplify session state for your application by using
available options for session state.
In Asp.Net MVC4, SessionState attribute provides you more control over the behavior of session-state by specifying the value of
SessionStateBehavior enumeration as shown below:

SessionStateBehavior Enumeration's Value

Full read-write session state behavior is enabled.

77

In Asp.Net MVC, TempData use session state for storing the data values across requests. Hence, when you will disabled the session
state for the controller, it will throw the exception as shown below:

Securing Asp.Net MVC Application by using Authorize Attribute


Authorization is the process of determining the rights of an authenticated user for accessing the application's resources. The Asp.Net
MVC Framework has a AuthorizeAttribute filter for filtering the authorized user to access a resource. Refer this article for Custom
Authentication and Authorization in ASP.NET MVC

Authorize Attribute Properties

Filtering Users by Users Property


Suppose you want to allow the access of AdminProfile to only shailendra and mohan users then you can specify the authorize users list
to Users property as shown below.
1.

[Authorize(Users = "shailendra,mohan")]

2.

public ActionResult AdminProfile()

3.

4.
5.

return View();
}

Filtering Users by Roles Property


Suppose you want to allow the access of AdminProfile action to only Admin and SubAdmin roles then you can specify the authorize roles
list to Users property as shown below.
1.

[Authorize(Roles = "Admin,SubAdmin")]

2.

public ActionResult AdminProfile()

3.

4.
5.

return View();
}

78

File upload with strongly typed view and model validation


Many times, we required to upload file with strongly-typed view and also apply validation on uploading file using data annotation
validators. In this article, I would like to share, how can we upload a file and validate that file, firstly at client side and after that at
server side.

How to do it..
Step 1 : Designing model with data annotation validation
1.

public class RegistrationModel

2.

3.

[Required(ErrorMessage = "Please Enter Your Full Name")]

4.

[Display(Name = "Full Name")]

5.

public string Name { get; set; }

6.
7.

[Required(ErrorMessage = "Please Enter Address")]

8.

[Display(Name = "Address")]

9.

[MaxLength(200)]

10.

public string Address { get; set; }

11.
12.

[Required(ErrorMessage = "Please Upload File")]

13.

[Display(Name = "Upload File")]

14.

[ValidateFile]

15.

public HttpPostedFileBase file { get; set; }

16. }
17.
18. //Customized data annotation validator for uploading file
19. public class ValidateFileAttribute : ValidationAttribute
20. {
21.

public override bool IsValid(object value)

22.

23.

int MaxContentLength = 1024 * 1024 * 3; //3 MB

24.

string[] AllowedFileExtensions = new string[] { ".jpg", ".gif", ".png", ".pdf" };

25.
26.

var file = value as HttpPostedFileBase;

27.
28.

if (file == null)

29.

return false;

30.

else if (!AllowedFileExtensions.Contains(file.FileName.Substring(file.FileName.LastIndexOf('.'))))

31.

32.

ErrorMessage = "Please upload Your Photo of type: " + string.Join(", ", AllowedFileExtensions);

33.

return false;

34.

35.

else if (file.ContentLength > MaxContentLength)

36.

37.

ErrorMessage

"Your

Photo

is

too

large,

maximum

allowed

size

is

"

(MaxContentLength

1024).ToString() + "MB";
38.

return false;

39.

40.

else

41.

return true;

42.

43. }

Step 2 : Designing view based on model


1.

<h2>File upload with model validation</h2>

79

2.

<h3 style="color: green">@ViewBag.Message</h3>

3.
4.

@using (Html.BeginForm("FileUpload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))

5.

6.

<fieldset>

7.

<legend></legend>

8.

<ol>

9.

<li>

10.

@Html.LabelFor(m => m.Name)

11.

@Html.TextBoxFor(m => m.Name, new { maxlength = 50 })

12.

@Html.ValidationMessageFor(m => m.Name)

13.

</li>

14.

<li>

15.

@Html.LabelFor(m => m.Address)

16.

@Html.TextAreaFor(m => m.Address, new { maxlength = 200 })

17.

@Html.ValidationMessageFor(m => m.Address)

18.

</li>

19.

<li class="lifile">

20.

@Html.TextBoxFor(m => m.file, new { type = "file" })

21.

@Html.ValidationMessageFor(m => m.file)

22.

</li>

23.

</ol>

24.

<input type="submit" value="Submit" />

25.

</fieldset>

26. }

Step 3 : Applying jQuery validation for validating file


1.

<script type="text/jscript">

2.

//get file size

3.

function GetFileSize(fileid) {

4.

try {

5.

var fileSize = 0;

6.

//for IE

7.

if ($.browser.msie) {

8.

//before making an object of ActiveXObject,

9.

//please make sure ActiveX is enabled in your IE browser

10.

var objFSO = new ActiveXObject("Scripting.FileSystemObject"); var filePath = $("#" + fileid)[0].value;

11.

var objFile = objFSO.getFile(filePath);

12.

var fileSize = objFile.size; //size in kb

13.

fileSize = fileSize / 1048576; //size in mb

14.

15.

//for FF, Safari, Opeara and Others

16.

else {

17.

fileSize = $("#" + fileid)[0].files[0].size //size in kb

18.

fileSize = fileSize / 1048576; //size in mb

19.

20.
21.

return fileSize;

22.

23.

catch (e) {

24.

alert("Error is :" + e);

25.

26. }
27.
28. //get file path from client system
29. function getNameFromPath(strFilepath) {

80

30.

var objRE = new RegExp(/([^\/\\]+)$/);

31.

var strName = objRE.exec(strFilepath);

32.
33.

if (strName == null) {

34.

return null;

35.

36.

else {

37.

return strName[0];

38.

39. }
40.
41. $(function () {
42.

$("#file").change(function () {

43.

var file = getNameFromPath($(this).val());

44.

if (file != null) {

45.

var extension = file.substr((file.lastIndexOf('.') + 1));

46.

switch (extension) {

47.

case 'jpg':

48.

case 'png':

49.

case 'gif':

50.

case 'pdf':

51.

flag = true;

52.

break;

53.

default:

54.

flag = false;

55.

56.

57.

if (flag == false) {

58.

$(".lifile > span").text("You can upload only jpg,png,gif,pdf extension file");

59.

return false;

60.

61.

else {

62.

var size = GetFileSize('file');

63.

if (size > 3) {

64.

$(".lifile > span").text("You can upload file up to 3 MB");

65.

66.

else {

67.

$(".lifile > span").text("");

68.

69.

70.

});

71. });
72. </script>

Step 4 : Designing Controller


1.

public ActionResult FileUpload()

2.

3.
4.

return View();
}

5.
6.

[HttpPost]

7.

public ActionResult FileUpload(RegistrationModel mRegister)

8.

9.

//Check server side validation using data annotation

10.

if (ModelState.IsValid)

11.

81

12.

//TO:DO

13.

var fileName = Path.GetFileName(mRegister.file.FileName);

14.

var path = Path.Combine(Server.MapPath("~/Content/Upload"), fileName);

15.

mRegister.file.SaveAs(path);

16.

ViewBag.Message = "File has been uploaded successfully";

17.

ModelState.Clear();

18.

19.

return View();

20. }

How it works...

WebGrid with custom paging and sorting in MVC4


WebGrid is simply used to display the data with paging and sorting. If you want to control the default behavior of the webgrid, you need
do it manually. In this article, I would like to explore how can we do custom paging and sorting. In this article I have used the MVC4 and
Entity Framework 5.0 with VS2012. Refer the article Enhancing WebGrid with ajax in MVC4 for more help.

82

How to do it...
The Model
First of all design the customer model using Entity Framework database first approach as show below;

Now develop the logic for querying the data from customer table and also develop the logic for custom paging and sorting.
1.

public class ModelServices : IDisposable

2.

3.

private readonly TestDBEntities entities = new TestDBEntities();

4.
5.

//For Custom Paging

6.

public IEnumerable<Customer> GetCustomerPage(int pageNumber, int pageSize, string sort, bool Dir)

7.

8.

if (pageNumber < 1)

9.

pageNumber = 1;

10.
11.

if (sort == "name")

12.

return entities.Customers.OrderByWithDirection(x => x.Name, Dir)

13.

.Skip((pageNumber - 1) * pageSize)

14.

.Take(pageSize)

15.

.ToList();

16.

else if (sort == "address")

17.

return entities.Customers.OrderByWithDirection(x => x.Address, Dir)

18.

.Skip((pageNumber - 1) * pageSize)

19.

.Take(pageSize)

20.

.ToList();

21.

else if (sort == "contactno")

22.

return entities.Customers.OrderByWithDirection(x => x.ContactNo, Dir)

23.

.Skip((pageNumber - 1) * pageSize)

24.

.Take(pageSize)

25.

.ToList();

26.

else

27.

return entities.Customers.OrderByWithDirection(x => x.CustID, Dir)

28.

.Skip((pageNumber - 1) * pageSize)

29.

.Take(pageSize)

30.

.ToList();

31.

32.

public int CountCustomer()

33.

34.

return entities.Customers.Count();

35.

36.
37.

public void Dispose()

38.

39.

entities.Dispose();

40.

41. }

83

42.
43. public class PagedCustomerModel
44. {
45.

public int TotalRows { get; set; }

46.

public IEnumerable<Customer> Customer { get; set; }

47.

public int PageSize { get; set; }

48. }

Extension Method for OrderByWithDirection


1.

public static class SortExtension

2.

3.

public static IOrderedEnumerable OrderByWithDirection

4.

(this IEnumerable source,Func keySelector,bool descending)

5.

6.

return descending ? source.OrderByDescending(keySelector)

7.

: source.OrderBy(keySelector);

8.

9.
10.

public static IOrderedQueryable OrderByWithDirection

11.

(this IQueryable source,Expression<func> keySelector,bool descending)</func

12. <func {</func


13. <func return descending ? source.OrderByDescending(keySelector)</func
14. <func : source.OrderBy(keySelector);</func
15. <func }</func
16. <func}</func
17. <func</func

The View
Now design the view based on the above developed model as show below
1.

@model Mvc4_CustomWebGrid.Models.PagedCustomerModel

2.

@{

3.

ViewBag.Title = "WebGrid with Custom Paging, Sorting";

4.

WebGrid grid = new WebGrid(rowsPerPage: Model.PageSize);

5.

grid.Bind(Model.Customer,

6.

autoSortAndPage: false,

7.
8.

rowCount: Model.TotalRows);
}

9.
10. @grid.GetHtml(
11.

fillEmptyRows: false,

12.

alternatingRowStyle: "alternate-row",

13.

headerStyle: "grid-header",

14.

footerStyle: "grid-footer",

15.

mode: WebGridPagerModes.All,

16.

firstText: "<< First",

17.

previousText: "< Prev",

18.

nextText: "Next >",

19.

lastText: "Last >>",

20.

columns: new[] {

21.

grid.Column("CustID",header: "ID", canSort: false),

22.

grid.Column("Name"),

23.

grid.Column("Address"),

24.

grid.Column("ContactNo",header: "Contact No")

25.

26. )

84

The Controller
Now, let's see how to write the code for implementing the webgrid functionality using model class and methods.
1.

public class HomeController : Controller

2.

3.

ModelServices mobjModel = new ModelServices();

4.
5.

public ActionResult WebGridCustomPaging(int page = 1, string sort = "custid", string sortDir = "ASC")

6.

7.

const int pageSize = 5;

8.

var totalRows = mobjModel.CountCustomer();

9.
10.

bool Dir = sortDir.Equals("desc", StringComparison.CurrentCultureIgnoreCase) ? true : false;

11.
12.

var customer = mobjModel.GetCustomerPage(page, pageSize, sort, Dir);

13.

var data = new PagedCustomerModel()

14.

15.

TotalRows = totalRows,

16.

PageSize = pageSize,

17.

Customer = customer

18.

};

19.

return View(data);

20.

21. }

How it works..

85

86

Enhancing WebGrid with ajax in MVC4


In previous posts I have explained how can we do custom paging and sorting in WebGrid. You can also enhance WebGrid with ajax for
asynchronous update of webpage.For making an Ajax WebGrid, we have to set the value of ajaxUpdateContainerId parameter, in which
we want to generate the WebGrid. Usually the container should be a DIV as show below:
1.

WebGrid grid = new WebGrid(

2.

// Other code is removed for clarity

3.

ajaxUpdateContainerId: "container-grid"

4.

);

5.
6.

<div id="container-grid">@grid.GetHtml(

7.

fillEmptyRows: true,

8.

alternatingRowStyle: "alternative-row",

9.

headerStyle: "header-grid",

10.

footerStyle: "footer-grid",

11.

mode: WebGridPagerModes.All,

12.

...

63. })</div>
We can also provide the id of the WebGrid to the ajaxUpdateContainerId parameter which is generated by htmlAttributes of GetHtml
method as I am using in my example.

How to do it...
The Model
First of all design the customer model using Entity Framework database first approach as show below

Now develop the logic for querying the data from customer table and also develop the logic for custom paging and sorting.
290.

public class ModelServices : IDisposable

291.

292.

private readonly TestDBEntities entities = new TestDBEntities();

293.
294.

//For Custom Paging

295.

public IEnumerable<Customer> GetCustomerPage(int pageNumber, int pageSize, string sort, bool Dir)

296.

297.

if (pageNumber < 1)

298.

pageNumber = 1;

299.
300.

if (sort == "name")

301.

return entities.Customers.OrderByWithDirection(x => x.Name, Dir)

302.

.Skip((pageNumber - 1) * pageSize)

303.

.Take(pageSize)

304.

.ToList();

305.

else if (sort == "address")

306.

return entities.Customers.OrderByWithDirection(x => x.Address, Dir)

307.

.Skip((pageNumber - 1) * pageSize)

308.

.Take(pageSize)

87

309.

.ToList();

310.

else if (sort == "contactno")

311.

return entities.Customers.OrderByWithDirection(x => x.ContactNo, Dir)

312.

.Skip((pageNumber - 1) * pageSize)

313.

.Take(pageSize)

314.

.ToList();

315.

else

316.

return entities.Customers.OrderByWithDirection(x => x.CustID, Dir)

317.

.Skip((pageNumber - 1) * pageSize)

318.

.Take(pageSize)

319.

.ToList();

320.

321.

public int CountCustomer()

322.

323.

return entities.Customers.Count();

324.

325.
326.

public void Dispose()

327.

328.

entities.Dispose();

329.

330.

331.
332.

public class PagedCustomerModel

333.

334.

public int TotalRows { get; set; }

335.

public IEnumerable<Customer> Customer { get; set; }

336.

public int PageSize { get; set; }

337.

Extension Method for OrderByWithDirection


118.

public static class SortExtension

119.

120.

public static IOrderedEnumerable OrderByWithDirection

121.

(this IEnumerable source,Func keySelector,bool descending)

122.

123.

return descending ? source.OrderByDescending(keySelector)

124.

: source.OrderBy(keySelector);

125.

126.
127.

public static IOrderedQueryable OrderByWithDirection

128.

(this IQueryable source,Expression<func> keySelector,bool descending)</func

129.

<func {</func

130.

<func return descending ? source.OrderByDescending(keySelector)</func

131.

<func : source.OrderBy(keySelector);</func

132.

<func }</func

133.

<func}</func

134.

<func</func

The View
Now design the view based on the above developed model as show below
47. @model Mvc4_CustomWebGrid.Models.PagedCustomerModel
48. @using Mvc4_CustomWebGrid.Models;
49. @{
50.

ViewBag.Title = "Ajax WebGrid with Custom Paging, Sorting";

88

51. }
52.
53. <script src="../../Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
54.
55. @{
56.

WebGrid

grid

new

WebGrid(rowsPerPage:

Model.PageSize,

defaultSort:

"Name",

ajaxUpdateContainerId:

"grid");
57.

grid.Bind(Model.Customer, autoSortAndPage: false, rowCount: Model.TotalRows);

58.

grid.Pager(WebGridPagerModes.All);

59.
60.

@grid.GetHtml(htmlAttributes: new { id = "grid" }, // id for ajaxUpdateContainerId parameter

61.

fillEmptyRows: false,

62.

alternatingRowStyle: "alternate-row",

63.

headerStyle: "grid-header",

64.

footerStyle: "grid-footer",

65.

mode: WebGridPagerModes.All,

66.

firstText: "<< First",

67.

previousText: "< Prev",

68.

nextText: "Next >",

69.

lastText: "Last >>",

70.

columns: new[] {

71.

grid.Column("CustID",header: "ID", canSort: false),

72.

grid.Column("Name"),

73.

grid.Column("Address"),

74.

grid.Column("ContactNo",header: "Contact No")

75.

})

76. }

The Controller
Now, let's see how to write the code for implementing the webgrid functionality using model class and methods.
69. public class HomeController : Controller
70. {
71.

ModelServices mobjModel = new ModelServices();

72.
73.

public ActionResult WebGridCustomPaging(int page = 1, string sort = "custid", string sortDir = "ASC")

74.

75.

const int pageSize = 5;

76.

var totalRows = mobjModel.CountCustomer();

77.
78.

bool Dir = sortDir.Equals("desc", StringComparison.CurrentCultureIgnoreCase) ? true : false;

79.
80.

var customer = mobjModel.GetCustomerPage(page, pageSize, sort, Dir);

81.

var data = new PagedCustomerModel()

82.

83.

TotalRows = totalRows,

84.

PageSize = pageSize,

85.

Customer = customer

86.

};

87.

return View(data);

88.

89. }

How it works..

89

How to upload a file in MVC4


Uploading a file in Asp.Net MVC application is very easy. The posted file is automatically available as a HttpPostedFileBase parameters
in the action of the controler. For uploading a file on the server you required to have a file input control with in html form having

90

encoding type set to multipart/form-data. The default encoding type of a form is application/x-www-form-urlencoded and this is no
sufficient for posting a large amount of data to server.

How to do it..
Step 1 : Form for uploading the file
1.

@using (Html.BeginForm("FileUpload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))

2.

3.

@Html.ValidationSummary();

4.

<ol>

5.

<li class="lifile">

6.

<input type="file" id="fileToUpload" name="file" />

7.

<span class="field-validation-error" id="spanfile"></span>

8.

</li>

9.

</ol>

10.

<input type="submit" id="btnSubmit" value="Upload" />

11. }

Step 2 : Validating the file on client side


1.

<script type="text/jscript">

2.

//get file size

3.

function GetFileSize(fileid) {

4.

try

5.

6.

var fileSize = 0;

7.

//for IE

8.

if ($.browser.msie)

9.

10.

//before making an object of ActiveXObject,

11.

//please make sure ActiveX is enabled in your IE browser

12.

var objFSO = new ActiveXObject("Scripting.FileSystemObject"); var filePath = $("#" + fileid)[0].value;

13.

var objFile = objFSO.getFile(filePath);

14.

var fileSize = objFile.size; //size in kb

15.

fileSize = fileSize / 1048576; //size in mb

16.

17.

//for FF, Safari, Opeara and Others

18.

else

19.

20.

fileSize = $("#" + fileid)[0].files[0].size //size in kb

21.

fileSize = fileSize / 1048576; //size in mb

22.

23.

return fileSize;

24.

25.

catch (e)

26.

27.

alert("Error is :" + e);

28.

29. }
30.
31. //get file path from client system
32. function getNameFromPath(strFilepath)
33. {
34.

var objRE = new RegExp(/([^\/\\]+)$/);

35.

var strName = objRE.exec(strFilepath);

36.
37.

if (strName == null)

91

38.

39.

return null;

40.

41.

else

42.

43.

return strName[0];

44.

45. }
46.
47. $("#btnSubmit").live("click", function ()
48. {
49.

if ($('#fileToUpload').val() == "")

50.

51.

$("#spanfile").html("Please upload file");

52.

return false;

53.

54.

else

55.

56.

return checkfile();

57.

58. });
59.
60. function checkfile()
61. {
62.

var file = getNameFromPath($("#fileToUpload").val());

63.

if (file != null)

64.

65.

var extension = file.substr((file.lastIndexOf('.') + 1));

66.

// alert(extension);

67.

switch (extension) {

68.

case 'jpg':

69.

case 'png':

70.

case 'gif':

71.

case 'pdf':

72.

flag = true;

73.

break;

74.

default:

75.

flag = false;

76.

77.

78.

if (flag == false)

79.

80.

$("#spanfile").text("You can upload only jpg,png,gif,pdf extension file");

81.

return false;

82.

83.

else

84.

85.

var size = GetFileSize('fileToUpload');

86.

if (size > 3)

87.

88.

$("#spanfile").text("You can upload file up to 3 MB");

89.

return false;

90.

91.

else

92.

93.

$("#spanfile").text("");

94.

92

95.

96. }
97.
98. $(function ()
99. {
100.

$("#fileToUpload").change(function () {

101.

checkfile();});

102.

});

103.

</script>

Step 3 : Controller's action for receiving the posted file


1.

[HttpPost]

2.

public ActionResult FileUpload(HttpPostedFileBase file)

3.

4.

if (ModelState.IsValid)

5.

6.

if (file == null)

7.

8.

ModelState.AddModelError("File", "Please Upload Your file");

9.

10.

else if (file.ContentLength > 0)

11.

12.

int MaxContentLength = 1024 * 1024 * 3; //3 MB

13.

string[] AllowedFileExtensions = new string[] { ".jpg", ".gif", ".png", ".pdf" };

14.
15.

if (!AllowedFileExtensions.Contains(file.FileName.Substring(file.FileName.LastIndexOf('.'))))

16.

17.

ModelState.AddModelError("File", "Please file of type: " + string.Join(", ", AllowedFileExtensions));

18.

19.
20.

else if (file.ContentLength > MaxContentLength)

21.

22.

ModelState.AddModelError("File", "Your file is too large, maximum allowed size is: " + MaxContentLength +
" MB");

23.

24.

else

25.

26.

//TO:DO

27.

var fileName = Path.GetFileName(file.FileName);

28.

var path = Path.Combine(Server.MapPath("~/Content/Upload"), fileName);

29.

file.SaveAs(path);

30.

ModelState.Clear();

31.

ViewBag.Message = "File uploaded successfully";

32.

33.

34.

35.

return View();

36. }

How it works...

93

RenderPartial vs RenderAction vs Partial vs Action in MVC Razor


There are different ways for rendering a partial view in MVC Razor. Many developers got confused whether to use RenderPartial or
RenderAction or Partial or Action helper methods for rendering a partial view. In this article, I would like to expose the difference among
Html.RenderPartial, Html.RenderAction, Html.Partial & Html.Action.

94

Html.RenderPartial
1.

This method result will be directly written to the HTTP response stream means it used the same TextWriter object as used in the current
webpage/template.

2.

This method returns void.

3.

Simple to use and no need to create any action.

4.

RenderPartial method is useful used when the displaying data in the partial view is already in the corresponding view model. For
example : In a blog to show comments of an article, we would like to use RenderPartial method since an article information with comments are
already populated in the view model.
1.

5.

@{Html.RenderPartial("_Comments");}
This method is faster than Partial method since its result is directly written to the response stream which makes it fast.

Html.RenderAction
1.

This method result will be directly written to the HTTP response stream means it used the same TextWriter object as used in the current
webpage/template.

2.

For this method, we need to create a child action for the rendering the partial view.

3.

RenderAction method is useful when the displaying data in the partial view is independent from corresponding view model. For
example : In a blog to show category list on each and every page, we would like to use RenderAction method since the list of category is
populated by the different model.
1.

@{Html.RenderAction("Category","Home");}

4.

This method is the best choice when you want to cache a partial view.

5.

This method is faster than Action method since its result is directly written to the HTTP response stream which makes it fast.

Html.Partial
1.

Renders the partial view as an HTML-encoded string.

2.

This method result can be stored in a variable, since it returns string type value.

3.

Simple to use and no need to create any action.

4.

Partial method is useful used when the displaying data in the partial view is already in the corresponding view model.For example : In
a blog to show comments of an article, we would like to use RenderPartial method since an article information with comments are already
populated in the view model.
1.

@Html.Partial("_Comments")

Html.Action
1.

Renders the partial view as an HtmlString .

2.

For this method, we need to create a child action for the rendering the partial view.

3.

This method result can be stored in a variable, since it returns string type value.

4.

Action method is useful when the displaying data in the partial view is independent from corresponding view model. For example : In a
blog to show category list on each and every page, we would like to use Action method since the list of category is populated by the different
model.
1.

5.

@{Html.Action("Category","Home");}
This method is also the best choice when you want to cache a partial view.

95

Enhancing WebGrid with Insert Update and Delete Operations


Many developers want to do Insert, Update and Delete with in WebGrid like as GridView, but don't know how to do it. This article will
help you to do the CRUD operations with in WebGrid.

Populating WebGrid
The Model
First of all design the customer model using Entity Framework database first approach as show below

1.

CREATE TABLE [dbo].[Customer]

2.

3.

[CustID] [int] IDENTITY(1,1) PRIMARY KEY,

4.

[Name] [varchar](100) NULL,

5.

[Address] [varchar](200) NULL,

6.

[ContactNo] [varchar](20) NULL,

7.

Now design the model for querying the data from customer table and populating it to the GridView
1.

public static class SortExtension

2.

3.

public static IOrderedEnumerable OrderByWithDirection

4.

(this IEnumerable source,Func keySelector,bool descending)

5.

6.

return descending ? source.OrderByDescending(keySelector)

7.

: source.OrderBy(keySelector);

8.

9.
10.

public static IOrderedQueryable OrderByWithDirection

11.

(this IQueryable source,Expression<func> keySelector,</func

12. <func bool descending)</func


13. <func {</func
14. <func return descending ? source.OrderByDescending(keySelector)</func
15. <func : source.OrderBy(keySelector);</func
16. <func }</func
17. <func}</func
18. <func</func
19. <funcpublic class ModelServices : IDisposable</func
20. <func{</func
21. <func private readonly TestDBEntities entities = new TestDBEntities();</func
22. <func </func
23. <func

public

IEnumerable<Customer>

GetCustomerPage(int

pageNumber,

int

pageSize,

string

sort,

bool

Dir)</func
24. <func {</func
25. <func if (pageNumber < 1)</func
26. <func pageNumber = 1;</func
27. <func </func
28. <func if (sort == "name")</func

96

29. <func return entities.Customers.OrderByWithDirection(x => x.Name, Dir)</func


30. <func .Skip((pageNumber - 1) * pageSize)</func
31. <func .Take(pageSize)</func
32. <func .ToList();</func
33. <func else if (sort == "address")</func
34. <func return entities.Customers.OrderByWithDirection(x => x.Address, Dir)</func
35. <func .Skip((pageNumber - 1) * pageSize)</func
36. <func .Take(pageSize)</func
37. <func .ToList();</func
38. <func else if (sort == "contactno")</func
39. <func return entities.Customers.OrderByWithDirection(x => x.ContactNo, Dir)</func
40. <func .Skip((pageNumber - 1) * pageSize)</func
41. <func .Take(pageSize)</func
42. <func .ToList();</func
43. <func else</func
44. <func return entities.Customers.OrderByWithDirection(x => x.CustID, Dir)</func
45. <func .Skip((pageNumber - 1) * pageSize)</func
46. <func .Take(pageSize)</func
47. <func .ToList();</func
48. <func }</func
49. <func public int CountCustomer()</func
50. <func {</func
51. <func return entities.Customers.Count();</func
52. <func }</func
53. <func </func
54. <func public void Dispose()</func
55. <func {</func
56. <func entities.Dispose();</func
57. <func }</func
58. <func}</func
59. <func</func
60. <funcpublic class PagedCustomerModel</func
61. <func{</func
62. <func public int TotalRows { get; set; }</func
63. <func public IEnumerable<Customer> Customer { get; set; }</func
64. <func public int PageSize { get; set; }</func
65. <func}</func

The View
Now design the view based on the above developed model as show below
1.

@model Mvc4_WebGrid_CRUD.Models.PagedCustomerModel

2.

@{

3.

ViewBag.Title = "WebGrid CRUD Operations";

4.

WebGrid grid = new WebGrid(rowsPerPage: Model.PageSize);

5.

grid.Bind(Model.Customer,autoSortAndPage: false,rowCount: Model.TotalRows

6.

);

7.

8.
9.

<div id="divmsg" style="color: green; font-weight: bold"></div>

10. <a href="#" class="add">Add New</a>


11. <br />
12. <br />
13. @grid.GetHtml(
14.

htmlAttributes: new { id = "grid" },

15.

fillEmptyRows: false,

16.

mode: WebGridPagerModes.All,

97

17.

firstText: "<< First",

18.

previousText: "< Prev",

19.

nextText: "Next >",

20.

lastText: "Last >>",

21.

columns: new[] {

22.

grid.Column("CustID",header: "ID", canSort: false),

23.
24.

grid.Column(header:

"Name",format:

@<span>

<span

id="spanName_@item.CustID">@item.Name</span>

@Html.TextBox("Name_"+(int)item.CustID,(string)item.Name,new{@style="display:none"})</span>),
25.
26.

grid.Column(header:

"Address",format:

@<span>

<span

id="spanAddress_@item.CustID">@item.Address</span>

@Html.TextBox("Address_"+(int)item.CustID,(string)item.Address,new{@style="display:none"})</span>),
27.
28.

grid.Column(header:

"Contact

No",format:

id="spanContactNo_@item.CustID">@item.ContactNo</span>

@<span>

<span

@Html.TextBox("ContactNo_"+(int)item.CustID,

(string)item.ContactNo,new{@style="display:none"})</span>),
29.
30.

grid.Column(header: "Action",format:@<text> <a href="#" id="Edit_@item.CustID" class="edit">Edit</a><a


href="#"

id="Update_@item.CustID"

id="Cancel_@item.CustID"

style="display:none"

style="display:none"

class="update">Update</a><a
class="cancel">Cancel</a><a

href="#"
href="#"

id="Delete_@item.CustID" class="delete">Delete</a></text>)
31. })

The Controller
Now, let's see how to write the code for populating the webgrid using model class and methods.
1.

public class HomeController : Controller

2.

3.

ModelServices mobjModel = new ModelServices();

4.
5.

public ActionResult WebGridCRUD(int page = 1, string sort = "custid", string sortDir = "ASC")

6.

7.

const int pageSize = 10;

8.

var totalRows = mobjModel.CountCustomer();

9.
10.

bool Dir = sortDir.Equals("desc", StringComparison.CurrentCultureIgnoreCase) ? true : false;

11.
12.

var customer = mobjModel.GetCustomerPage(page, pageSize, sort, Dir);

13.

var data = new PagedCustomerModel()

14.

15.

TotalRows = totalRows,

16.

PageSize = pageSize,

17.

Customer = customer

18.

};

19.

return View(data);

20.

21. }

Insert Operation
The Model
1.

public bool SaveCustomer(string name, string address, string contactno)

2.

3.

try

98

4.

5.

Customer cust = new Customer();

6.

cust.Name = name;

7.

cust.Address = address;

8.

cust.ContactNo = contactno;

9.
10.

entities.Customers.Add(cust);

11.

entities.SaveChanges();

12.

return true;

13.

14.

catch

15.

16.

return false;

17.

18. }

The View
1.

<script type="text/javascript">

2.

$(".add").live("click", function () {

3.
4.

var existrow = $('.save').length;

5.

if (existrow == 0) {

6.

var index = $("#grid tbody tr").length + 1;

7.
8.

var Name = "Name_" + index;

9.

var Address = "Address_" + index;

10.

var ContactNo = "ContactNo_" + index;

11.

var Save = "Save_" + index;

12.

var Cancel = "Cancel_" + index;

13.
14.

var

tr

'<tr

class="alternate-row"><td></td><td><span>

<input

id="'

Name

'"

type="text"

/></span></td>' +
15.

'<td><span> <input id="' + Address + '" type="text" /></span></td>' +

16.

'<td><span> <input id="' + ContactNo + '" type="text" /></span></td>' +

17.

'<td>

<a

href="#"

id="'

Save

'"

class="save">Save</a><a

href="#"

id="'

Cancel

'"

class="icancel">Cancel</a></td>' +
18.

'</tr>';

19.
20.

$("#grid tbody").append(tr);

21.

22.

else {

23.

alert('First Save your previous record !!');

24.

25.
26.

});

27.
28. $(".icancel").live("click", function () {
29.

var flag = confirm('Are you sure to cancel');

30.

if (flag) {

31.

$(this).parents("tr").remove();

32.

33. });
34.
35. $(".save").live("click", function () {
36.

var id = $("#grid tbody tr").length;

37.

var Name = $("#Name_" + id).val();

99

38.

var Address = $("#Address_" + id).val();

39.

var ContactNo = $("#ContactNo_" + id).val();

40.
41.

if (id != "") {

42.

$.ajax({

43.

type: "GET",

44.

contentType: "application/json; charset=utf-8",

45.

url: '@Url.Action("SaveRecord", "Home")',

46.

data: { "name": Name, "address": Address, "contactno": ContactNo },

47.

dataType: "json",

48.

beforeSend: function () { },

49.

success: function (data) {

50.

if (data.result == true) {

51.

$("#divmsg").html("Record has been saved successfully !!");

52.

setTimeout(function () { window.location.replace("WebGridCRUD"); }, 2000);

53.

54.

else {

55.

alert('There is some error');

56.

57.

58.

});

59.

60. });
61. <script>

The Controller
1.

[HttpGet]

2.

public JsonResult SaveRecord(string name, string address, string contactno)

3.

4.

bool result = false;

5.

try

6.

7.

result = mobjModel.SaveCustomer(name, address, contactno);

8.

9.

catch (Exception ex)

10.

11.

12.

return Json(new { result }, JsonRequestBehavior.AllowGet);

13. }

100

How it works..

Update Operation
The Model
1.

public bool UpdateCustomer(int id, string name, string address, string contactno)

2.

3.

try

4.

5.

var cust = (from tbl in entities.Customers

6.

where tbl.CustID == id

7.

select tbl).FirstOrDefault();

8.

cust.Name = name;

9.

cust.Address = address;

10.

cust.ContactNo = contactno;

11.
12.

entities.SaveChanges();

13.

return true;

14.

15.

catch

16.

17.

return false;

18.

19. }

101

The View
1.

<script type="text/javascript">

2.

$(".edit").live("click", function () {

3.

var str = $(this).attr("id").split("_");

4.

id = str[1];

5.
6.

var Name = "#Name_" + id;

7.

var spanName = "#spanName_" + id;

8.

var Address = "#Address_" + id;

9.

var spanAddress = "#spanAddress_" + id;

10.

var ContactNo = "#ContactNo_" + id;

11.

var spanContactNo = "#spanContactNo_" + id;

12.
13.

$(Name).show();

14.

$(spanName).hide();

15.

$(Address).show();

16.

$(spanAddress).hide();

17.

$(ContactNo).show();

18.

$(spanContactNo).hide();

19.
20.

$(this).hide();

21.

$("#Update_" + id).show();

22.

$("#Cancel_" + id).show();

23. });
24.
25. $(".update").live("click", function () {
26.

var str = $(this).attr("id").split("_");

27.

id = str[1];

28.
29.

var Name = $("#Name_" + id).val();

30.

var spanName = $("#spanName_" + id).val();

31.

var Address = $("#Address_" + id).val();

32.

var spanAddress = $("#spanAddress_" + id).val();

33.

var ContactNo = $("#ContactNo_" + id).val();

34.

var spanContactNo = $("#spanContactNo_" + id).val();

35.
36.

if (id != "") {

37.

$.ajax({

38.

type: "GET",

39.

contentType: "application/json; charset=utf-8",

40.

url: '@Url.Action("UpdateRecord", "Home")',

41.

data: { "id": id, "name": Name, "address": Address, "contactno": ContactNo },

42.

dataType: "json",

43.

beforeSend: function () {//alert(id);

44.

},

45.

success: function (data) {

46.

if (data.result == true) {

47.

$("#Update_" + id).hide();

48.

$("#Cancel_" + id).hide();

49.

$("#Edit_" + id).show();

50.
51.

var Name = "#Name_" + id;

52.

var spanName = "#spanName_" + id;

53.

var Address = "#Address_" + id;

54.

var spanAddress = "#spanAddress_" + id;

55.

var ContactNo = "#ContactNo_" + id;

102

56.

var spanContactNo = "#spanContactNo_" + id;

57.
58.

$(Name).hide();

59.

$(spanName).show();

60.

$(Address).hide();

61.

$(spanAddress).show();

62.

$(ContactNo).hide();

63.

$(spanContactNo).show();

64.
65.

$(spanName).text($(Name).val());

66.

$(spanAddress).text($(Address).val());

67.

$(spanContactNo).text($(ContactNo).val());

68.

69.

else {

70.

alert('There is some error');

71.

72.

73.

});

74.

75. });
76.
77. <script>

The Controller
1.

[HttpGet]

2.

public JsonResult UpdateRecord(int id, string name, string address, string contactno)

3.

4.

bool result = false;

5.

try

6.

7.

result = mobjModel.UpdateCustomer(id, name, address, contactno);

8.
9.

10.

catch (Exception ex)

11.

12.

13.

return Json(new { result }, JsonRequestBehavior.AllowGet);

14. }

How it works..

103

Delete Operation
The Model
1.

public bool DeleteCustomer(int id)

2.

3.

try

4.

5.

var cust = (from tbl in entities.Customers

6.

where tbl.CustID == id

7.

select tbl).FirstOrDefault();

8.
9.

entities.Customers.Remove(cust);

10.

entities.SaveChanges();

11.

return true;

12.

13.

catch

14.

15.

return false;

16.

17. }

The View
1.

<script type="text/javascript">

2.

$(".delete").live("click", function () {

3.

var str = $(this).attr("id").split("_");

4.

id = str[1];

5.
6.

var flag = confirm('Are you sure to delete ??');

7.

if (id != "" && flag) {

8.

$.ajax({

9.

type: "GET",

10.

contentType: "application/json; charset=utf-8",

11.

url: '@Url.Action("DeleteRecord", "Home")',

12.

data: { "id": id },

13.

dataType: "json",

14.

beforeSend: function () { },

15.

success: function (data) {

16.

if (data.result == true) {

17.

$("#Update_" + id).parents("tr").remove();

18.

19.

else {

20.

alert('There is some error');

21.

22.

23.

});

104

24.

25. });
26. <script>

The Controller
1.

public bool DeleteCustomer(int id)

2.

3.

try

4.

5.

var cust = (from tbl in entities.Customers

6.

where tbl.CustID == id

7.

select tbl).FirstOrDefault();

8.
9.

entities.Customers.Remove(cust);

10.

entities.SaveChanges();

11.

return true;

12.

13.

catch

14.

15.

return false;

16.

17. }

How it works..

105

Custom Razor View Engine for C# and VB


You should be happy to know, Asp.Net MVC is an open source and highly extensible framework. You can customized it according to your
need. As you read my previous article Removing the Web Form View Engine for better performance of Razor View Engine from your
Asp.Net MVC Razor application. In this article, you will learn how can you customize the Razor View engine for C# and VB language.

Removing All the View Engines & registering the Razor Engine
1.

protected void Application_Start()

2.

3.

//Remove All View Engine including Webform and Razor

4.

ViewEngines.Engines.Clear();

5.

//Register Razor View Engine

6.

ViewEngines.Engines.Add(new RazorViewEngine());

7.
8.

//Other code is removed for clarity


}

After removing the Web Form and other View engine as you noticed that Razor View engine looks up the C# and VB views as shown
below.

As you know MVC is highly extensible hence you can completely replace the Razor view engine with a new custom razor engine. by
doing so, this will slightly improve your application performance. If your MVC application is using only C# language, there is no need to
looks up the .vbhtml views and same for VB language.

Custom C# Razor View Engine

106

Regisering the C# Razor View Engine


64.

protected void Application_Start()

65.

66.

//Remove All View Engine including Webform and Razor

67.

ViewEngines.Engines.Clear();

68.

//Register C# Razor View Engine

69.

ViewEngines.Engines.Add(new CSharpRazorViewEngine());

70.

//Other code is removed for clarity

71.

Custom VB Razor View Engine

107

Regisering the VB Razor View Engine

108

Donut Caching and Donut Hole Caching with Asp.Net MVC 4


Donut caching is the best way to cache an entire web page except for one or more parts of the web page. Before Donut caching, we
have Output Caching which cache the entire web page.

When to use Donut caching...


Suppose, you have a web application in which some pages like HomePage,Tools etc. are same for all the users excepts the user's logged
in details like username.
If you want to cache all these pages for all the users by using OutputCache with VaryByParam UserID, then the entire page would be
cached every time for each user with a different user name (or whatever your dynamic part of the page is). This is not a good practice
since there will be 1000 cached pages if there are 1000 logged in user at a time.

To resolve this issue, Donut Caching was introduced which cached only one copy of the entire page for all the user except for a small
part which remain dynamic. This small part act like as a hole in the cached content and much like a donut.
Donut caching is very useful in the scenarios where most of the elements in your page are rarely changed except the few sections that
dynamically change, or changed based on a request parameter.

The MvcDonutCaching NuGet Package


For implementing Donut caching you need to install MvcDonutCaching NuGet package within your Visual Studio 2012. You can install
this through NuGet or directly type the command "install-package MvcDonutCaching" in the "Package Manager Console" as shown
below:

109

Once the MvcDonutCaching NuGet package is installed, you can add the DonutOutputCache attribute to the action methods or to the
controller. Most of the options of OutputCache attribute are also available with Donut Caching.

72.

[DonutOutputCache(Duration=60)]

73.

public ActionResult Index()

74.
75.

[DonutOutputCache(CacheProfile="TwoMins")]

76.

public ActionResult Index()

77.
78.

[DonutOutputCache(Duration=60, VaryByCustom="whatever")]

79.

public ActionResult Index()

80.
81.

[DonutOutputCache(Duration=60, VaryByParam="something;that")]

82.

public ActionResult Index(string something)

83.
84.

[DonutOutputCache(Duration=60, VaryByParam="none")]

85.

public ActionResult Index(int referrerId)

Donut Hole Caching


Donut Hole Caching is the inverse of Donut caching means while caching the entire page it cached only a small part of the page(the
donut hole).

When to use Donut Hole caching...


Suppose, you have a web application in which ProductCategory is shown on each and every pages so it makes sense to render all of the
categories just once and cache the resulting HTML by using Donut Hole Caching.

110

Donut Hole caching is very useful in the scenarios where most of the elements in your page are dynamic except the few sections that
rarely change, or changed based on a request parameter. Asp.Net MVC has great support for Donut Hole caching through the use of
Child Actions.
338. [ChildActionOnly]
339. [OutputCache(Duration=60)]
340. public ActionResult CategoriesList()
341. {
342. // Get categories list from the database and
343. // pass it to the child view
344. ViewBag.Categories = Model.GetCategories();
345. return View();
346. }

View with Donut Hole Caching


Now call the above action method "CategoriesList" from the parent view as shown below:
135. <h1>MVC Donut Hole Caching Demo</h1>
136.
137. <div>@Html.Action("CategoriesList")</div>
138.
139. <!-- Rest of the page with non cacheable content goes here -->

return View() vs return RedirectToAction() vs return Redirect() vs return


RedirectToRoute()
There are different ways for returning/rendering a view in MVC Razor. Many developers got confused when to use return View(), return
RedirectToAction(), return Redirect() and return RedirectToRoute(). In this article, I would like to explain the difference among "return View()" and
"return RedirectToAction()", "return Redirect()" and "return RedirectToRoute()".

return View()
111

This tells MVC to generate HTML to be displayed for the specified view and sends it to the browser. This acts like as Server.Transfer() in Asp.Net
WebForm.

86.

public ActionResult Index()

87.

88.

return View();

89.

90.
91.

[HttpPost]

92.

public ActionResult Index(string Name)

93.

94.

ViewBag.Message = "Hi, Dot Net Tricks";

95.

//Like Server.Transfer() in Asp.Net WebForm

96.

return View("MyIndex");

97.

98.
99.

public ActionResult MyIndex()

100. {
101. ViewBag.Msg = ViewBag.Message; // Assigned value : "Hi, Dot Net Tricks"
102. return View("MyIndex");
103. }
What happens if we call the action method directly like return MyIndex(). It is simply a method call which returns a rendered view that is
specified in MyIndex() action method.

347. public ActionResult Index()


348. {
349. return View();
350. }
351.
352. [HttpPost]
353. public ActionResult Index(string Name)
354. {

112

355. ViewBag.Message = "Hi, Dot Net Tricks";


356. //Like Server.Transfer() in Asp.Net WebForm
357. return MyIndex();
358. }
359.
360. public ActionResult MyIndex()
361. {
362. ViewBag.Msg = ViewBag.Message; // Assigned value : "Hi, Dot Net Tricks"
363. return View("MyIndex");
364. }

return RedirectToAction()
This tells MVC to redirect to specified action instead of rendering HTML. In this case, browser receives the redirect notification and make a new
request for the specified action. This acts like as Response.Redirect() in Asp.Net WebForm.
Moreover, RedirectToAction construct a redirect url to a specific action/controller in your application and use the route table to generate the
correct URL. RedirectToAction cause the browser to receive a 302 redirect within your application and gives you an easier way to work with your
route table.

104. public ActionResult Index()


105. {
106. return View();
107. }
108.
109. [HttpPost]
110. public ActionResult Index(string Name)
111. {
112. ViewBag.Message = "Hi, Dot Net Tricks";
113. //Like Response.Redirect() in Asp.Net WebForm
114. return RedirectToAction("MyIndex");
115. }
116.
117. public ActionResult MyIndex()
118. {
119. ViewBag.Msg = ViewBag.Message; // Assigned value : Null
120. return View("MyIndex");
121. }

return Redirect()
This tells MVC to redirect to specified URL instead of rendering HTML. In this case, browser receives the redirect notification and make a new
request for the specified URL. This also acts like as Response.Redirect() in Asp.Net WebForm. In this case, you have to specify the full URL to
redirect.
Moreover, Redirect also cause the browser to receive a 302 redirect within your application, but you have to construct the URLs yourself.

113

1.

public ActionResult Index()

2.

3.

return View();

4.

5.
6.

[HttpPost]

7.

public ActionResult Index(string Name)

8.

9.

ViewBag.Message = "Hi, Dot Net Tricks";

10. //Like Response.Redirect() in Asp.Net WebForm


11. return Redirect("Home/MyIndex");
12. }
13.
14. public ActionResult MyIndex()
15. {
16. ViewBag.Msg = ViewBag.Message; // Assigned value : Null
17. return View("MyIndex");
18. }

return RedirectToRoute()
This tells MVC to look up the specifies route into the Route table that is is defined in global.asax and then redirect to that
controller/action defined in that route. This also make a new request like RedirectToAction().

Defined Route
1.

public static void RegisterRoutes(RouteCollection routes)

2.

3.

routes.MapRoute(

4.

"MyRoute", // Route name

5.

"Account/", // URL

6.

new { controller = "Account", action = "Login"} // Parameter defaults

7.

);

8.
9.

routes.MapRoute(

10.

"Default", // Route name

11.

"{controller}/{action}/{id}", // URL with parameters

12.

new { controller = "Home", action = "MyIndex", id = UrlParameter.Optional } // Parameter defaults

13.

);

14. }

HomeController
1.
2.

public ActionResult Index()

3.

4.
5.

return View();
}

6.
7.

[HttpPost]

8.

public ActionResult Index(string Name)

9.

10.

return RedirectToRoute("MyRoute");

11. }

114

AccountController
1.
2.

public ActionResult Login()

3.

4.
5.

return View();
}

Note
1.

Return View doesn't make a new requests, it just renders the view without changing URLs in the browser's address bar.

2.

Return RedirectToAction makes a new requests and URL in the browser's address bar is updated with the generated URL by MVC.

3.

Return Redirect also makes a new requests and URL in the browser's address bar is updated, but you have to specify the full URL to
redirect

4.

Between RedirectToAction and Redirect, best practice is to use RedirectToAction for anything dealing with your application
actions/controllers. If you use Redirect and provide the URL, you'll need to modify those URLs manually when you change the route table.

5.

RedirectToRoute redirects to a specific route defined in the Route table.

Html submission by ValidateInput and AllowHtml attribute in MVC4


Sometimes, your required to save Html data in the database. By default Asp.Net MVC doesn't allow a user to submit html for avoiding Cross Site
Scripting attack to your application. Suppose you have below form and you can submit the Html in description textarea.

If you do this and try to submit it you will get the error as shown in fig.

115

However, if you want to do this, you can achieve it by using ValidateInput attribute and AllowHtml attribute.

ValidateInput Attribute
This is the simple way to allow the submission of HTML. This attribute can enable or disable input validation at the controller level or at any
action method.

ValidateInput at Controller Level


1.
2.

[ValidateInput(false)]

3.

public class HomeController : Controller

4.

5.

public ActionResult AddArticle()

6.

7.

return View();

8.

9.
10.

[HttpPost]

11.

public ActionResult AddArticle(BlogModel blog)

12.

13.

if (ModelState.IsValid)

14.

15.
16.

17.

return View();

18.

19. }
Now, the user can submit Html for this Controller successfully.

ValidateInput at Action Method Level


1.
2.

public class HomeController : Controller

3.

4.

public ActionResult AddArticle()

5.

6.

return View();

7.

8.
9.

[ValidateInput(false)]

10.

[HttpPost]

11.

public ActionResult AddArticle(BlogModel blog)

12.

13.

if (ModelState.IsValid)

116

14.

15.
16.

17.

return View();

18.

19. }
Now, the user can submit Html for this action method successfully.

Limitation of ValidateInput attribute


This attribute also has the issue since this allow the Html input for all the properties and that is unsafe. Since you have enable Html input for only
one-two properties then how to do this. To allow Html input for a single property, you should use AllowHtml attribute.

AllowHtml Attribute
This is the best way to allow the submission of HTML for a particular property. This attribute will be added to the property of a model to bypass
input validation for that property only. This explicit declaration is more secure than the ValidateInput attribute.
1.

using System.ComponentModel.DataAnnotations;

2.

using System.Web.Mvc;

3.
4.

public class BlogModel

5.

6.

[Required]

7.

[Display(Name = "Title")]

140. public string Title { get; set; }


141.
142. [AllowHtml]
143. [Required]
144. [Display(Name = "Description")]
145. public string Description{ get; set; }
146.
147. }
Make sure, you have removed the ValidateInput attribute from Conroller or Action method. Now, the user can submit Html only for the
Description property successfully.

Exception or Error Handling and Logging in MVC4


Error handing is the main concern in any application, whether it is web application or desktop application. Usually, we catch the exception and
log its details to database or text,xml file and also display a user friendly message to end user in-place of error.

117

Asp.Net MVC has some bulit-in exception filters. HandleError is the default bulit-in exception filter. Let's see how to use this filter with in your
application.

HandleError Attribute
The HandleErrorAttribute filter works only when custom errors are enabled in the Web.config file of your application. You can enable custom
errors by adding a customErrors attribute inside the <system.web> node, as shown below:
1.

</system.web>

2.

...

3.

<customErrors mode="On" defaultRedirect="Error.htm"/>

4.

</system.web>

HandleError Attribute can be used to handle error at Action Method level, Controller level and Global level.

HandleError Attribute at Action Method Level


Simply put this attribute to the action method to tell MVC how to react when an exception occurs.
1.

[HandleError(ExceptionType = typeof(System.Data.DataException), View = "DatabaseError")]

2.

public ActionResult Index(int id)

3.

4.

var db = new MyDataContext();

5.

return View("Index", db.Categories.Single(x => x.Id == id));

6.

In the above example when a database exception (System.Data.DataException) occurs during the execution of the Index action, MVC will display
the DatabaseError view.

HandleError Attribute at Controller Level


Simply put this attribute to the controller to tell MVC how to react when an exception occurs with in the action methods of this controller.
1.

[HandleError(ExceptionType = typeof(System.Data.DataException), View = "DatabaseError")]

2.

public class HomeController : Controller

3.

4.
5.

/* Controller Actions with HandleError applied to them */


}

In the above example when a database exception (System.Data.DataException) occurs during the execution of the controler's any action
methos, MVC will display the DatabaseError view.

HandleError Attribute at Global Level


You can also apply the HandleError Attribute for the entire application by registering it as a global error handler. For registering a global error
handler, open the FilterConfig.cs file with in App_Start folder to find the RegisterGlobalFilters method.
By default, ASP.NET MVC template has already registered a global HandleErrorAttribute to the GlobalFilterCollection for your application. Here
you can also add your own custom filter to the global filter collection as well.
1.

public static void RegisterGlobalFilters(GlobalFilterCollection filters)

2.

3.

filters.Add(new HandleErrorAttribute

4.

5.

ExceptionType = typeof(System.Data.DataException),

6.

View = "DatabaseError"

7.

});

8.
9.

filters.Add(new HandleErrorAttribute()); //by default added

10. }

Note
Always remember, by default, global filters are executed in their registered order. so register error filters for specific exception types before any
other.

118

You can also set the order of execution of these filter by giving number values to each. The above registered filters can be re-written as:
1.

public static void RegisterGlobalFilters(GlobalFilterCollection filters)

2.

3.

filters.Add(new HandleErrorAttribute(),2); //by default added

4.

filters.Add(new HandleErrorAttribute

5.

6.

ExceptionType = typeof(System.Data.DataException),

7.

View = "DatabaseError"

8.
9.

},1);
}

Now, all the filters will be executed in the number sequence.

Limitation of HandleError Attribute


1.

It has no support to log the exceptions since it suppressed the error once it is handled.

2.

It only catch 500 Http error and doesn't catch other HTTP errors like 404,401 etc.

3.

It doesn't catch the errors that occur outside the controllers like errors occurs in model.

4.

It returns error view even if error occurred in AJAX calls that is not useful in the client-side. It would be great to return a piece of JSON in
AJAX exceptions .

Extending HandleError Filter for logging and handling more errors


You can also make your custom error filter by extending HandleError filter. Let's see how to extend this filter to log the exceptions and return a
JSON object for AJAX calls.
1.

public class CustomHandleErrorAttribute : HandleErrorAttribute

2.

3.

public override void OnException(ExceptionContext filterContext)

4.

5.

if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)

6.

7.

return;

8.

9.
10.

if (new HttpException(null, filterContext.Exception).GetHttpCode() != 500)

11.

12.

return;

13.

14.
15.

if (!ExceptionType.IsInstanceOfType(filterContext.Exception))

16.

17.

return;

18.

19.
20.

// if the request is AJAX return JSON else view.

21.

if (filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest")

22.

23.

filterContext.Result = new JsonResult

24.

25.

JsonRequestBehavior = JsonRequestBehavior.AllowGet,

26.

Data = new

27.

28.

error = true,

29.

message = filterContext.Exception.Message

30.

31.

};

32.

33.

else

119

34.

35.

var controllerName = (string)filterContext.RouteData.Values["controller"];

36.

var actionName = (string)filterContext.RouteData.Values["action"];

37.

var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);

38.
39.

filterContext.Result = new ViewResult

40.

41.

ViewName = View,

42.

MasterName = Master,

43.

ViewData = new ViewDataDictionary(model),

44.

TempData = filterContext.Controller.TempData

45.

};

46.

47.
48.

// log the error by using your own method

49.

LogError(filterContext.Exception.Message, filterContext.Exception);

50.
51.

filterContext.ExceptionHandled = true;

52.

filterContext.HttpContext.Response.Clear();

53.

filterContext.HttpContext.Response.StatusCode = 500;

54.
55.

filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;

56.

57. }

Different ways of rendering layouts in Asp.Net MVC


In Asp.Net MVC, Layouts are like as Master Pages in Asp.Net Web Forms. These helps us to maintain consistent look and feel across all the views
within your Asp.Net MVC application. Like Master Pages, Layout may contains common CSS, jQuery files across the multiple Views and one or
more placeholders for which Views provide content. For layout and its components refer this article Layouts, RenderBody, RenderSection and
RenderPage in ASP.NET MVC.
In Asp.Net MVC, at application level we have _ViewStart file with in Views folder for defining the default Layout page for your Asp.Net MVC
application. In this article, I am going to expose the different ways to apply layout pages for your application. Suppose we have to render the
layouts as shown in the fig. by using various ways.

Method 1 : Control Layouts rendering by using _ViewStart file in the root directory
of the Views folder
We can change the default rendering of layouts with in _ViewStart file by using the below code:
1.
2.

@{
var controller = HttpContext.Current.Request.RequestContext.RouteData.Values["Controller"].ToString();

120

3.
4.

string layout = "";

5.

if (controller == "Admin")

6.

7.

layout = "~/Views/Shared/_AdminLayout.cshtml";

8.

9.

else

10.

11.

layout = "~/Views/Shared/_Layout.cshtml";

12.

13.
14.

Layout = layout;

15. }

Method 2 : Return Layout from ActionResult


We can also override the default layout rendering by returning the layout from the ActionResult by using the below code:
1.

public ActionResult Index()

2.

3.

RegisterModel model = new RegisterModel();

4.

//TO DO:

5.
6.

return View("Index", "_AdminLayout", model);


}

Method 3 : Define Layout with in each view on the top


We can also override the default layout rendering by defining the layout on the view by using the below code:
1.

@{

2.
3.

Layout = "~/Views/Shared/_AdminLayout.cshtml";
}

Method 4 : Adding _ViewStart file in each of the directories


We can also set the default layout for a particular directory by putting _ViewStart file in each of the directories with the required Layout
information as shown below:

1.

@{

2.
3.

Layout = "~/Views/Shared/_AdminLayout.cshtml";
}

121

A brief history of Asp.Net MVC framework


ASP.Net MVC is a new Framework built on the top of Microsoft .Net Framework to develop web application. This framework implements the MVC
pattern which helps to provides separation of code and also provide better support for test-driven development (TDD).
Asp.Net MVC is a lightweight and highly testable open source framework for building highly scalable and well designed web applications. Here is
the list of released version history of ASP.NET MVC Framework with theirs features.

Asp.Net MVC1
1.

Released on Mar 13, 2009

2.

Runs on .Net 3.5 and with Visual Studio 2008 & Visual Studio 2008 SP1

3.

MVC Pattern architecture with WebForm Engine

4.

Html Helpers

5.

Ajax helpers

6.

Routing

7.

Unit Testing

Asp.Net MVC2
1.

Released on Mar 10, 2010

2.

Runs on .Net 3.5, 4.0 and with Visual Studio 2008 & 2010

3.

Strongly typed HTML helpers means lambda expression based Html Helpers

4.

Templated Helpers

5.

Support for Data Annotations Attribute

6.

Client-side validation

7.

UI helpers with automatic scaffolding & customizable templates

8.

Attribute-based model validation on both client and server

9.

Overriding the HTTP Method Verb including GET, PUT, POST, and DELETE

10.

Areas for partitioning a large applications into modules

11.

Asynchronous controllers

Asp.Net MVC3
1.

Released on Jan 13, 2011

2.

Runs on .Net 4.0 and with Visual Studio 2010

3.

The Razor view engine

4.

Improved Support for Data Annotations

5.

Remote Validation

6.

Compare Attribute

7.

Sessionless Controller

8.

Child Action Output Caching

9.

Dependency Resolver

10.

Entity Framework Code First support

11.

Partial-page output caching

12.

ViewBag dynamic property for passing data from controller to view

13.

Global Action Filters

14.

Better JavaScript support with unobtrusive JavaScript, jQuery Validation, and JSON binding

15.

Use of NuGet to deliver software and manage dependencies throughout the platform

16.

Good Intellisense support for Razor into Visual Studio

Asp.Net MVC4
1.

Released on Aug 15, 2012

2.

Runs on .Net 4.0, 4.5 and with Visual Studio 2010SP1 & Visual Studio 2012

3.

ASP.NET Web API

4.

Enhancements to default project templates

122

5.

Mobile project template using jQuery Mobile

6.

Display Modes

7.

Task support for Asynchronous Controllers

8.

Bundling and minification

9.

Support for the Windows Azure SDK

Asp.Net MVC5
1.

Released on 17 October 2013

2.

Runs on .Net 4.5, 4.5.1 and with Visual Studio 2013

3.

One Asp.Net

4.

Asp.Net Identity

5.

ASP.NET Scaffolding

6.

Authentication filters - run prior to authorization filters in the ASP.NET MVC pipeline

7.

Bootstrap in the MVC template

8.

ASP.NET Web API2

Note
In this article, I have mention only stable released version of Asp.Net MVC Framework.

How to get textboxes values in MVC4 created by jQuery


Yesterday, I was trying to get the values of TextBoxes created by jQuery. I was expecting to get the value of each Textbox created by jQuery by
the Id attribute of the TextBox, but I was getting NULL. I tried to find out the reason behind this reason and finally I got the solution. Let's
understand the ID and Name attribute of Html controls.

1.

ID

Id attribute of an input html control is responsible for uniquely identified a control on the html page. We use Id for getting an input html control's
value using jQuery at client side or for applying some CSS to that control.

2.

Name

Name attribute of an input html control is responsible for posting that control values on server side.
Hence, while creating a Html TextBox or Dropdown list using jQuery also defined the Id and Name attributes of an Html TextBox or Dropdown list.

Note
When you will not defined the Name attributes of an Html TextBox or Dropdown list then form will not post the TextBox or Dropdown list values to
the server. It means at controller's action result you will not find the Html TextBox or Dropdown list.
Suppose, you need to select no of customers from drop down list as shown below fig.

Also, Textboxes for entering customers full name are created by jQuery as shown below.

123

When you will submit the form you will get the Textboxes created by jQuery at controller side as shown below -

The View
1.

<script src="~/Scripts/jquery-1.8.2.js"></script>

2.

<script>

3.

$(document).ready(function () {

4.

$("#ddl").change(function () {

5.

var i = $("#ddl :selected").val();

6.

var str = "";

7.

for (var j = 1; j <= i; j++) {

8.

var id = "txtCustomer" + j;

9.

//Remember to add name attribute to get values at server side

10.

str = str + "<span>Customer " + j + " Full Name: </span><input type='text' id='" + id + "' name='" + id +
"'/><br/>";

11.

12.

$("#content").html(str);

13.

});

14.

});

15. </script>
16.
17. <br />
18. @using (Html.BeginForm())
19. {
20.

<h2>Get TextBoxes Values Created by jQuery</h2>

124

21.
22.

<span>Select No. of Customers </span>

23.

<select id="ddl" name="ddl">

24.

<option>Select</option>

25.

<option>1</option>

26.

<option>2</option>

27.

<option>3</option>

28.

<option>4</option>

29.

</select>

30.

<br />

31.

<div id="content">

32.

</div>

33.

<br />

34.

<div align="center">

35.

<input type="submit" id="btnSave" value="Save" />

36.

</div>

37. }
You can get the Html TextBox or Dropdown list values created by jQuery by two method as given below -

Method 1: Get Values Using FormCollection


1.

public ActionResult Index()

2.

3.
4.

return View();
}

5.
6.

[HttpPost]

7.

public ActionResult Index(FormCollection form, string ddl)

8.

9.

for (int i = 1; i <= Convert.ToInt32(ddl); i++)

10.

11.

string id = "txtCustomer" + i;

12.

string customer = form[id];

13.

14.

return View();

15. }

Method 2: Get Values Using Request.Form


1.

public ActionResult Index()

2.

3.
4.

return View();
}

5.
6.

[HttpPost]

7.

public ActionResult Index(string ddl)

8.

9.

for (int i = 1; i <= Convert.ToInt32(ddl); i++)

10.

11.

string id = "txtCustomer" + i;

12.

string customer = Request.Form[id];

13.

14.

return View();

15. }

125

Changing browser URL with jQuery mobile and Asp.Net MVC


Like Asp.Net MVC, jQuery mobile based MVC5 or MVC4 application does not update the browser URL with the current controller or action or id.
Since jQuery mobile treats each request as an AJAX request. Hence when you navigate to new page or redirect to new action or page, then the
browser URL would be same for all the navigation and redirection.

How to do it..
I did some work around it and found the better solution for changing browser URL with jQuery mobile and Asp.Net MVC. jQuery mobile has datatheme attribute which you need to specify in your DIV having attribute data-role="page"
Make a new MVC Helpers for specifying the data-theme attribute and register it in your web.config of Views folder of your Asp.Net MVC
application.

Making Custom Asp.Net Helper


1.

namespace jQueryMobileSite.CustomHelpers

2.

3.

public static class CustomHtmlHelper

4.

5.

public static IHtmlString GetPageUrl(this HtmlHelper htmlHelper, ViewContext viewContext)

6.

7.

StringBuilder urlBuilder = new StringBuilder();

8.

urlBuilder.Append("data-url='");

9.

urlBuilder.Append(viewContext.HttpContext.Request.Url.GetComponents

(UriComponents.PathAndQuery,

UriFormat.UriEscaped));
10.

urlBuilder.Append("'");

11.

return htmlHelper.Raw(urlBuilder.ToString());

12.

13. }
14. }

Adding Custom Asp.Net Helper


1.

<system.web.webPages.razor>

2.

...

3.

<pages pageBaseType="System.Web.Mvc.WebViewPage">

4.

<namespaces>

5.

<!-- other code has been removed for clarity -->

6.

<add namespace="jQueryMobileSite.CustomHelpers"/>

7.

...

8.

</namespaces>

9.

</pages>

126

10. </system.web.webPages.razor>

Using Custom Asp.Net Helper


Now you can use this custom helpers on your views's DIV having attribute data-role="page" . Since this DIV acts as a new page for the jQuery
Mobile.
1.

<div data-role="page" data-theme="d" @Html.GetPageUrl(ViewContext)>

2.

@* TO DO: Your Code *@

3.

</div>

Custom Authentication and Authorization in ASP.NET MVC


When standard types of authentication do not meet your requirements, you need to modify an authentication mechanism to create a custom
solution. A user context has principal which represents the identity and roles for that user. A user is authenticated by its identity and assigned
roles to a user determine about authorization or permission to access resources.

ASP.NET provides IPrincipal and IIdentity interfaces to represents the identity and role for a user. You can create a custom solution by evaluating
the IPrincipal and IIdentity interfaces which are bound to the HttpContext as well as the current thread.
1.

public class CustomPrincipal : IPrincipal

2.

3.

public IIdentity Identity { get; private set; }

4.

public bool IsInRole(string role)

5.

6.

if (roles.Any(r => role.Contains(r)))

7.

8.

return true;

9.

10.

else

11.

12.

return false;

13.

14.

15.
16.

public CustomPrincipal(string Username)

17.

18.

this.Identity = new GenericIdentity(Username);

19.

20.
21.

public int UserId { get; set; }

22.

public string FirstName { get; set; }

23.

public string LastName { get; set; }

24.

public string[] roles { get; set; }

25.

127

Now you can put this CustomPrincipal objects into the threads currentPrinciple property and into the HttpContexts User property to accomplish
your custom authentication and authorization process.

ASP.NET Forms Authentication


ASP.NET forms authentication occurs after IIS authentication is completed. You can configure forms authentication by using forms element with in
web.config file of your application. The default attribute values for forms authentication are shown below:

365. <system.web>
366. <authentication mode="Forms">
367. <forms loginUrl="Login.aspx"
368. protection="All"
369. timeout="30"
370. name=".ASPXAUTH"
371. path="/"
372. requireSSL="false"
373. slidingExpiration="true"
374. defaultUrl="default.aspx"
375. cookieless="UseDeviceProfile"
376. enableCrossAppRedirects="false" />
377. </authentication>
378. </system.web>
The FormsAuthentication class creates the authentication cookie automatically when SetAuthCookie() or RedirectFromLoginPage() methods are
called. The value of authentication cookie contains a string representation of the encrypted and signed FormsAuthenticationTicket object.

You can create the FormsAuthenticationTicket object by specifying the cookie name, version of the cookie, directory path, issue date of the
cookie, expiration date of the cookie, whether the cookie should be persisted, and optionally user-defined data as shown below:

128

148. FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,


149. "userName",
150. DateTime.Now,
151. DateTime.Now.AddMinutes(30), // value of time out property
152. false, // Value of IsPersistent property
153. String.Empty,
154. FormsAuthentication.FormsCookiePath);
Now, you can encrypt this ticket by using the Encrypt method FormsAuthentication class as given below:

77.

string encryptedTicket = FormsAuthentication.Encrypt(ticket);

Note
To encrypt FormsAuthenticationTicket ticket set the protection attribute of the forms element to All or Encryption.

Custom Authorization
ASP.NET MVC provides Authorization filter to authorize a user. This filter can be applied to an action, a controller, or even globally. This filter is
based on AuthorizeAttribute class. You can customize this filter by overriding OnAuthorization() method as shown below:

90.

public class CustomAuthorizeAttribute : AuthorizeAttribute

91.

92.

public string UsersConfigKey { get; set; }

93.

public string RolesConfigKey { get; set; }

94.
95.

protected virtual CustomPrincipal CurrentUser

96.

97.

get { return HttpContext.Current.User as CustomPrincipal; }

98.

99.
100. public override void OnAuthorization(AuthorizationContext filterContext)
101. {
102. if (filterContext.HttpContext.Request.IsAuthenticated)
103. {
104. var authorizedUsers = ConfigurationManager.AppSettings[UsersConfigKey];
105. var authorizedRoles = ConfigurationManager.AppSettings[RolesConfigKey];

129

106.
107. Users = String.IsNullOrEmpty(Users) ? authorizedUsers : Users;
108. Roles = String.IsNullOrEmpty(Roles) ? authorizedRoles : Roles;
109.
110. if (!String.IsNullOrEmpty(Roles))
111. {
112. if (!CurrentUser.IsInRole(Roles))
113. {
114. filterContext.Result = new RedirectToRouteResult(new
115. RouteValueDictionary(new { controller = "Error", action = "AccessDenied" }));
116.
117. // base.OnAuthorization(filterContext); //returns to login url
118. }
119. }
120.
121. if (!String.IsNullOrEmpty(Users))
122. {
123. if (!Users.Contains(CurrentUser.UserId.ToString()))
124. {
125. filterContext.Result = new RedirectToRouteResult(new
126. RouteValueDictionary(new { controller = "Error", action = "AccessDenied" }));
127.
128. // base.OnAuthorization(filterContext); //returns to login url
129. }
130. }
131. }
132.

130

133. }
134. }

User Authentication
A user will be authenticated if IsAuthenticated property returns true. For authenticating a user you can use one of the following two ways:

89.

Thread.CurrentPrincipal.Identity.IsAuthenticated

90.

HttpContext.Current.User.Identity.IsAuthenticated

Designing Data Model


Now its time to create data access model classes for creating and accessing Users and Roles as shown below:

21.

public class User

22.

23.

public int UserId { get; set; }

24.
25.

[Required]

26.

public String Username { get; set; }

27.
28.

[Required]

29.

public String Email { get; set; }

30.
31.

[Required]

32.

public String Password { get; set; }

33.
34.

public String FirstName { get; set; }

35.

public String LastName { get; set; }

36.
37.

public Boolean IsActive { get; set; }

38.

public DateTime CreateDate { get; set; }

39.
40.

public virtual ICollection<Role> Roles { get; set; }

41.

1.

public class Role

131

2.

3.

public int RoleId { get; set; }

4.
5.

[Required]

6.

public string RoleName { get; set; }

7.

public string Description { get; set; }

8.
9.

public virtual ICollection<User> Users { get; set; }

10.

Defining Database Context with code first mapping between User and Role
Using Entity Framework code first approach, create a DataContext having User and Role entities with its relational mapping details as shown
below:
1.

public class DataContext : DbContext

2.

3.

public DataContext()

4.

: base("DefaultConnection")

5.

6.
7.

8.

protected override void OnModelCreating(DbModelBuilder modelBuilder)

9.

10.

modelBuilder.Entity<User>()

11.

.HasMany(u => u.Roles)

12.

.WithMany(r=>r.Users)

13.

.Map(m =>

14.

15.

m.ToTable("UserRoles");

16.

m.MapLeftKey("UserId");

17.

m.MapRightKey("RoleId");

132

18.

});

19.

20.

public DbSet<User> Users { get; set; }

21.

public DbSet<Role> Roles { get; set; }

22.

Code First Database Migrations


With the help of entity framework code first database migrations create the database named as Security in the SQL Server. Run the following
command through Visual Studio Package Manager Console to migrate your code into SQL Server database.

After running first command i.e. enabling migrations for your project, add seed data to Configuration.cs file of Migrations folder as shown below:
1.

protected override void Seed(Security.DAL.DataContext context)

2.

3.

Role role1 = new Role { RoleName = "Admin" };

4.

Role role2 = new Role { RoleName = "User" };

5.
6.

User user1 = new User { Username = "admin", Email = "admin@ymail.com", FirstName = "Admin", Password = "123456", IsActive = true, CreateDate
= DateTime.UtcNow, Roles = new List() };

7.
8.

User user2 = new User { Username = "user1", Email = "user1@ymail.com", FirstName = "User1", Password = "123456", IsActive = true, CreateDate
= DateTime.UtcNow, Roles = new List() };

9.
10.

user1.Roles.Add(role1);

11.

user2.Roles.Add(role2);

12.
13.

context.Users.Add(user1);

133

14.

context.Users.Add(user2);

15.

When above three commands will be executed successfully as shown above, the following database will be created in your SQL Server.

Solution Structure

134

Designing View Model


Create a view model class for handing login process as given below:
1.

public class LoginViewModel

2.

3.

[Required]

4.

[Display(Name = "User name")]

5.

public string Username { get; set; }

6.
7.

[Required]

8.

[DataType(DataType.Password)]

9.

[Display(Name = "Password")]

10.

public string Password { get; set; }

11.
12.

[Display(Name = "Remember me?")]

13.

public bool RememberMe { get; set; }

14.

15.
1.

public class CustomPrincipalSerializeModel

2.

3.

public int UserId { get; set; }

4.

public string FirstName { get; set; }

5.

public string LastName { get; set; }

6.

public string[] roles { get; set; }

7.

Forms Authentication Initialization


1.

public class AccountController : Controller

2.

3.

DataContext Context = new DataContext();

4.

//

135

5.

// GET: /Account/

6.

public ActionResult Index()

7.

8.

return View();

9.

10.
11.

[HttpPost]

12.

public ActionResult Index(LoginViewModel model, string returnUrl = "")

13.

14.

if (ModelState.IsValid)

15.

16.

var user = Context.Users.Where(u => u.Username == model.Username && u.Password == model.Password).FirstOrDefault();

17.

if (user != null)

18.

19.

var roles=user.Roles.Select(m => m.RoleName).ToArray();

20.
21.

CustomPrincipalSerializeModel serializeModel = new CustomPrincipalSerializeModel();

22.

serializeModel.UserId = user.UserId;

23.

serializeModel.FirstName = user.FirstName;

24.

serializeModel.LastName = user.LastName;

25.

serializeModel.roles = roles;

26.
27.

string userData = JsonConvert.SerializeObject(serializeModel);

28.

FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(

29.

1,

30.

user.Email,

31.

DateTime.Now,

136

32.

DateTime.Now.AddMinutes(15),

33.

false, //pass here true, if you want to implement remember me functionality

34.

userData);

35.
36.

string encTicket = FormsAuthentication.Encrypt(authTicket);

37.

HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);

38.

Response.Cookies.Add(faCookie);

39.
40.

if(roles.Contains("Admin"))

41.

42.

return RedirectToAction("Index", "Admin");

43.

44.

else if (roles.Contains("User"))

45.

46.

return RedirectToAction("Index", "User");

47.

48.

else

49.

50.

return RedirectToAction("Index", "Home");

51.

52.

53.
54.

ModelState.AddModelError("", "Incorrect username and/or password");

55.

56.
57.

return View(model);

58.

137

59.
60.

[AllowAnonymous]

61.

public ActionResult LogOut()

62.

63.

FormsAuthentication.SignOut();

64.

return RedirectToAction("Login", "Account", null);

65.

66.

67.
1.

public class MvcApplication : System.Web.HttpApplication

2.

3.

protected void Application_Start()

4.

5.

AreaRegistration.RegisterAllAreas();

6.
7.

WebApiConfig.Register(GlobalConfiguration.Configuration);

8.

FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

9.

RouteConfig.RegisterRoutes(RouteTable.Routes);

10.

BundleConfig.RegisterBundles(BundleTable.Bundles);

11.
12.

Database.SetInitializer<DataContext>(new DataContextInitilizer());

13.

14.

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)

15.

16.

HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];

17.

if (authCookie != null)

18.

138

19.
20.

FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);

21.
22.

CustomPrincipalSerializeModel serializeModel = JsonConvert.DeserializeObject<CustomPrincipalSerializeModel>(authTicket.UserData);

23.

CustomPrincipal newUser = new CustomPrincipal(authTicket.Name);

24.

newUser.UserId = serializeModel.UserId;

25.

newUser.FirstName = serializeModel.FirstName;

26.

newUser.LastName = serializeModel.LastName;

27.

newUser.roles = serializeModel.roles;

28.
29.

HttpContext.Current.User = newUser;

30.

31.
32.

33.

Base Controller for accessing Current User


Create a base controller for accessing your User data in your all controller. Inherit, your all controller from this base controller to access user
information from the UserContext.
1.

public class BaseController : Controller

2.

3.

protected virtual new CustomPrincipal User

4.

5.

get { return HttpContext.User as CustomPrincipal; }

6.

7.

1.

public class HomeController : BaseController

2.

3.

//

4.

// GET: /Home/

139

5.

public ActionResult Index()

6.

7.

string FullName = User.FirstName + " " + User.LastName;

8.

return View();

9.

10.

Base View Page for accessing Current User


Create a base class for all your views for accessing your User data in your all views as shown below:
1.

public abstract class BaseViewPage : WebViewPage

2.

3.

public virtual new CustomPrincipal User

4.

5.

get { return base.User as CustomPrincipal; }

6.

7.

8.

public abstract class BaseViewPage<TModel> : WebViewPage<TModel>

9.

10.

public virtual new CustomPrincipal User

11.

12.

get { return base.User as CustomPrincipal; }

13.

14.

Register this class with in the \Views\Web.config as base class for all your views as given below:
1.

<system.web.webPages.razor>

2.

<!--Other code has been removed for clarity-->

3.

<pages pageBaseType="Security.DAL.Security.BaseViewPage">

4.

<namespaces>

5.

<!--Other code has been removed for clarity-->

6.

</namespaces>

140

7.

</pages>

8.

</system.web.webPages.razor>

Now you can access the authenticated user information on all your view in easy and simple way as shown below in Admin View:
1.

@{

2.

ViewBag.Title = "Index";

3.

Layout = "~/Views/Shared/_AdminLayout.cshtml";

4.

5.

<h4>Welcome : @User.FirstName</h4>

6.

<h1>Admin DashBoard</h1>

Login View
1.

@model Security.Models.LoginViewModel

2.
3.

@{

4.

ViewBag.Title = "Index";

5.

6.
7.

@using (Html.BeginForm())

8.

9.

@Html.AntiForgeryToken()

10.
11.

<div class="form-horizontal">

12.

<h4>User Login</h4>

13.

<hr />

14.

@Html.ValidationSummary(true)

15.
16.

<div class="form-group">

17.

@Html.LabelFor(model => model.Username, new { @class = "control-label col-md-2" })

141

18.

<div class="col-md-10">

19.

@Html.EditorFor(model => model.Username)

20.

@Html.ValidationMessageFor(model => model.Username)

21.

</div>

22.

</div>

23.
24.

<div class="form-group">

25.

@Html.LabelFor(model => model.Password, new { @class = "control-label col-md-2" })

26.

<div class="col-md-10">

27.

@Html.EditorFor(model => model.Password)

28.

@Html.ValidationMessageFor(model => model.Password)

29.

</div>

30.

</div>

31.
32.

<div class="form-group">

33.

@Html.LabelFor(model => model.RememberMe, new { @class = "control-label col-md-2" })

34.

<div class="col-md-10">

35.

@Html.EditorFor(model => model.RememberMe)

36.

@Html.ValidationMessageFor(model => model.RememberMe)

37.

</div>

38.

</div>

39.
40.

<div class="form-group">

41.

<div class="col-md-offset-2 col-md-10">

42.

<input type="submit" value="Login" class="btn btn-default" />

43.

</div>

44.

</div>

142

45.

</div>

46.

Applying CustomAuthorize attribute


To make secure your admin or user pages, decorate your Admin and User controllers with CustomAuthorize attribute as defined above and
specify the uses or roles to access admin and user pages.
1.

[CustomAuthorize(Roles= "Admin")]

2.

// [CustomAuthorize(Users = "1")]

3.

public class AdminController : BaseController

4.

5.

//

6.

// GET: /Admin/

7.

public ActionResult Index()

8.

9.

return View();

10.

11.

1.
2.

[CustomAuthorize(Roles= "User")]

3.

// [CustomAuthorize(Users = "1,2")]

4.

public class UserController : BaseController

5.

6.

//

7.

// GET: /User/

8.

public ActionResult Index()

9.

10.

return View();

11.

12.

You can also specify the Roles and Users with in your web.config as a key to avoid hard code values for Users and Roles at the controller level.

143

1.

<add key="RolesConfigKey" value="Admin"/>

2.

<add key="UsersConfigKey" value="2,3"/>

Use one of these keys within the CustomAuthorize attribute as shown below:
1.

//[CustomAuthorize(RolesConfigKey = "RolesConfigKey")]

2.

[CustomAuthorize(UsersConfigKey = "UsersConfigKey")]

3.
4.

public class AdminController : BaseController

5.

6.

//

7.

// GET: /Admin/

8.

public ActionResult Index()

9.

10.

return View();

11.

12.

1.

[CustomAuthorize(RolesConfigKey = "RolesConfigKey")]

2.

// [CustomAuthorize(UsersConfigKey = "UsersConfigKey")]

3.

public class UserController : BaseController

4.

5.

//

6.

// GET: /User/

7.

public ActionResult Index()

8.

9.

return View();

10.

11.

Test your application


When you will run your application and will login into the application using user1, you will be redirected to User dashboard as shown below:

144

When user will try to access unauthorized pages such as Admin dashboard using URL: http://localhost:11681/Admin , he will get the custom error
page as shown below:

Detailed ASP.NET MVC Pipeline


ASP.NET MVC is an open source framework built on the top of Microsoft .NET Framework to develop web application that enables a clean
separation of code. ASP.NET MVC framework is the most customizable and extensible platform shipped by Microsoft. In this article, you will learn
the detail pipeline of ASP.NET MVC.

Routing
Routing is the first step in ASP.NET MVC pipeline. typically, it is a pattern matching system that matches the incoming request to the registered
URL patterns in the Route Table.
The UrlRoutingModule(System.Web.Routing.UrlRoutingModule) is a class which matches an incoming HTTP request to a registered route pattern
in the RouteTable(System.Web.Routing.RouteTable).
When ASP.NET MVC application starts at first time, it registers one or more patterns to the RouteTable to tell the routing system what to do with
any requests that match these patterns. An application has only one RouteTable and this is setup in the Application_Start event of Global.asax of
the application.
1.
2.

public class RouteConfig


{

145

3.

public static void RegisterRoutes(RouteCollection routes)

4.

5.

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

6.
7.

routes.MapRoute(

8.

name: "Default",

9.

url: "{controller}/{action}/{id}",

10.

defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }

11.

);

12.

13.

1.

protected void Application_Start()

2.

3.

//Other code is removed for clarity

4.
5.
When

RouteConfig.RegisterRoutes(RouteTable.Routes);
}
the

UrlRoutingModule

finds

matching

route

within

RouteCollection

(RouteTable.Routes),

it

retrieves

the

IRouteHandler(System.Web.Mvc.IRouteHandler) instance(default is System.Web.MvcRouteHandler) for that route. From the route handler, the
module gets an IHttpHandler(System.Web.IHttpHandler) instance(default is System.Web.MvcHandler).
1.

public interface IRouteHandler

2.

3.
4.

IHttpHandler GetHttpHandler(RequestContext requestContext);


}

Controller Initialization
146

The MvcHandler initiates the real processing inside ASP.NET MVC pipeline by using ProcessRequest method. This method uses the
IControllerFactory instance (default is System.Web.Mvc.DefaultControllerFactory) to create corresponding controller.
1.

protected internal virtual void ProcessRequest(HttpContextBase httpContext)

2.

3.

SecurityUtil.ProcessInApplicationTrust(delegate {

4.

IController controller;

5.

IControllerFactory factory;

6.

this.ProcessRequestInit(httpContext, out controller, out factory);

7.

try

8.

9.

controller.Execute(this.RequestContext);

10.

11.

finally

12.

13.

factory.ReleaseController(controller);

14.

15.

});

16. }

Action Execution
1.

When the controller is initialized, the controller calls its own InvokeAction() method by passing the details of the chosen action method.
This is handled by the IActionInvoker.
1.

2.

public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)


After chosen of appropriate action method, model binders(default is System.Web.Mvc.DefaultModelBinder) retrieves the data from

incoming HTTP request and do the data type conversion, data validation such as required or date format etc. and also take care of input values
mapping to that action method parameters.
3.

Authentication Filter was introduced with ASP.NET MVC5 that run prior to authorization filter. It is used to authenticate a user.
Authentication filter process user credentials in the request and provide a corresponding principal. Prior to ASP.NET MVC5, you use authorization
filter for authentication and authorization to a user.
By default, Authenticate attribute is used to perform Authentication. You can easily create your own custom authentication filter by
implementing IAuthenticationFilter.

4.

Authorization filter allow you to perform authorization process for an authenticated user. For example, Role based authorization for
users to access resources.
By default, Authorize attribute is used to perform authorization. You can also make your own custom authorization filter by implementing
IAuthorizationFilter.

5.

Action filters are executed before(OnActionExecuting) and after(OnActionExecuted) an action is executed. IActionFilter interface
provides you two methods OnActionExecuting and OnActionExecuted methods which will be executed before and after an action gets executed
respectively. You can also make your own custom ActionFilters filter by implementing IActionFilter. For more about filters refer this
article Understanding ASP.NET MVC Filters and Attributes

6.

When action is executed, it process the user inputs with the help of model (Business Model or Data Model) and prepare Action Result.

Result Execution
1.

Result filters are executed before(OnResultnExecuting) and after(OnResultExecuted) the ActionResult is executed. IResultFilter interface
provides you two methods OnResultExecuting and OnResultExecuted methods which will be executed before and after an ActionResult gets
executed respectively. You can also make your own custom ResultFilters filter by implementing IResultFilter.

2.

Action Result is prepared by performing operations on user inputs with the help of BAL or DAL. The Action Result type can be
ViewResult, PartialViewResult, RedirectToRouteResult, RedirectResult, ContentResult, JsonResult, FileResult and EmptyResult.
Various Result type provided by the ASP.NET MVC can be categorized into two category- ViewResult type and NonViewResult type. The Result
type which renders and returns an HTML page to the browser, falls into ViewResult category and other result type which returns only data either
in text format, binary format or a JSON format, falls into NonViewResult category.

View Initialization and Rendering


1.

ViewResult type i.e. view and partial view are represented by IView(System.Web.Mvc.IView) interface and rendered by the appropriate
View Engine.
1.

public interface IView

147

2.

3.
4.
2.

void Render(ViewContext viewContext, TextWriter writer);


}
This process is handled by IViewEngine(System.Web.Mvc.IViewEngine) interface of the view engine. By default ASP.NET MVC provides

WebForm and Razor view engines. You can also create your custom engine by using IViewEngine interface and can registered your custom view
engine in to your Asp.Net MVC application as shown below:
1.

protected void Application_Start()

2.

3.

//Remove All View Engine including Webform and Razor

4.

ViewEngines.Engines.Clear();

5.

//Register Your Custom View Engine

6.

ViewEngines.Engines.Add(new CustomViewEngine());

7.
8.
3.

//Other code is removed for clarity


}
Html Helpers are used to write input fields, create links based on the routes, AJAX-enabled forms, links and much more. Html Helpers

are extension methods of the HtmlHelper class and can be further extended very easily. In more complex scenario, it might render a form with
client side validation with the help of JavaScript or jQuery.

Understanding ASP.NET MVC Filters and Attributes


ASP.NET MVC provides a simple way to inject your piece of code or logic either before or after an action is executed. This is achieved by
decorating the controllers or actions with ASP.NET MVC attributes or custom attributes. An attribute or custom attribute implements the ASP.NET
MVC filters(filter interface) and can contain your piece of code or logic. You can make your own custom filters or attributes either by
implementing ASP.NET MVC filter interface or by inheriting and overriding methods of ASP.NET MVC filter attribute class if available.
Typically, Filters are used to perform the following common functionalities in your ASP.NET MVC application.
47.

Custom Authentication

48.

Custom Authorization(User based or Role based)

49.

Error handling or logging

50.

User Activity Logging

51.

Data Caching

52.

Data Compression

Types of Filters
The ASP.NET MVC framework provides five types of filters.
12.

Authentication filters (New in ASP.NET MVC5)

13.

Authorization filters

14.

Action filters

15.

Result filters

16.

Exception filters

Authentication Filters
This filter is introduced with ASP.NET MVC5. The IAuthenticationFilter interface is used to create CustomAuthentication filter. The definition of this
interface is given below13. public interface IAuthenticationFilter
14. {
15.

void OnAuthentication(AuthenticationContext filterContext);

16.
17.

void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext);

18. }
You can create your CustomAuthentication filter attribute by implementing IAuthenticationFilter as shown below3.

public class CustomAuthenticationAttribute : ActionFilterAttribute, IAuthenticationFilter

148

4.

5.

public void OnAuthentication(AuthenticationContext filterContext)

6.

7.

//Logic for authenticating a user

8.

9.

//Runs after the OnAuthentication method

10.

public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)

11.

12.

//TODO: Additional tasks on the request

13.

14. }

Authorization Filters
The ASP.NET MVC Authorize filter attribute implements the IAuthorizationFilter interface. The definition of this interface is given below13. public interface IAuthorizationFilter
14. {
15.

void OnAuthorization(AuthorizationContext filterContext);

16. }
The AuthorizeAttribute class provides the following methods to override in the CustomAuthorize attribute class.
12. public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter
13. {
14.

protected virtual bool AuthorizeCore(HttpContextBase httpContext);

15.

protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext);

16.

public virtual void OnAuthorization(AuthorizationContext filterContext);

17.

protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext);

18. }
In this way you can make your CustomAuthorize filter attribute either by implementing IAuthorizationFilter interface or by inheriting and
overriding above methods of AuthorizeAttribute class.

Action Filters
Action filters are executed before or after an action is executed. The IActionFilter interface is used to create an Action Filter which provides two
methods OnActionExecuting and OnActionExecuted which will be executed before or after an action is executed respectively.
1.

public interface IActionFilter

2.

3.

void OnActionExecuting(ActionExecutingContext filterContext);

4.
5.

void OnActionExecuted(ActionExecutedContext filterContext);


}

Result Filters
Result filters are executed before or after generating the result for an action. The Action Result type can be ViewResult, PartialViewResult,
RedirectToRouteResult, RedirectResult, ContentResult, JsonResult, FileResult and EmptyResult which derives from the ActionResult class. Result
filters are called after the Action filters. The IResultFilter interface is used to create an Result Filter which provides two methods
OnResultExecuting and OnResultExecuted which will be executed before or after generating the result for an action respectively.
1.

public interface IResultFilter

2.

3.

void OnResultExecuted(ResultExecutedContext filterContext);

4.
5.

void OnResultExecuting(ResultExecutingContext filterContext);


}

149

Exception Filters
Exception filters are executed when exception occurs during the actions execution or filters execution. The IExceptionFilter interface is used to
create an Exception Filter which provides OnException method which will be executed when exception occurs during the actions execution or
filters execution.
1.

public interface IExceptionFilter

2.

3.
4.

void OnException(ExceptionContext filterContext);


}

ASP.NET MVC HandleErrorAttribute filter is an Exception filter which implements IExceptionFilter. When HandleErrorAttribute filter receives the
exception it returns an Error view located in the Views/Shared folder of your ASP.NET MVC application.

Order of Filter Execution


All ASP.NET MVC filter are executed in an order. The correct order of execution is given below:
1.

Authentication filters

2.

Authorization filters

3.

Action filters

4.

Result filters

Configuring Filters
You can configure your own custom filter into your application at following three levels:

1.

Global level

By registering your filter into Application_Start event of Global.asax.cs file with the help of FilterConfig class.
1.

protected void Application_Start()

2.

3.
4.

2.

FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
}

Controller level

By putting your filter on the top of the controller name as shown below1.

[Authorize(Roles="Admin")]

2.

public class AdminController : Controller

3.

4.
5.

3.

//
}

Action level

By putting your filter on the top of the action name as shown below1.

public class UserController : Controller

2.

3.

[Authorize(Users="User1,User2")]

4.

public ActionResult LinkLogin(string provider)

5.

6.

// TODO:

7.

return View();

8.
9.

}
}

150

Persisting Data with TempData


TempData is used to pass data from current request to subsequent request (means redirecting from one page to another). Its life is very short
and lies only till the target view is fully loaded. But you can persist data in TempData by calling Keep() method.

TempData with Keep method


If you want to keep value in TempData object after request completion, you need to call Keep method with in the current action. There are two
overloaded Keep methods to retains value after current request completion.

void Keep()

9.

Calling this method with in the current action ensures that all the items in TempData are not removed at the end of the current request.
1.
2.

@model MyProject.Models.EmpModel;
@{

3.

Layout = "~/Views/Shared/_Layout.cshtml";

4.

ViewBag.Title = "About";

5.

var tempDataEmployeet = TempData["emp"] as Employee; //need typcasting

6.
7.

TempData.Keep(); // retains all strings values


}

void Keep(string key)

10.

Calling this method with in the current action ensures that specific item in TempData is not removed at the end of the current request.
1.
2.

@model MyProject.Models.EmpModel;
@{

3.

Layout = "~/Views/Shared/_Layout.cshtml";

4.

ViewBag.Title = "About";

5.

var tempDataEmployeet = TempData["emp"] as Employee; //need typcasting

6.
7.

TempData.Keep("emp"); // retains only "emp" string values


}

Key point about TempData and TempData.Keep()


7.

Items in TempData will only tagged for deletion after they have read.

8.

Items in TempData can be untagged by calling TempData.Keep(key).

9.

RedirectResult and RedirectToRouteResult always calls TempData.Keep() to retain items in TempData.

Summary
In this article you have learned how to persist data in TempData. I hope you will refer this article for your need. I would like to have feedback
from my blog readers. Please post your feedback, question, or comments about this article.

Understanding HTML Helpers in ASP.NET MVC


An HTML Helper is just a method that returns a HTML string. The string can represent any type of content that you want. For example, you can
use HTML Helpers to render standard HTML tags like HTML <input>, <button> and <img> tags etc.
You can also create your own HTML Helpers to render more complex content such as a menu strip or an HTML table for displaying database data.

Different types of HTML Helpers


There are three types of HTML helpers as given below:

Inline Html Helpers

15.

These are create in the same view by using the Razor @helper tag. These helpers can be reused only on the same view.
1.

@helper ListingItems(string[] items)

2.

3.

<ol>

4.

@foreach (string item in items)

5.

6.

<li>@item</li>

7.

151

8.

</ol>

9.

10.
11.

<h3>Programming Languages:</h3>

12.
13.

@ListingItems(new string[] { "C", "C++", "C#" })

14.
15.

<h3>Book List:</h3>

16.
17.
16.

@ListingItems(new string[] { "How to C", "how to C++", "how to C#" })

Built-In Html Helpers

Built-In Html Helpers are extension methods on the HtmlHelper class. The Built-In Html helpers can be divided into three categories1.

Standard Html Helpers

These helpers are used to render the most common types of HTML elements like as HTML text boxes, checkboxes etc. A list of most common
standard html helpers is given below:

2.

Strongly Typed HTML Helpers

These helpers are used to render the most common types of HTML elements in strongly typed view like as HTML text boxes, checkboxes etc. The
HTML elements are created based on model properties.
The strongly typed HTML helpers work on lambda expression. The model object is passed as a value to lambda expression, and you can select
the field or property from model object to be used to set the id, name and value attributes of the HTML helper. A list of most common stronglytyped html helpers is given below:

152

3.

Templated HTML Helpers

These helpers figure out what HTML elements are required to render based on properties of your model class. This is a very flexible approach for
displaying data to the user, although it requires some initial care and attention to set up. To setup proper HTML element with Templated HTML
Helper, make use of DataType attribute of DataAnnitation class.
For example, when you use DataType as Password, A templated helper automatically render Password type HTML input element.

17.

Custom Html Helpers


153

You can also create your own custom helper methods by creating an extension method on the HtmlHelper class or by creating static methods
with in a utility class.
1.

public static class CustomHelpers

2.

3.

//Submit Button Helper

4.

public static MvcHtmlString SubmitButton(this HtmlHelper helper, string

5.

buttonText)

6.

7.

string str = "<input type=\"submit\" value=\"" + buttonText + "\" />";

8.

return new MvcHtmlString(str);

9.

10.

//Readonly Strongly-Typed TextBox Helper

11.

public static MvcHtmlString TextBoxFor<TModel, TValue>(this

12.

HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>>

13.

expression, bool isReadonly)

14.

15.

MvcHtmlString html = default(MvcHtmlString);

16.
17.

if (isReadonly)

18.

19.

html = System.Web.Mvc.Html.InputExtensions.TextBoxFor(htmlHelper,

20.

expression, new { @class = "readOnly",

21.

@readonly = "read-only" });

22.

23.

else

24.

25.

html = System.Web.Mvc.Html.InputExtensions.TextBoxFor(htmlHelper,

26.

expression);

27.

28.

return html;

29.

30. }

154

Understanding AJAX Helpers in ASP.NET MVC


AJAX Helpers are used to create AJAX enabled elements like as Ajax enabled forms and links which performs request asynchronously. AJAX
Helpers are extension methods of AJAXHelper class which exist in System.Web.Mvcnamespace.
>

Unobtrusive AJAX
ASP.NET MVC supports unobtrusive Ajax which is based on jQuery. The unobtrusive Ajax means that you use helper methods to define your Ajax
features, rather than adding blocks of code throughout your views.

Various configuration options for AJAX Helpers


The AjaxOptions class defines properties that allow you to specify callbacks for different stages in the AJAX request life cycle. There are following
properties provided by AjaxOptions class for AJAX helpers:

What is Cross Domain AJAX?


By default, web browsers allows AJAX calls only to your web applications site of origin i.e. site hosted server. This restriction help us to prevent
various security issues like cross site scripting (XSS) attacks. But, sometimes you need to interact with externally hosted API(s) like Twitter or
Google. Hence to interact with these external API(s) or services your web application must support JSONP requests or Cross-Origin Resource
Sharing (CORS). By default, ASP.NET MVC does not support JSONP or Cross-Origin Resource Sharing. For this you need to do a little bit of coding
and configuration.

155

Understanding ASP.NET MVC Scaffolding


Scaffolding is a technique used by many MVC frameworks like ASP.NET MVC, Ruby on Rails, Cake PHP and Node.JS etc., to generate code for
basic CRUD (create, read, update, and delete) operations against your database effectively. Further you can edit or customize this auto
generated code according to your need.
Scaffolding consists of page templates, entity page templates, field page templates, and filter templates. These templates are called Scaffold
templates and allow you to quickly build a functional data-driven Website.

How Scaffold templates works in ASP.NET MVC..


Scaffold templates are used to generate code for basic CRUD operations within your ASP.NET MVC applications against your database with the
help Entity Framework. These templates use the Visual Studio T4 templating system to generate views for basic CRUD operations with the help
of Entity Framework.

Steps to create ASP.NET MVC CRUD operations using scaffolding


11.

Adding controller to your project

12.

Choosing a scaffold template for creating CRUD operations

156

13.

Provide a name to your controller

The following actions are created for insert, update and delete operations based on scaffold template within User controller.

157

Layouts, RenderBody, RenderSection and RenderPage in ASP.NET MVC


Layouts are used to maintain a consistent look and feel across multiple views within ASP.NET MVC application. As compared to Web Forms,
layouts serve the same purpose as master pages, but offer a simple syntax and greater flexibility.

Basic structure of Layout Page


42. <!DOCTYPE html>
43. <html>
44. <head>
45.

<meta charset="utf-8" />

46.

<meta name="viewport" content="width=device-width" />

47.

<title>@ViewBag.Title</title>

48.

@Styles.Render("~/Content/css")

49.

@Scripts.Render("~/bundles/modernizr")

50. </head>
51. <body>
52.

@RenderBody()

53.
54.

@Scripts.Render("~/bundles/jquery")

55.

@RenderSection("scripts", required: false)

56. </body>
57. </html>
In Asp.Net MVC, at application level we have _ViewStart file with in Views folder for defining the default Layout page for your ASP.NET MVC
application. For rendering layout page refer this article Different ways of rendering layouts in Asp.Net MVC.

Styles.Render and Scripts.Render


Style.Render is used to render a bundle of CSS files defined within BundleConfig.cs files. Styles.Render create style tag(s) for the CSS bundle.
Like Style.Render, Scripts.Render is also used to render a bundle of Script files by rendering script tag(s) for the Script bundle.
11. public class BundleConfig
12. {

158

13.

public static void RegisterBundles(BundleCollection bundles)

14.

15.

bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(

16.

"~/Scripts/jquery.unobtrusive*",

17.

"~/Scripts/jquery.validate*"));

18.
19.

bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(

20.

"~/Content/themes/base/jquery.ui.core.css",

21.

"~/Content/themes/base/jquery.ui.resizable.css",

22.

"~/Content/themes/base/jquery.ui.selectable.css",

23.

"~/Content/themes/base/jquery.ui.button.css",

24.

"~/Content/themes/base/jquery.ui.dialog.css",

25.

"~/Content/themes/base/jquery.ui.theme.css"));

26.

27. }

Note
23.

Styles.Render and Scripts.Render generate multiple style and script tags for each item in the CSS bundle and Script bundle when
optimizations are disabled.

24.

When optimizations are enabled, Styles.Render and Scripts.Render generate a single style and script tag to a version-stamped URL
which represents the entire bundle for CSS and Scripts.
You can enable and disable optimizations by setting EnableOptimizations property of BundleTable class to true or false with in Global.asax.cs file
as shown below.
16. protected void Application_Start()
17. {
18.

//Other code has been removed for clarity

19.

System.Web.Optimization.BundleTable.EnableOptimizations = false;

20. }

Sections
A section allow you to specify a region of content within a layout. It expects one parameter which is the name of the section. If you dont provide
that, an exception will be thrown. A section in a layout page can be defined by using the following code.
16. @section header{
17. <h1>Header Content</h1>
18. }
You can render above defined section header on the content page as given below:
8.

@RenderSection("header")

By default, sections are mandatory. To make sections optional, just provides the second parameter value as false, which is a Boolean value.
68. @RenderSection("header",false)

Note
A view can define only those sections that are referred to in the layout page otherwise an exception will be thrown.

RenderBody
RenderBody method exists in the Layout page to render child page/view. It is just like the ContentPlaceHolder in master page. A layout page can
have only one RenderBody method.
34.

@RenderBody()

159

RenderPage
RenderPage method also exists in the Layout page to render other page exists in your application. A layout page can have multiple RenderPage
method.
8.

@RenderPage("~/Views/Shared/_Header.cshtml")

Understanding Attribute Routing in ASP.NET MVC


ASP.NET MVC5 and WEB API 2 supports a new type of routing, called attribute routing. In this routing, attributes are used to define routes.
Attribute routing provides you more control over the URIs by defining routes directly on actions and controllers in your ASP.NET MVC application
and WEB API. To know about convention-based routing referRouting in Asp.Net MVC with example.

Defining Attribute Routing in ASP.NET MVC


122.

Controller level attribute routing

You can define routes at controller level which apply to all actions within the controller unless a specific route is added to an action.
1.

[RoutePrefix("MyHome")]

2.

[Route("{action=index}")] //default action

3.

public class HomeController : Controller

4.

5.

//new route: /MyHome/Index

6.

public ActionResult Index()

7.

8.

return View();

9.

10.
11.

//new route: /MyHome/About

12.

public ActionResult About()

13.

14.

ViewBag.Message = "Your application description page.";

15.

return View();

16.

17.
18.

//new route: /MyHome/Contact

19.

public ActionResult Contact()

20.

21.

ViewBag.Message = "Your contact page."; return View();

22.

23. }

123.

Action level attribute routing

You can define routes at action level which apply to a specific action with in the controller.
1.

public class HomeController : Controller

2.

3.

[Route("users/{id:int:min(100)}")] //route: /users/100

4.

public ActionResult Index(int id)

5.

6.

//TO DO:

7.

return View();

8.

9.
10.

[Route("users/about")] //route" /users/about

11.

public ActionResult About()

12.

13.

ViewBag.Message = "Your application description page.";

14.

return View();

15.

160

16.
17.

//route: /Home/Contact

18.

public ActionResult Contact()

19.

20.

ViewBag.Message = "Your contact page.";

21.

return View();

22.

23. }

Note
379.

Attribute routing should configure before the convention-based routing.

380.

When you combine attribute routing with convention-based routing, actions which do not have Route attribute for defining attribute-

based routing will work according to convention-based routing. In above example Contact action will work according to convention-based
routing.
When you have only attribute routing, actions which do not have Route attribute for defining attribute-based routing will not be the part

381.

of attribute routing. In this way they cant be access from outside as a URI.

When to use Attribute Routing


The convention-based routing is complex to support certain URI patterns that are common in RESTful APIs. But by using attribute routing you can
define these URI patterns very easily.
For example, resources often contain child resources like Clients have orders, movies have actors, books have authors and so on. Its natural to
create URIs that reflects these relations like as: /clients/1/orders
This type of URI is difficult to create using convention-based routing. Although it can be done, the results dont scale well if you have many
controllers or resource types.
With attribute routing, its pretty much easy to define a route for this URI. You simply add an attribute to the controller action as:

155.

[Route("clients/{clientId}/orders")]

156.

public IEnumerable GetOrdersByClient(int clientId)

157.

158.

//TO DO

159.

Enabling Attribute Routing in ASP.NET MVC


Enabling attribute routing in your ASP.NET MVC5 application is simple, just add a call to routes.MapMvcAttributeRoutes() method with in
RegisterRoutes() method of RouteConfig.cs file.

78. public class RouteConfig


79. {
80.

public static void RegisterRoutes(RouteCollection routes)

81.

82.

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

83.
84.

//enabling attribute routing

85.

routes.MapMvcAttributeRoutes();

86.

87. }
You can also combine attribute routing with convention-based routing.

135.

public class RouteConfig

136.

137.

public static void RegisterRoutes(RouteCollection routes)

138.

139.

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

140.
141.

//enabling attribute routing

142.

routes.MapMvcAttributeRoutes();

143.

161

144.

//convention-based routing

145.

/routes.MapRoute(

146.

name: "Default",

147.

url: "{controller}/{action}/{id}",

148.

defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });

149.

150.

151.

Defining Attribute Routing for Area in ASP.NET MVC


You can also define attribute routing for a controller that belongs to an area by using the RouteArea attribute. When you define attribute routing
for all controllers with in an area, you can safely remove the AreaRegistration class for that area.

91. [RouteArea("Admin")]
92. [RoutePrefix("menu")]
93. [Route("{action}")]
94. public class MenuController : Controller
95. {
96.

// route: /admin/menu/login

97.

public ActionResult Login()

98.

99.

return View();

100.

101.
102.

// route: /admin/menu/products

103.

[Route("products")]

104.

public ActionResult GetProducts()

105.

106.

return View();

107.

108.
109.

// route: /categories

110.

[Route("~/categories")]

111.

public ActionResult Categories()

112.

113.

return View();

114.

115.
116.

[Route("customers/{customerId}/orders")]

117.

public IEnumerable GetOrdersByCustomer(int customerId)

118.

119.

//TO DO

120.

121.

162

Você também pode gostar