MVC Questions & Answers
MVC Questions & Answers
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.
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
3.
ASP.NET MVC framework components were designed to be pluggable and extensible and therefore can be replaced or customized easier then
Web Forms.
4.
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 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.
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.
2.
3.
$("#" + defaultbtn).click();
4.
return false;
5.
6.
});
7.
});
8.
</script>
9.
10. {
11.
@Html.TextBox("txtname")
12.
13.
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
1.
2.
3.
4.
5.
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.
3.
4.
5.
6.
TempData
1.
TempData is a dictionary object that is derived from TempDataDictionary class and stored in short lives session.
1.
2.
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.
2.
3.
Session is also used to pass data within the ASP.NET MVC application and Unlike TempData, it never expires.
4.
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.
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.
2.
3.
4.
5.
[MaxLength(50)]
6.
7.
8.
[Display(Name = "Password")]
9.
[MaxLength(50)]
10.
11. }
@model MyModels.UserLoginViewModel
@{
3.
4.
Layout = "~/Views/Shared/_Layout.cshtml";
5.
6.
@using (Html.BeginForm())
7.
8.
<div class="editor-label">
9.
10. </div>
11. <div class="editor-field">
12.
13.
14. </div>
15. <div class="editor-label">
16.
17. </div>
18. <div class="editor-field">
19.
20.
21. </div>
22. <p>
23.
24. </p>
25. </div>
26. }
2.
3.
return View();
4.
5.
[HttpPost]
6.
7.
8.
9.
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.
22.
23.
24.
25.
26.
27.
28.
return View(user);
29. }
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.
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.
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.
DataType
2.
DisplayName
3.
DisplayFormat
specify the display format for a property like different format for Date proerty.
4.
Required
5.
ReqularExpression
6.
Range
7.
StringLength
8.
MaxLength
9.
Bind
specify fields to include or exclude when adding parameter or form values to model properties.
10.
ScaffoldColumn
5
using System.ComponentModel;
3.
using System.ComponentModel.DataAnnotations;
4.
using System.Web.Mvc;
5.
namespace Employee.Models
6.
7.
[Bind(Exclude = "EmpId")]
8.
9.
10.
[ScaffoldColumn(false)]
11.
12.
13.
[DisplayName("Employee Name")]
14.
15.
[StringLength(100,MinimumLength=3)]
16.
17.
18.
19.
[StringLength(300)]
20.
21.
22.
23.
24.
25.
26.
27.
[DataType(DataType.EmailAddress)]
28.
29.
[MaxLength(50)]
30.
[RegularExpression(@"[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}",
ErrorMessage
"Please
enter
correct
email")]
31.
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.
src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"
type="text/javascript"></script>
@model Employee.Models
@{
3.
4.
Layout = "~/Views/Shared/_Layout.cshtml";
5.
6.
@using (Html.BeginForm())
7.
8.
<div class="editor-label">
9.
10.
</div>
11.
<div class="editor-field">
12.
13.
14.
</div>
15.
<div class="editor-label">
16.
17.
</div>
18.
<div class="editor-field">
19.
20.
21.
</div>
22.
<div class="editor-label">
23.
24.
</div>
25.
<div class="editor-field">
26.
27.
28.
</div>
29.
<div class="editor-label">
30.
31.
</div>
32.
<div class="editor-field">
33.
34.
35.
</div>
36.
37.
</p>
38. }
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.
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.
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.
<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.
CSS Class
1.
2.
.inputclass
{
3.
width:100px;
4.
height:25px;
5.
@if (false)
2.
3.
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
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
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
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.
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.
2.
3.
4.
ViewEngines.Engines.Clear();
5.
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
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.
2.
3.
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
4.
5.
6.
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.
2.
3.
SecurityUtil.ProcessInApplicationTrust(delegate {
4.
IController controller;
5.
IControllerFactory factory;
6.
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.
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.
2.
3.
4.
ViewEngines.Engines.Clear();
5.
6.
ViewEngines.Engines.Add(new CustomViewEngine());
7.
8.
7.
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.
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:
MultipleCommand.cshtml
1.
2.
3.
<fieldset>
4.
<legend>Registration Form</legend>
5.
<ol>
6.
<li>
7.
8.
9.
10.
</li>
11.
<li>
12.
13.
14.
15.
</li>
16.
<li>
17.
18.
19.
20.
</li>
21.
</ol>
22.
23.
24.
<button
type="submit"
id="btnCancel"
name="Command"
value="Cancel"
onclick="$
</fieldset>
26. }
18
MultipleCommand.cshtml
1.
2.
3.
<fieldset>
4.
<legend>Registration Form</legend>
5.
<ol>
6.
<li>
7.
8.
9.
10.
</li>
11.
<li>
12.
13.
14.
15.
</li>
16.
<li>
17.
18.
19.
20.
</li>
21.
</ol>
22.
23.
24.
<button
type="submit"
id="btnCancelSecForm"
name="Command"
value="Cancel"
onclick="$
</fieldset>
26. }
27. @using (Html.BeginForm("MultipleButtonCancel", "Home", FormMethod.Post, new { id = "cancelForm" })) { }
19
MultipleCommand.cshtml
1.
2.
3.
<button
name="ClientCancel"
type="button"
onclick="
document.location.href
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
public DataContext()
15.
: base("DefaultConnection")
16.
17.
18.
19.
20.
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
@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.
8.
<script>
9.
$(document).ready(function () {
10.
11.
$("#dialog-alert").dialog({
12.
autoOpen: false,
13.
resizable: false,
14.
height: 170,
15.
width: 350,
16.
17.
modal: true,
18.
draggable: true,
19.
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.
39.
autoOpen: false,
40.
resizable: false,
41.
width: 400,
42.
43.
modal: true,
44.
draggable: true,
45.
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.
57.
modal: true,
58.
draggable: true,
59.
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.
76.
autoOpen: false,
77.
resizable: false,
78.
width: 400,
79.
80.
modal: true,
81.
draggable: true,
82.
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.
94.
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>
2.
3.
4.
5.
// GET: /User/
6.
7.
8.
return View(db.Users.ToList());
9.
10.
11.
// GET: /User/Details/5
12.
13.
14.
15.
if (user == null)
16.
17.
return HttpNotFound();
18.
19.
return View(user);
20.
21.
22.
// GET: /User/Create
23.
24.
25.
return PartialView();
26.
26
27.
28.
// POST: /User/Create
29.
[HttpPost]
30.
[ValidateAntiForgeryToken]
31.
32.
33.
if (ModelState.IsValid)
34.
35.
db.Users.Add(user);
36.
db.SaveChanges();
37.
38.
return RedirectToAction("Index");
39.
40.
41.
return View(user);
42.
43.
44.
// GET: /User/Edit/5
45.
46.
47.
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.
59.
60.
if (ModelState.IsValid)
61.
62.
db.Entry(user).State = EntityState.Modified;
63.
db.SaveChanges();
64.
65.
return RedirectToAction("Index");
66.
67.
return View(user);
68.
69.
70.
// GET: /User/Delete/5
71.
72.
73.
74.
db.Users.Remove(user);
75.
db.SaveChanges();
76.
77.
return RedirectToAction("Index");
78.
79.
80.
81.
82.
db.Dispose();
83.
base.Dispose(disposing);
27
84.
85.
2.
RegistrationModel.cs
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11. }
12.
13. public class Country
14. {
15.
16.
17. }
18.
19. public class City
20. {
21.
22.
23.
24. }
ExplicitServer.cshtml
1.
2.
3.
@model Mvc4_Client_ServerSideValidation.Models.RegistrationModel
@{
ViewBag.Title = "Explicit Server Side Validation";
28
4.
5.
6.
<script type="text/jscript">
7.
$(function () {
8.
$('#Country_ID').change(function () {
9.
10.
if (id != "") {
11.
$.ajax({
12.
type: "GET",
13.
14.
15.
data: { "mCountry": id },
16.
dataType: "json",
17.
18.
19.
20.
21.
});
22.
$('#City_ID').html(items);
23.
},
24.
25.
26.
27.
});
28.
29.
else
30. {
31.
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.
42.
43.
44.
</li>
45.
<li>
46.
47.
48.
49.
</li>
50.
<li>
51.
52.
53.
54.
</li>
55.
<li>
56.
57.
58.
59.
</li>
29
60.
<li>
61.
62.
@Html.DropDownListFor(m
=>
m.City.ID,
new
SelectList(ViewBag.City,
"ID",
"Name"),
new
style
"width:310px" })
63.
64.
</li>
65.
<li>
66.
67.
68.
69.
</li>
70.
<li>
71.
72.
73.
74.
</li>
75.
<li>
76.
77.
78.
</li>
79.
</ol>
80.
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.
3.
4.
5.
if (string.IsNullOrEmpty(mRegister.UserName))
6.
7.
8.
9.
if (!string.IsNullOrEmpty(mRegister.UserName))
10.
11.
12.
if (!emailRegex.IsMatch(mRegister.UserName))
13.
14.
15.
if (string.IsNullOrEmpty(mRegister.Password))
16.
17.
18.
1.
if (string.IsNullOrEmpty(mRegister.ConfirmPassword))
2.
3.
4.
5.
30
6.
7.
if (mRegister.ConfirmPassword != mRegister.Password)
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
if (string.IsNullOrEmpty(mRegister.Address))
19.
20.
21.
22.
if (string.IsNullOrEmpty(mRegister.MobileNo))
23.
24.
25.
26.
if (!mRegister.TermsAccepted)
27.
28.
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.
RegistrationModel.cs
1.
2.
3.
4.
5.
33
6.
7.
8.
9.
[StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
10.
[DataType(DataType.Password)]
11.
[Display(Name = "Password")]
12.
13.
14.
15.
[StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
16.
[DataType(DataType.Password)]
17.
18.
19.
20.
21.
22.
23.
24.
[Display(Name = "City")]
25.
26.
27.
28.
29.
[Display(Name = "Address")]
30.
[MaxLength(200)]
31.
32.
34
33.
34.
[Display(Name = "Mobile")]
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
return false;
55.
else
56.
return true;
57.
58.
59.
35
60.
61.
62.
63.
64.
return false;
65.
else
66.
return true;
67.
68.
ServerMeta.cshtml
1.
@model Mvc4_Model_ServerSideValidation.Models.RegistrationMetaModel
2.
@{
3.
4.
5.
6.
<script type="text/jscript">
7.
$(function ()
8.
9.
$('#Country_ID').change(function ()
10.
11.
12.
if (id != "")
13.
14.
$.ajax({
15.
type: "GET",
16.
17.
18.
data: { "mCountry": id },
36
19.
dataType: "json",
20.
beforeSend: function () {
21.
},
22.
23.
24.
25.
26.
});
27.
$('#City_ID').html(items);
28.
},
29.
30.
31.
32.
});
33.
34.
else {
35.
36.
$('#City_ID').html(items);
37.
38.
});
39.
});
40.
</script>
41.
42.
@using (Html.BeginForm())
43.
44.
<fieldset>
45.
<ol>
37
46.
<li>
47.
48.
49.
50.
</li>
51.
<li>
52.
53.
54.
55.
</li>
56.
<li>
57.
58.
59.
60.
</li>
61.
<li>
62.
63.
@Html.DropDownListFor(m => m.Country.ID, new SelectList(ViewBag.Country, "ID", "Name", ViewBag.SelCountry), new { style = "width:310px"
})
64.
65.
</li>
66.
<li>
67.
68.
@Html.DropDownListFor(m => m.City.ID, new SelectList(ViewBag.City, "ID", "Name", ViewBag.SelCity), new { style = "width:310px" })
69.
70.
</li>
71.
<li>
72.
38
73.
74.
75.
</li>
76.
<li>
77.
78.
79.
80.
</li>
81.
<li>
82.
83.
84.
</li>
85.
</ol>
86.
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.
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
42
2.
3.
The order of included files as shown above, is fixed since below javascript library depends on top javascript library.
<appSettings>
2.
3.
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.
2.
3.
4.
HtmlHelper.ClientValidationEnabled = true;
5.
HtmlHelper.UnobtrusiveJavaScriptEnabled = true;
6.
@model MvcApp.Models.Appointment
2.
@{
3.
4.
HtmlHelper.ClientValidationEnabled = false;
5.
6.
...
43
How to do it..
Follow the following steps for making and validating cascading dropdown list in mvc razor.
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.
13.
14.
15.
16.
[Display(Name = "Country")]
17.
18.
[Display(Name = "City")]
19.
20.
21.
[Display(Name = "Address")]
22.
[StringLength(200)]
23.
24.
27. {
28.
29.
30.
return false;
31.
32. }
33. // Implement IClientValidatable for client side Validation
34. public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
35. {
36. return new ModelClientValidationRule[]
37. {
38.
39. }
40. }
41.
42.
46.
47.
48. {
49. [MustBeSelectedAttribute(ErrorMessage = "Please Select City")]
50. public int? ID { get; set; }
51. public string Name { get; set; }
52.
44
53. }
54. }
@model Mvc4_Validate_CascadingDropdown.Models.RegistrationModel
2.
3.
4.
5.
6.
7.
<script type="text/jscript">
8.
9.
10.
11.
options.rules["required"] = true;
12.
if (options.message) {
13.
options.messages["required"] = options.message;
14.
15.
16.
});
17.
$(function () {
18.
19. $('#Country_ID').change(function () {
20.
21.
if (id != "") {
22.
$.ajax({
23.
type: "GET",
24.
25.
26.
data: { "mCountry": id },
27.
dataType: "json",
28.
beforeSend: function () {
29.
//alert(id);
30. },
31.
32.
33.
34.
35.
});
36.
37. $('#City_ID').html(items);
38.
},
39.
40.
41.
42.
});
43.
44.
else {
45.
46.
$('#City_ID').html(items);
47.
48.
});
49.
});
50. </script>
51. <h2>Custom Validation for Cascading Dropdown List</h2>
45
=>
m.Country.ID,
new
SelectList(ViewBag.Country,
"ID",
"Name",
71.
76. </fieldset>
77.
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.
10.
11.
void BindCountry() {
12.
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.
20.
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.
46
38.
39.
select c;
40.
ViewBag.City = city;
41.
42.
else {
43.
ViewBag.City = City;
46.
47.
48.
49.
50.
51.
#endregion
52.
53.
54.
try {
55.
if (mCountry != 0) {
56. //below code is only for demo, you can pick city from database
57.
int index = 1;
58.
70.
71.
select c;
72.
73.
74. }
75.
76.
77.
return Json(null);
78. }
79.
80.
81.
return View();
82.
83.
47
84.
85.
BindCountry();
86.
BindCity(0);
87.
return View();
88.
89.
[HttpPost]
90.
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
How to do it..
Follow the following steps for validating checkbox in mvc razor.
2.
3.
4.
5.
6.
[Display(Name = "Address")]
7.
8.
9.
20. public
IEnumerable<ModelClientValidationRule>
GetClientValidationRules(ModelMetadata
metadata,
ControllerContext context)
21.
22.
23.
24.
25. }
@model Mvc4_Model_ServerSideValidation.Models.RegistrationModel
2.
@{
3.
4.
5.
6.
7.
8.
<script type="text/jscript">
9.
14.
options.rules["required"] = true;
15.
if (options.message) {
16.
options.messages["required"] = options.message;
17.
18.
19.
}); </script>
50
<fieldset>
How it works..
Now, you have applied the custom validation to the checkbox. This validation works for client-side and server side.
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.
2.
3.
4.
[Display(Name = "UserName")]
5.
6.
7.
8.
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.
13.
14.
15.
[StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
16.
[DataType(DataType.Password)]
17.
18.
19.
20.
21.
[Display(Name = "Country")]
22.
23.
24.
[Display(Name = "City")]
25.
26.
27.
28.
[Display(Name = "Address")]
29.
[StringLength(200)]
30.
31.
32.
33.
[Display(Name = "Mobile")]
34.
35.
36.
37.
38.
39. }
40.
41. public
class
MustBeTrueAttribute
ValidationAttribute,
IClientValidatable
//
IClientValidatable
for
44.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
public class MustBeSelected : ValidationAttribute, IClientValidatable // IClientValidatable for client side Validation
52
32.
33.
34.
35.
36.
return false;
37.
else
38.
return true;
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
53
59.
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.
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
87.
88.
BindCountry();
89.
BindCity(0);
90.
return View();
91.
92.
93.
[HttpPost]
94.
95.
96.
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
2.
3.
routes.MapRoute(
4.
5.
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
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.
routes.MapRoute(
2.
3.
4.
new
{ controller
= "Home", action
"Index", id
UrlParameter.Optional }
parameters
5.
);
routes.MapRoute(
2.
3.
4.
5.
6.
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.
routes.MapRoute(
2.
3.
4.
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.
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.
3.
4.
new
{ controller
= "Home", action
"Index", id
UrlParameter.Optional }
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
routes.MapRoute(
2.
3.
4.
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.
3.
4.
5.
6.
new[] { "Mvc4_RouteConstraints"});
);
7.
8.
routes.MapRoute(
9.
10.
11.
12.
new[] { "Mvc4_Route"});
13. );
63
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.
2.
3.
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.
5.
6.
7.
8.
get
9.
10.
return "Department";
11.
12.
13.
14.
15.
16.
context.MapRoute(
17.
"Department_default",
18.
"Department/{controller}/{action}/{id}",
19.
20.
);
21.
22.
23. }
Populating Area
Now you can create controllers, views, and models in the Department area like as below.
65
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.
bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.min.css",
2.
"~/Content/mystyle.min.css"));
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.
2.
3.
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. }
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.
2.
3.
BundleConfig.RegisterBundles(BundleTable.Bundles);
4.
5.
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.
67
2.
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.
@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.
2.
3.
BundleConfig.RegisterBundles(BundleTable.Bundles);
4.
5.
BundleTable.EnableOptimizations = true;
6.
7.
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
71
Creating Bundle
Now create the bundle for your css and js files with in the Global.asax file as shown below.
1.
2.
3.
4.
bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/mystyle.min.css",
5.
"~/Content/site.min.css"));
6.
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.
2.
3.
RegisterBundles(BundleTable.Bundles);
4.
5.
@System.Web.Optimization.Styles.Render("~/Content/css")
2.
@System.Web.Optimization.Scripts.Render("~/bundles/jquery")
72
In
1.
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.
3.
<pages>
4.
<namespaces>
5.
6.
</namespaces>
7.
<controls>
8.
<add
assembly="Microsoft.AspNet.Web.Optimization.WebForms"
</controls>
10.
</pages>
2.
3.
BundleConfig.RegisterBundles(BundleTable.Bundles);
4.
5.
BundleTable.EnableOptimizations = true;
6.
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.
Advantage of Caching
73
1.
When content is cached at the client or in proxies, it cause minimum request to server.
2.
When content is cached at the web server, it can eliminate the database request.
3.
When content is cached at the client side, it it also reduce the network traffic.
4.
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.
2.
3.
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.
[OutputCache(Duration=20, VaryByParam="none")]
2.
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(Duration
7200,
Location
OutputCacheLocation.Client,
VaryByParam
"none",
NoStore
true)]
2.
3.
4.
5.
6.
return View();
}
75
The Model can be broken down into several different layers as given below:
1.
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.
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.
76
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:
[Authorize(Users = "shailendra,mohan")]
2.
3.
4.
5.
return View();
}
[Authorize(Roles = "Admin,SubAdmin")]
2.
3.
4.
5.
return View();
}
78
How to do it..
Step 1 : Designing model with data annotation validation
1.
2.
3.
4.
5.
6.
7.
8.
[Display(Name = "Address")]
9.
[MaxLength(200)]
10.
11.
12.
13.
14.
[ValidateFile]
15.
16. }
17.
18. //Customized data annotation validator for uploading file
19. public class ValidateFileAttribute : ValidationAttribute
20. {
21.
22.
23.
24.
25.
26.
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.
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. }
79
2.
3.
4.
5.
6.
<fieldset>
7.
<legend></legend>
8.
<ol>
9.
<li>
10.
11.
12.
13.
</li>
14.
<li>
15.
16.
17.
18.
</li>
19.
<li class="lifile">
20.
21.
22.
</li>
23.
</ol>
24.
25.
</fieldset>
26. }
<script type="text/jscript">
2.
3.
function GetFileSize(fileid) {
4.
try {
5.
var fileSize = 0;
6.
//for IE
7.
if ($.browser.msie) {
8.
9.
10.
11.
12.
13.
14.
15.
16.
else {
17.
18.
19.
20.
21.
return fileSize;
22.
23.
catch (e) {
24.
25.
26. }
27.
28. //get file path from client system
29. function getNameFromPath(strFilepath) {
80
30.
31.
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.
44.
if (file != null) {
45.
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.
59.
return false;
60.
61.
else {
62.
63.
if (size > 3) {
64.
65.
66.
else {
67.
68.
69.
70.
});
71. });
72. </script>
2.
3.
4.
return View();
}
5.
6.
[HttpPost]
7.
8.
9.
10.
if (ModelState.IsValid)
11.
81
12.
//TO:DO
13.
14.
15.
mRegister.file.SaveAs(path);
16.
17.
ModelState.Clear();
18.
19.
return View();
20. }
How it works...
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.
2.
3.
4.
5.
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.
13.
.Skip((pageNumber - 1) * pageSize)
14.
.Take(pageSize)
15.
.ToList();
16.
17.
18.
.Skip((pageNumber - 1) * pageSize)
19.
.Take(pageSize)
20.
.ToList();
21.
22.
23.
.Skip((pageNumber - 1) * pageSize)
24.
.Take(pageSize)
25.
.ToList();
26.
else
27.
28.
.Skip((pageNumber - 1) * pageSize)
29.
.Take(pageSize)
30.
.ToList();
31.
32.
33.
34.
return entities.Customers.Count();
35.
36.
37.
38.
39.
entities.Dispose();
40.
41. }
83
42.
43. public class PagedCustomerModel
44. {
45.
46.
47.
48. }
2.
3.
4.
5.
6.
7.
: source.OrderBy(keySelector);
8.
9.
10.
11.
The View
Now design the view based on the above developed model as show below
1.
@model Mvc4_CustomWebGrid.Models.PagedCustomerModel
2.
@{
3.
4.
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.
17.
18.
19.
20.
columns: new[] {
21.
22.
grid.Column("Name"),
23.
grid.Column("Address"),
24.
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.
2.
3.
4.
5.
public ActionResult WebGridCustomPaging(int page = 1, string sort = "custid", string sortDir = "ASC")
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
TotalRows = totalRows,
16.
PageSize = pageSize,
17.
Customer = customer
18.
};
19.
return View(data);
20.
21. }
How it works..
85
86
2.
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.
291.
292.
293.
294.
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.
302.
.Skip((pageNumber - 1) * pageSize)
303.
.Take(pageSize)
304.
.ToList();
305.
306.
307.
.Skip((pageNumber - 1) * pageSize)
308.
.Take(pageSize)
87
309.
.ToList();
310.
311.
312.
.Skip((pageNumber - 1) * pageSize)
313.
.Take(pageSize)
314.
.ToList();
315.
else
316.
317.
.Skip((pageNumber - 1) * pageSize)
318.
.Take(pageSize)
319.
.ToList();
320.
321.
322.
323.
return entities.Customers.Count();
324.
325.
326.
327.
328.
entities.Dispose();
329.
330.
331.
332.
333.
334.
335.
336.
337.
119.
120.
121.
122.
123.
124.
: source.OrderBy(keySelector);
125.
126.
127.
128.
129.
<func {</func
130.
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.
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.
58.
grid.Pager(WebGridPagerModes.All);
59.
60.
61.
fillEmptyRows: false,
62.
alternatingRowStyle: "alternate-row",
63.
headerStyle: "grid-header",
64.
footerStyle: "grid-footer",
65.
mode: WebGridPagerModes.All,
66.
67.
68.
69.
70.
columns: new[] {
71.
72.
grid.Column("Name"),
73.
grid.Column("Address"),
74.
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.
72.
73.
public ActionResult WebGridCustomPaging(int page = 1, string sort = "custid", string sortDir = "ASC")
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
TotalRows = totalRows,
84.
PageSize = pageSize,
85.
Customer = customer
86.
};
87.
return View(data);
88.
89. }
How it works..
89
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.
2.
3.
@Html.ValidationSummary();
4.
<ol>
5.
<li class="lifile">
6.
7.
8.
</li>
9.
</ol>
10.
11. }
<script type="text/jscript">
2.
3.
function GetFileSize(fileid) {
4.
try
5.
6.
var fileSize = 0;
7.
//for IE
8.
if ($.browser.msie)
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
else
19.
20.
21.
22.
23.
return fileSize;
24.
25.
catch (e)
26.
27.
28.
29. }
30.
31. //get file path from client system
32. function getNameFromPath(strFilepath)
33. {
34.
35.
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.
52.
return false;
53.
54.
else
55.
56.
return checkfile();
57.
58. });
59.
60. function checkfile()
61. {
62.
63.
if (file != null)
64.
65.
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.
81.
return false;
82.
83.
else
84.
85.
86.
if (size > 3)
87.
88.
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>
[HttpPost]
2.
3.
4.
if (ModelState.IsValid)
5.
6.
if (file == null)
7.
8.
9.
10.
11.
12.
13.
14.
15.
if (!AllowedFileExtensions.Contains(file.FileName.Substring(file.FileName.LastIndexOf('.'))))
16.
17.
18.
19.
20.
21.
22.
ModelState.AddModelError("File", "Your file is too large, maximum allowed size is: " + MaxContentLength +
" MB");
23.
24.
else
25.
26.
//TO:DO
27.
28.
29.
file.SaveAs(path);
30.
ModelState.Clear();
31.
32.
33.
34.
35.
return View();
36. }
How it works...
93
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.
3.
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.
2.
This method result can be stored in a variable, since it returns string type value.
3.
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.
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
Populating WebGrid
The Model
First of all design the customer model using Entity Framework database first approach as show below
1.
2.
3.
4.
5.
6.
7.
Now design the model for querying the data from customer table and populating it to the GridView
1.
2.
3.
4.
5.
6.
7.
: source.OrderBy(keySelector);
8.
9.
10.
11.
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
The View
Now design the view based on the above developed model as show below
1.
@model Mvc4_WebGrid_CRUD.Models.PagedCustomerModel
2.
@{
3.
4.
5.
6.
);
7.
8.
9.
15.
fillEmptyRows: false,
16.
mode: WebGridPagerModes.All,
97
17.
18.
19.
20.
21.
columns: new[] {
22.
23.
24.
grid.Column(header:
"Name",format:
@<span>
<span
id="[email protected]">@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="[email protected]">@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="[email protected]">@item.ContactNo</span>
@<span>
<span
@Html.TextBox("ContactNo_"+(int)item.CustID,
(string)item.ContactNo,new{@style="display:none"})</span>),
29.
30.
id="[email protected]"
id="[email protected]"
style="display:none"
style="display:none"
class="update">Update</a><a
class="cancel">Cancel</a><a
href="#"
href="#"
id="[email protected]" 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.
2.
3.
4.
5.
public ActionResult WebGridCRUD(int page = 1, string sort = "custid", string sortDir = "ASC")
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
TotalRows = totalRows,
16.
PageSize = pageSize,
17.
Customer = customer
18.
};
19.
return View(data);
20.
21. }
Insert Operation
The Model
1.
2.
3.
try
98
4.
5.
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.
5.
if (existrow == 0) {
6.
7.
8.
9.
10.
11.
12.
13.
14.
var
tr
'<tr
class="alternate-row"><td></td><td><span>
<input
id="'
Name
'"
type="text"
/></span></td>' +
15.
16.
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.
24.
25.
26.
});
27.
28. $(".icancel").live("click", function () {
29.
30.
if (flag) {
31.
$(this).parents("tr").remove();
32.
33. });
34.
35. $(".save").live("click", function () {
36.
37.
99
38.
39.
40.
41.
if (id != "") {
42.
$.ajax({
43.
type: "GET",
44.
45.
46.
47.
dataType: "json",
48.
beforeSend: function () { },
49.
50.
if (data.result == true) {
51.
52.
53.
54.
else {
55.
56.
57.
58.
});
59.
60. });
61. <script>
The Controller
1.
[HttpGet]
2.
3.
4.
5.
try
6.
7.
8.
9.
10.
11.
12.
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.
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.
4.
id = str[1];
5.
6.
7.
8.
9.
10.
11.
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.
27.
id = str[1];
28.
29.
30.
31.
32.
33.
34.
35.
36.
if (id != "") {
37.
$.ajax({
38.
type: "GET",
39.
40.
41.
42.
dataType: "json",
43.
44.
},
45.
46.
if (data.result == true) {
47.
$("#Update_" + id).hide();
48.
$("#Cancel_" + id).hide();
49.
$("#Edit_" + id).show();
50.
51.
52.
53.
54.
55.
102
56.
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.
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.
5.
try
6.
7.
8.
9.
10.
11.
12.
13.
14. }
How it works..
103
Delete Operation
The Model
1.
2.
3.
try
4.
5.
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.
4.
id = str[1];
5.
6.
7.
8.
$.ajax({
9.
type: "GET",
10.
11.
12.
data: { "id": id },
13.
dataType: "json",
14.
beforeSend: function () { },
15.
16.
if (data.result == true) {
17.
$("#Update_" + id).parents("tr").remove();
18.
19.
else {
20.
21.
22.
23.
});
104
24.
25. });
26. <script>
The Controller
1.
2.
3.
try
4.
5.
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
Removing All the View Engines & registering the Razor Engine
1.
2.
3.
4.
ViewEngines.Engines.Clear();
5.
6.
ViewEngines.Engines.Add(new RazorViewEngine());
7.
8.
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.
106
65.
66.
67.
ViewEngines.Engines.Clear();
68.
69.
ViewEngines.Engines.Add(new CSharpRazorViewEngine());
70.
71.
107
108
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.
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.
74.
75.
[DonutOutputCache(CacheProfile="TwoMins")]
76.
77.
78.
[DonutOutputCache(Duration=60, VaryByCustom="whatever")]
79.
80.
81.
[DonutOutputCache(Duration=60, VaryByParam="something;that")]
82.
83.
84.
[DonutOutputCache(Duration=60, VaryByParam="none")]
85.
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. }
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.
87.
88.
return View();
89.
90.
91.
[HttpPost]
92.
93.
94.
95.
96.
return View("MyIndex");
97.
98.
99.
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.
112
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.
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.
2.
3.
return View();
4.
5.
6.
[HttpPost]
7.
8.
9.
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.
2.
3.
routes.MapRoute(
4.
5.
"Account/", // URL
6.
7.
);
8.
9.
routes.MapRoute(
10.
11.
12.
13.
);
14. }
HomeController
1.
2.
3.
4.
5.
return View();
}
6.
7.
[HttpPost]
8.
9.
10.
return RedirectToRoute("MyRoute");
11. }
114
AccountController
1.
2.
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.
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(false)]
3.
4.
5.
6.
7.
return View();
8.
9.
10.
[HttpPost]
11.
12.
13.
if (ModelState.IsValid)
14.
15.
16.
17.
return View();
18.
19. }
Now, the user can submit Html for this Controller successfully.
3.
4.
5.
6.
return View();
7.
8.
9.
[ValidateInput(false)]
10.
[HttpPost]
11.
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.
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.
5.
6.
[Required]
7.
[Display(Name = "Title")]
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.
4.
</system.web>
HandleError Attribute can be used to handle error at Action Method level, Controller level and Global level.
2.
3.
4.
5.
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.
2.
3.
4.
5.
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.
2.
3.
filters.Add(new HandleErrorAttribute
4.
5.
ExceptionType = typeof(System.Data.DataException),
6.
View = "DatabaseError"
7.
});
8.
9.
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.
2.
3.
4.
filters.Add(new HandleErrorAttribute
5.
6.
ExceptionType = typeof(System.Data.DataException),
7.
View = "DatabaseError"
8.
9.
},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 .
2.
3.
4.
5.
if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
6.
7.
return;
8.
9.
10.
11.
12.
return;
13.
14.
15.
if (!ExceptionType.IsInstanceOfType(filterContext.Exception))
16.
17.
return;
18.
19.
20.
21.
if (filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
22.
23.
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.
36.
37.
38.
39.
40.
41.
ViewName = View,
42.
MasterName = Master,
43.
44.
TempData = filterContext.Controller.TempData
45.
};
46.
47.
48.
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. }
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.
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. }
2.
3.
4.
//TO DO:
5.
6.
@{
2.
3.
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
1.
@{
2.
3.
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
121
Asp.Net MVC1
1.
2.
Runs on .Net 3.5 and with Visual Studio 2008 & Visual Studio 2008 SP1
3.
4.
Html Helpers
5.
Ajax helpers
6.
Routing
7.
Unit Testing
Asp.Net MVC2
1.
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.
6.
Client-side validation
7.
8.
9.
Overriding the HTTP Method Verb including GET, PUT, POST, and DELETE
10.
11.
Asynchronous controllers
Asp.Net MVC3
1.
2.
3.
4.
5.
Remote Validation
6.
Compare Attribute
7.
Sessionless Controller
8.
9.
Dependency Resolver
10.
11.
12.
13.
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.
Asp.Net MVC4
1.
2.
Runs on .Net 4.0, 4.5 and with Visual Studio 2010SP1 & Visual Studio 2012
3.
4.
122
5.
6.
Display Modes
7.
8.
9.
Asp.Net MVC5
1.
2.
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.
8.
Note
In this article, I have mention only stable released version of Asp.Net MVC Framework.
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.
6.
7.
8.
var id = "txtCustomer" + j;
9.
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.
124
21.
22.
23.
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.
36.
</div>
37. }
You can get the Html TextBox or Dropdown list values created by jQuery by two method as given below -
2.
3.
4.
return View();
}
5.
6.
[HttpPost]
7.
8.
9.
10.
11.
string id = "txtCustomer" + i;
12.
13.
14.
return View();
15. }
2.
3.
4.
return View();
}
5.
6.
[HttpPost]
7.
8.
9.
10.
11.
string id = "txtCustomer" + i;
12.
13.
14.
return View();
15. }
125
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.
namespace jQueryMobileSite.CustomHelpers
2.
3.
4.
5.
6.
7.
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. }
<system.web.webPages.razor>
2.
...
3.
<pages pageBaseType="System.Web.Mvc.WebViewPage">
4.
<namespaces>
5.
6.
<add namespace="jQueryMobileSite.CustomHelpers"/>
7.
...
8.
</namespaces>
9.
</pages>
126
10. </system.web.webPages.razor>
2.
3.
</div>
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.
2.
3.
4.
5.
6.
7.
8.
return true;
9.
10.
else
11.
12.
return false;
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
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.
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
77.
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.
91.
92.
93.
94.
95.
96.
97.
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
21.
22.
23.
24.
25.
[Required]
26.
27.
28.
[Required]
29.
30.
31.
[Required]
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
1.
131
2.
3.
4.
5.
[Required]
6.
7.
8.
9.
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.
2.
3.
public DataContext()
4.
: base("DefaultConnection")
5.
6.
7.
8.
9.
10.
modelBuilder.Entity<User>()
11.
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.
21.
22.
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.
2.
3.
4.
5.
6.
User user1 = new User { Username = "admin", Email = "[email protected]", FirstName = "Admin", Password = "123456", IsActive = true, CreateDate
= DateTime.UtcNow, Roles = new List() };
7.
8.
User user2 = new User { Username = "user1", Email = "[email protected]", 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
2.
3.
[Required]
4.
5.
6.
7.
[Required]
8.
[DataType(DataType.Password)]
9.
[Display(Name = "Password")]
10.
11.
12.
13.
14.
15.
1.
2.
3.
4.
5.
6.
7.
2.
3.
4.
//
135
5.
// GET: /Account/
6.
7.
8.
return View();
9.
10.
11.
[HttpPost]
12.
13.
14.
if (ModelState.IsValid)
15.
16.
17.
if (user != null)
18.
19.
20.
21.
22.
serializeModel.UserId = user.UserId;
23.
serializeModel.FirstName = user.FirstName;
24.
serializeModel.LastName = user.LastName;
25.
serializeModel.roles = roles;
26.
27.
28.
29.
1,
30.
user.Email,
31.
DateTime.Now,
136
32.
DateTime.Now.AddMinutes(15),
33.
34.
userData);
35.
36.
37.
38.
Response.Cookies.Add(faCookie);
39.
40.
if(roles.Contains("Admin"))
41.
42.
43.
44.
else if (roles.Contains("User"))
45.
46.
47.
48.
else
49.
50.
51.
52.
53.
54.
55.
56.
57.
return View(model);
58.
137
59.
60.
[AllowAnonymous]
61.
62.
63.
FormsAuthentication.SignOut();
64.
65.
66.
67.
1.
2.
3.
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.
15.
16.
17.
if (authCookie != null)
18.
138
19.
20.
21.
22.
23.
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.
2.
3.
4.
5.
6.
7.
1.
2.
3.
//
4.
// GET: /Home/
139
5.
6.
7.
8.
return View();
9.
10.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
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.
3.
<pages pageBaseType="Security.DAL.Security.BaseViewPage">
4.
<namespaces>
5.
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.
141
18.
<div class="col-md-10">
19.
20.
21.
</div>
22.
</div>
23.
24.
<div class="form-group">
25.
26.
<div class="col-md-10">
27.
28.
29.
</div>
30.
</div>
31.
32.
<div class="form-group">
33.
34.
<div class="col-md-10">
35.
36.
37.
</div>
38.
</div>
39.
40.
<div class="form-group">
41.
42.
43.
</div>
44.
</div>
142
45.
</div>
46.
[CustomAuthorize(Roles= "Admin")]
2.
// [CustomAuthorize(Users = "1")]
3.
4.
5.
//
6.
// GET: /Admin/
7.
8.
9.
return View();
10.
11.
1.
2.
[CustomAuthorize(Roles= "User")]
3.
// [CustomAuthorize(Users = "1,2")]
4.
5.
6.
//
7.
// GET: /User/
8.
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.
2.
Use one of these keys within the CustomAuthorize attribute as shown below:
1.
//[CustomAuthorize(RolesConfigKey = "RolesConfigKey")]
2.
[CustomAuthorize(UsersConfigKey = "UsersConfigKey")]
3.
4.
5.
6.
//
7.
// GET: /Admin/
8.
9.
10.
return View();
11.
12.
1.
[CustomAuthorize(RolesConfigKey = "RolesConfigKey")]
2.
// [CustomAuthorize(UsersConfigKey = "UsersConfigKey")]
3.
4.
5.
//
6.
// GET: /User/
7.
8.
9.
return View();
10.
11.
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:
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.
145
3.
4.
5.
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
6.
7.
routes.MapRoute(
8.
name: "Default",
9.
url: "{controller}/{action}/{id}",
10.
11.
);
12.
13.
1.
2.
3.
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.
2.
3.
4.
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.
2.
3.
SecurityUtil.ProcessInApplicationTrust(delegate {
4.
IController controller;
5.
IControllerFactory factory;
6.
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.
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.
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.
147
2.
3.
4.
2.
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.
2.
3.
4.
ViewEngines.Engines.Clear();
5.
6.
ViewEngines.Engines.Add(new CustomViewEngine());
7.
8.
3.
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.
Custom Authentication
48.
49.
50.
51.
Data Caching
52.
Data Compression
Types of Filters
The ASP.NET MVC framework provides five types of filters.
12.
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.
16.
17.
18. }
You can create your CustomAuthentication filter attribute by implementing IAuthenticationFilter as shown below3.
148
4.
5.
6.
7.
8.
9.
10.
11.
12.
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.
16. }
The AuthorizeAttribute class provides the following methods to override in the CustomAuthorize attribute class.
12. public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter
13. {
14.
15.
16.
17.
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.
2.
3.
4.
5.
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.
2.
3.
4.
5.
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.
2.
3.
4.
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.
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.
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.
3.
4.
5.
3.
//
}
Action level
By putting your filter on the top of the action name as shown below1.
2.
3.
[Authorize(Users="User1,User2")]
4.
5.
6.
// TODO:
7.
return View();
8.
9.
}
}
150
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.
6.
7.
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.
6.
7.
Items in TempData will only tagged for deletion after they have read.
8.
9.
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.
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.
2.
3.
<ol>
4.
5.
6.
<li>@item</li>
7.
151
8.
</ol>
9.
10.
11.
<h3>Programming Languages:</h3>
12.
13.
14.
15.
<h3>Book List:</h3>
16.
17.
16.
Built-In Html Helpers are extension methods on the HtmlHelper class. The Built-In Html helpers can be divided into three categories1.
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.
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.
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.
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.
2.
3.
4.
5.
buttonText)
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
if (isReadonly)
18.
19.
html = System.Web.Mvc.Html.InputExtensions.TextBoxFor(htmlHelper,
20.
21.
22.
23.
else
24.
25.
html = System.Web.Mvc.Html.InputExtensions.TextBoxFor(htmlHelper,
26.
expression);
27.
28.
return html;
29.
30. }
154
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.
155
12.
156
13.
The following actions are created for insert, update and delete operations based on scaffold template within User controller.
157
46.
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.
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.
158
13.
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.
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")
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.
3.
4.
5.
6.
7.
8.
return View();
9.
10.
11.
12.
13.
14.
15.
return View();
16.
17.
18.
19.
20.
21.
22.
23. }
123.
You can define routes at action level which apply to a specific action with in the controller.
1.
2.
3.
4.
5.
6.
//TO DO:
7.
return View();
8.
9.
10.
11.
12.
13.
14.
return View();
15.
160
16.
17.
//route: /Home/Contact
18.
19.
20.
21.
return View();
22.
23. }
Note
379.
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.
155.
[Route("clients/{clientId}/orders")]
156.
157.
158.
//TO DO
159.
81.
82.
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
83.
84.
85.
routes.MapMvcAttributeRoutes();
86.
87. }
You can also combine attribute routing with convention-based routing.
135.
136.
137.
138.
139.
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
140.
141.
142.
routes.MapMvcAttributeRoutes();
143.
161
144.
//convention-based routing
145.
/routes.MapRoute(
146.
name: "Default",
147.
url: "{controller}/{action}/{id}",
148.
149.
150.
151.
91. [RouteArea("Admin")]
92. [RoutePrefix("menu")]
93. [Route("{action}")]
94. public class MenuController : Controller
95. {
96.
// route: /admin/menu/login
97.
98.
99.
return View();
100.
101.
102.
// route: /admin/menu/products
103.
[Route("products")]
104.
105.
106.
return View();
107.
108.
109.
// route: /categories
110.
[Route("~/categories")]
111.
112.
113.
return View();
114.
115.
116.
[Route("customers/{customerId}/orders")]
117.
118.
119.
//TO DO
120.
121.
162