MVC How To-Tollplus
MVC How To-Tollplus
NET MVC
ASP.NET MVC
Tips & Tricks
A must for every .NET Web developer
Sheo Narayan
ASP.NET MVC Tips & Tricks About Author
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
Contents
44. How to access form data into the controller using Request? ................................................................... 44
45. How to access form data into the controller using FormCollection?........................................................ 45
46. How to access form data into controller using parameters? .................................................................... 46
47. How to rename action method? ............................................................................................................... 47
48. How to rename a controller? .................................................................................................................... 47
Partial view ................................................................................................................................................................ 48
49. How to create a partial view? ................................................................................................................... 48
50. How to render/call a partial view from a content page (View) ? .............................................................. 50
51. How to return a partial view from controller action method? ................................................................. 50
52. How to call a partial view that accepts Model as parameter? .................................................................. 50
Redirect ..................................................................................................................................................................... 52
53. How to redirect the user to another page from controller action method? ............................................ 52
54. How to redirect the user to another action method from the controller action method? ...................... 52
55. How to redirect the user to another route url? ........................................................................................ 53
Passing data ............................................................................................................................................................... 53
56. How to pass data from one action method to another action method? .................................................. 53
57. How to pass data from controller action method to the View? ............................................................... 54
58. How to access data from querystring to the controller action method?.................................................. 56
Output ....................................................................................................................................................................... 57
59. How to return a view from controller action method?............................................................................. 57
60. How to return a model/object to the view from controller action method? ........................................... 57
61. How to output a content from controller action method? ....................................................................... 58
62. How to output JSON content from controller action method? ................................................................ 59
63. How to output JavaScript content from controller action method?......................................................... 59
64. How to output a file content from controller action method? ................................................................. 60
Route ......................................................................................................................................................................... 61
65. How to define a new route in ASP.NET MVC? .......................................................................................... 61
66. How to perform catchall operation in ASP.NET MVC route? .................................................................... 62
67. How to catch the route url segments into controller action method? ..................................................... 62
68. How to perform a browser constraint check in the route and redirect the user to browser specific page?
64
69. How to expose an action method by a certain url (attribute routing)? .................................................... 68
70. How to create a custom route handler in ASP.NET MVC to redirect the user to a specific page for a
specific url?............................................................................................................................................................ 69
URLs ........................................................................................................................................................................... 71
71. How to get the url of the action method? ................................................................................................ 71
72. How to create a hyperlink based on Controller action method? .............................................................. 73
73. How to avoid Length querystring in the URL generated by ActionLink? .................................................. 73
74. How to create a URL based on a Route defined? ...................................................................................... 74
Authentication and Authorization............................................................................................................................. 74
75. How to create forms authentication in ASP.NET MVC? ............................................................................ 74
76. How to perform authorization for a particular view/page in ASP.NET MVC? .......................................... 77
77. How to mark a controller to be accessed only by logged in user?............................................................ 78
78. How to make an action method public in secure controller? ................................................................... 78
Error handling ............................................................................................................................................................ 79
79. How to handle error in controller action method and pass error to the View? ....................................... 79
80. How to handle error for controller action method and redirect the user to a default error page? ......... 80
81. How to handle a specific type of error for the controller and redirect user to an error specific page? ... 82
Validation .................................................................................................................................................................. 83
82. How to prevent Cross-Site Request Forgery (CSRF) attack in ASP.NET MVC? .......................................... 83
83. How to perform a custom validation in ASP.NET MVC? ........................................................................... 84
84. How to mark a form to not validate the input data for any HTML or script data? ................................... 86
85. How to perform remote validation on a particular model field?.............................................................. 87
86. How to validate the data passed in url at the routing level itself in ASP.NET MVC? ................................ 89
87. How to use fluent validation framework in ASP.NET MVC? ..................................................................... 91
Session management ................................................................................................................................................ 94
88. How to store user specific data into session? ........................................................................................... 94
89. How to specify time out to the session object? ........................................................................................ 95
Caching ...................................................................................................................................................................... 95
90. How to cache the output of the action method?...................................................................................... 95
91. How to specify a profile for the output cache and use it in multiple actions? ......................................... 96
92. How to cache a partial view output? ........................................................................................................ 97
93. How to store data into Cache in ASP.NET MVC? ....................................................................................... 99
Database operations ............................................................................................................................................... 100
94. How to list the data from database? ....................................................................................................... 100
95. How to insert a record into database in ASP.NET MVC?......................................................................... 103
96. How to update a record into the database in ASP.NET MVC? ................................................................ 108
97. How to delete a record from the database? ........................................................................................... 112
© SN ITFunda Services LLP – http://sn.itfunda.com 4
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks About Author
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
98. How to upload a file on the server in ASP.NET MVC? ............................................................................. 115
99. How to upload multiple files on server in ASP.NET MVC? ...................................................................... 118
100. How to paginate records in the ASP.NET MVC view? ............................................................................. 121
101. How to sort and paginate records in ASP.NET MVC? .............................................................................. 124
102. How to perform a search based on a keyword from the database table in ASP.NET MVC? .................. 130
103. How to quickly list database records in Grid in ASP.NET MVC? .............................................................. 134
104. How to insert data into more than one database tables in ASP.NET MVC? ........................................... 136
105. How to work with Transactions in ASP.NET MVC?.................................................................................. 136
Ajax .......................................................................................................................................................................... 142
106. How to insert a record into database using Ajax? .................................................................................. 143
107. How to search records from the database using Ajax in ASP.NET MVC? ............................................... 149
108. How to list records from database using JSON in ASP.NET MVC? .......................................................... 153
Asynchronous .......................................................................................................................................................... 157
109. How to create an asynchronous controller and action methods in ASP.NET MVC?............................... 157
Bundles .................................................................................................................................................................... 159
110. What are bundles in ASP.NET MVC? ....................................................................................................... 159
111. How to create and use a JavaScript bundle in ASP.NET MVC? ............................................................... 159
112. How to create and use a CSS style bundle in ASP.NET MVC? ................................................................. 161
113. How to render Scripts / Styles bundles in the custom format in ASP.NET MVC? ................................... 162
114. What is optimization of JavaScript and CSS files? ................................................................................... 162
115. How to optimize JavaScript and CSS file in ASP.NET MVC? .................................................................... 163
ASP.NET Web API .................................................................................................................................................... 164
116. How to create an ASP.NET Web API Controller?..................................................................................... 164
117. How to insert a record into database by consuming ASP.NET Web API from ASP.NET MVC View? ...... 167
118. How to list records from database by consuming ASP.NET Web API from ASP.NET MVC View?.......... 170
119. How to delete record from database by consuming ASP.NET Web API from ASP.NET MVC View?...... 170
120. How to update record to database by consuming ASP.NET Web API from ASP.NET MVC View? .......... 176
121. How to consume external Web API in ASP.NET MVC? ........................................................................... 180
Exporting Data ......................................................................................................................................................... 182
122. Export to export data into MS Excel in ASP.NET MVC?........................................................................... 182
123. Export to export data into MS Word in ASP.NET MVC? .......................................................................... 185
124. How to export data into XML in ASP.NET MVC? ..................................................................................... 187
Unit testing .............................................................................................................................................................. 190
125. How to create a new ASP.NET MVC Test project? .................................................................................. 190
© SN ITFunda Services LLP – http://sn.itfunda.com 5
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks About Author
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
About Author
Mr. Sheo Narayan is a software professional since 2000 (15+ years) and working in .NET Technologies since its
first release. He is also the founder of a popular .NET Community website http://www.DotNetFunda.com. He has
been awarded many awards like Microsoft® Most Valuable Professional (MVP), Star Entrepreneur Award. He has
served thousands of professionals worldwide in solving their technical issues and teaching them in their
professional careers. His corporate training clients includes many MNCs.
Copyright notice
© All rights reserved to SN ITFunda Services LLP (http://sn.itfunda.com). No part of this book shall be
reproduced, stored in retrieval system or transmitted by any means mechanical, electronic, photocopying,
recording, or otherwise, without written permission from the SN ITFunda Services LLP. All though every
precaution has been taken while preparing this book, the publisher and author assume no responsibility for
errors or omissions or damaging resulting from the use of the information contained in this book or related items.
Website: http://sn.itfunda.com.com
Email: [email protected]
Phone: +91-40-4222-2291, +91-768-088-9888
Every effort has been taken to make this book and related materials as accurate as possible, but no warranty is
implied. The information provided in this book and related materials are on “as is” basis. The author and the
publisher shall have neither liability nor responsibility to any person or entity with respect to any loss or damage
arising from the information contained in this book or related items.
Sales information
This book and related items are available on sale on www.itfunda.com website.
For bulk sale or corporate (commercial) license, please contact at [email protected] or on above mentioned
phone numbers.
Phone: +91-40-4222-2291
Mobile: +91-768-088-9888
Email: [email protected]
Website: http://www.itfunda.com
Acknowledgements
I would like to take this opportunity to thank my wife Dr. Sunita for all her support and encouragement and of
course to my daughter Sindhuja and my son Shreeharsh for being so patient to get my time.
A lot of thanks to my website www.dotnetfunda.com that always inspires me to do more and more for the .NET
Technology and its community.
I would also like to thank all my colleagues at DotNetFunda.Com. To name a few Sainath Sherigar, Shivprasad
Koirala, Vakul Kumar More, Vuyiswa Maseko for their continuous support and contribution of countless number
of hours in maintaining www.dotnetfunda.com.
Of course moderators like Radha Srikanth, are also doing pretty decent job and I would like to thank them as well
for their support.
Last but not least, I would like to thank my staffs at SN ITFunda Services LLP for their continuous support in doing
whatever I decide to do.
If you have any comments on this book or you want us to add any How to’s related with .NET Technologies,
please feel free to let us know and we shall try to add them in our future release.
References
Writing books without getting knowledge from different sources are impossible. Thanks to the authors of books,
internet articles and other blogs for sharing their knowledge.
ASP.NET MVC stands for ASP.NET Model View Controller design pattern. MVC was first invented by Trygve
Reenskaug and was named as “Thing Model View Editor” pattern originally. Slowly it became popular and
renamed as “Model View Controller”.
ASP.NET MVC was created by Scott Guthrie of Microsoft in 2007 based on the MVC framework implemented in
different framework like Ruby on Rails, Spring etc. ASP.NET MVC (Model View Controller) is an architectural
design pattern that separates an application into three main components
1. Model
2. View and
3. Controller
ASP.NET MVC is not the replacement of traditional ASP.NET Web form but it’s an alternative. The ASP.NET MVC
App is highly testable application than traditional ASP.NET Web form applications. The namespace used for
ASP.NET MVC is System.Web.Mvc.
Model
Model can generally be called as a logic layer cum data access layer that can contain the business logic or data
access logic. It encapsulates the logic for the application domain.
View
Views can be called as Presentation layer that displays the application data in the browser.
Controller
Controllers are the place where the user interactions are handled. Controller is responsible to receive the
request, process the response by sending to the Model and give the response to the View again.
So in MVC, the View is only responsible to display the information. Controller is responsible for receiving request,
processing it using Model and sending it back to View and Model is responsible to apply logic, connect to the
database and retrieve data.
The benefit of ASP.MVC is that it helps to isolate the application to achieve maintainability, testability and cleaner
separation of concerns.
Benefits
All layers are loosely coupled.
o UI belongs to the View
o Input logic belongs to the Controller and
o Business logic and data manipulations belong to the Model
The separation of layers helps in parallel development as a developer can focus on only one part of the
application at a time. For example, a member of team can entirely work on a single model without
worrying about its View; another team member can focus on just the Controller part and so on.
The separation of layers helps in easily managing the complexity of the application as all layers are
decoupled; apart from this it also helps to test the individual component separately so suitable for Test
Driver Development.
It doesn’t use View state and server based forms so no view state!
Suitable for large team size as team members can work independently.
Other facts
1. Interface based programming – mostly used interfaces are
IHttpContext
IHttpRequest
IHttpResponse
2. The incoming request are mapped to a controller and it’s method as against file on the server (other web
framework map the incoming request to the file)
In ASP.NET when we request http://localhost/test/default.aspx - the default.aspx is assumed to
be a physical file.
Basics
Open Visual Studio (in this case Visual Studio 2013 Community edition) and go to File > New Project …
Select Visual C# > Web > ASP.NET Web Application template and Framework as .NET Framework 4.5. Specify
Name, Location to create project, Solution type and Solution name and click OK.
Select MVC as Template and click OK (Make sure that your Authentication type is Individual User Accounts after
you click Change Authentication button.
This will create a Project template in ASP.NET MVC and the Visual Studio looks like below
The default page opened in the left side of the Visual Studio is Project_Readme.html that has some useful links to
know more about how to work with ASP.NET MVC. In the right side, Solution Explorer gives the complete
structure of the ASP.NET MVC project structure.
1. Controller name must end with “controller” word. Eg. PersonalDetailsController, EmployeesController
2. Database table corresponding Model name should be similar to the database table name (not
mandatory, however its ideal)
3. Views – There should be a view folder inside Views folder corresponding to each controller. Like for
PersonalDetailsController, there should be a folder Views/PersonalDetails, similarly for
EmployeesController, there should be Views/Employees folder.
To create a new controller, right click the Controllers folder and select Add > Controller …
Select the type of controller you want to create and click Add button.
Write the controller name (notice the selected characters, you need to replace only selected characters from the
controller name and click Add.
This will create a DefaultController whose code would look similar to this
/Controllers/DefaultController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace WebApplication4.Controllers
{
public class DefaultController : Controller
{
// GET: Default
public ActionResult Index()
{
return View();
}
}
}
Notice that a corresponding Default folder would also get created when the controller gets created.
There are few other ways to create a View, however if you have an action method and do not have corresponding
View, right click the Action method and select Add View …
Empty (without model) – generally used to render static content to the browser
Create – applicable only when we are going to add a Create form for the model – need to select a
model
Details – applicable only when we are going to show the details of a model – need to select a model
Delete – applicable only when we are going to delete a model record – need to select a model
Edit – applicable only when we are going to edit a model record – need to select a model
List – applicable only when we are going to list model records
Empty - applicable only when we are going to create a view with a model and want to scaffold the
HTML code based on model property.
© SN ITFunda Services LLP – http://sn.itfunda.com 18
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks Basics
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
Keep the Use a layout page checkbox checked as we do not want to select any other master page
(_Layout.cshtml) and want to use default.
It will create a Index.cshtml view in the Views/Default folder and the code would look like
/Views/Default/Index.cshtml
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
To create a Models folder from the Solution Explorer and select Add > Class …
Write the name of the Model you want to create, in this case PersonalDetail and click Add.
A class file named PersonDetail.cs is added into Models folder. Now, let’s assume that we want to create a Model
corresponding to the following table in the database. Notice that database table name is also PersonalDetail.
To do that we need to create properties corresponding to the fields of the database table and our Model looks
like below.
/Models/PersonalDetail.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace WebApplication1.Models
{
public class PersonalDetail
{
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOpt
ion.Identity)]
public int AutoId { get; set; }
Remember that we need to add last two namespaces in order to add attributes to the properties. Let’s talk about
attributes added to the properties of this Model.
The best way to add the namespace is press Ctrl + . by keeping the cursor on the attributes. It will give a
IntelliSense as the probable namespace and then select the appropriate one.
To scaffold the View and Controller based on Model, we need to configure our web.config (application root) for
the database for which we have created the Model. Go to your web.config file and change the connectionStrings
value appropriately so that it connects to your database.
Step 1
Change the connectionString value of the above part of the root web.config file. In this case it looks like below
<connectionStrings>
<add name="DefaultConnection"
connectionString="Data Source=SNITFunda;Initial
Catalog=TrainingDatabase;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
Where
Step 2
You should be getting Rebuild All succeeded message at the status bar of Visual Studio.
Step 3
Now, follow the first step to add a controller as shown in the picture below.
In the next dialogue box where we need to select the Controller type, select MVC 5 Controller with views, using
Entity Framework and click Add.
In the next dialog box, Select Model class as the PersonalDetail model, the one that we have just created in
previous step. Select ApplicationDbConext as the Data context class (this gets automatically created when we
create the project).
Keep the Generate views checkbox checked as we want to create Views too for this Model. The Reference script
libraries checkbox makes sure that we have jquery, jquery validate scripts are referenced in the view wherever it
is required (mainly in the Create/Edit views. User a layout page checkbox, let us use the default Master page
(_Layout.cshtml).
Notice that the Controller name is automatically written based on the Model name selected. Keep it as it is and
click Add. Here we are assuming that we have a PersonalDetail model created in the project by following above
point.
In case you get any error after creating Add button that looks something like
The model backing the '' context has changed since the database was created. Consider using Code First
Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).
Double click global.asax page under the root of the application and add following line of the code under
Application_Start() event.
System.Data.Entity.Database.SetInitializer<Namespace.Models.ApplicationDbContex
t>(null);
Assuming you successfully completed above steps, notice the change in the Solution Explorer.
You will notice that PersonalDetialsController.cs file gets added into Controllers folder.
In Views folder PersonalDetials folder gets created and following files are also gets created
I. Create.cshtml – used to create a new record in the database using PersonalDetail model.
II. Delete.cshtml – used to delete a record in the database using PersonalDetail model.
III. Details.cshtml – used to show the details of the PersonalDetail database table record using PersonalDetail
model.
IV. Edit.cshtml – used to edit the record in the database using PersonalDetail model.
V. Index.cshtml – used to list the record from the PersonalDetail database table using PersonalDetial model.
Now you can run the project and navigate to PersonalDetails folder. Your URL should look something similar to
http://localhost:54003/PersonalDetails (replace port 54003 to your own) and you should be able to list a blank
page with Create New link. Clicking the link takes you to the /PersonalDetails/Create page where one can create a
new record. Similarly, delete and edit works.
Razor is a syntax used in Microsoft .NET technologies to develop web pages and application that let us embed the
server based code (like C# and Visual Basic) into the web pages.
Server based content help us in creating dynamic content on the fly and can perform some complex logic as well.
All the server side code in Razor starts with @{ and ends with }. We can mix the html and server based code
inside the Razor block and that is the beauty of the Razor markup.
To declare a variable in the View using Razor syntax, we need to first create a code block by using @{ and } and
then we can use the same syntax we use in the C#.
@{
In the above code, notice that we have created the Code block and then start writing C# syntax to declare and
assign the variables.
To comment in the code block of Razor view, we use the same syntax as we use in C#. Like for single line // and
for multiline /* and */.
/*
* multi
* line
* comment
*/
To comment, HTML along with other code, we need to use razor comment block that starts with @* and ends
with *@.
@*<h3>Inline expression</h3>
This is @fileName logo.
<h3>Code Expression</h3>
<p>Sum is @(a + b)</p>*@
To perform a for loop, we write the syntax as we write in C#, however it start with @. Like
Notice that html code is mixed with the C# code inside the for loop.
It is similar to the for loop except that it can be done only to those collection that has similar type of objects in it
as it is in C#.
<ol>
@foreach (var variable in Request.ServerVariables)
{
<li>@variable</li>
}
</ol>
Notice that @ character is just before the first line of the conditional statement, else doesn’t have @ as the Razor
markup automatically detects the starting and ending if block and assumes that else is the part of if not the HTML
syntax.
It is similar to if, we just need to write switch statement. Notice how beautifully we are able to mix the C# and
HTML code.
@switch (fileName)
{
case "itfunda":
<p>itfunda logo</p>
break;
case "dotnetfunda":
<p>dotnetfunda logo</p>
break;
default :
<p>no logo</p>
break;
}
To write the variable data inside the URL, we wrap the variable with bracket.
Notice that the variable filename is wrapped with “(“ and “)”, if we do not do that Razor doesn’t understand
fileName as a variable and throws error.
CS1061: 'string' does not contain a definition for 'gif' and no extension method 'gif' accepting a first argument of
type 'string' could be found (are you missing a using directive or an assembly reference?)
If the declared variable is of number type, we can simply use the mathematical operators like +, - etc. prefixed
with @.
If the variable is of string type, we need to convert them into respective number type and use the mathematical
operators.
Notice .AsInt() here sum is of string type and we are converting them to Integer and adding 6 into it. Similar to
.AsInt() we have .AsDecimal() etc.
Instead of .AsInt(), we could have also used C# int.Parse() to convert the string into integer.
<p>
The value of a is @(int.Parse(sum) * 50)
</p>
Sometimes, Razor markup gets confused between the HTML and C# code. In that case, if we need to force a
certain group of characters to mark as HTML syntax then we can wrap those between <text> and </text> like
below.
18. How to create & call an inline custom helper method in Razor markup?
Sometimes, we need to create a custom helper method in the Razor to avoid the duplication of the code. To do
that we can use @helper markup followed by the name of the method and parameters if any.
To call this helper method, we can call it as if it is any other method defined in Razor server side block.
19. How to create and call an external HTML helper method in Razor markup?
Create a C# class in any new folder (in this case “Utility”) of the application and write following code.
NAMESPACE:
using System.Web.Mvc;
CODE:
Note the first parameter of the Sum method ie. HtmlHelper that help us to call this method using @Html.
This creates an extension method called Sum that can be used in Razor syntax using @Html.
To import a namespace in Razor markup, we use using statement as we write in C# class however it should be
prefixed with @.
@using MVCTraining5.Utility
To call any method insider that namespace, we do not need to give a fully qualified name. Assuming LogError
class is in this namespace, we can call its method like below.
<p>@LogError.GetDate()</p>
To call external method defined in the C# class, we can start calling them by giving their fully qualified name (if
the namespace is not imported using @using statement).
<p>
@MVCTraining5.Utility.LogError.GetDate()
</p>
Here, we are assuming that we have a static method GetDate() definiend in the LogError class that is in
MVCTraining5.Utility namespace.
To specify a model for the View, we can using @model statement at the top of the View page.
@model MVCTraining5.Models.PersonalDetail
Now, in the following code the PersonalDetail class properties can be accessed using @Model like
@Model.FirstName
ViewBag or ViewData (“in short, ViewBag and Viewdata are temporary placeholders to store some value valid for
that request only) is nothing but an object or variable whose value is generally set in the Controller action
method (however it can also be set at other places like View). To write their values, simply call them as if you call
any other variable.
@{
ViewBag.Title = "Index";
ViewData["MyName"] = "Sheo Narayan";
}
To write their values, call them as if you are calling any variables in Razor syntax.
<h2>ViewBag | ViewData</h2>
@ViewBag.Title
<p>
@ViewData["MyName"]
</p>
24. How to unbox ViewBag / ViewData data to its stored type object?
Let’s assume that we have a collection of PersonalDetail stored in the ViewBag inside the Controller action
method.
ViewBag.PersonalDetails = list;
@{
To create a read only view, we need to create an action method inside a Controller first. Go to your Controller
and add an action method like defined in point 5 (How to create a view?) and follow the steps.
As discussed in the previous point, we first need to create an action method in the Controlller for the view and
follow the steps to create the View.
Now, write following code to create a form. (Here we are assuming that we have a CreateNew method in the
PersonalDetailsController controller.
@using (Html.BeginForm())
{
<text>
When this code renders in the browser, it generates following source code.
</form>
Notice that the by default method of the form is post with Html.BeginForm and as we have not passed any
parameter to the Html.BeginForm so the action value is by default the current url that means when the form gets
submitted after clicking on the Submit button, it gets submitted on /PersonalDetails/CreateNew action method of
the PersonalDetailsController.
To create a model based view, we declare model for the View at the top of the page by using @model directive.
@model WebApplication1.Models.PersonalDetail
To display the property’s value of the Model, we can use @Model.PropertyNames like
@Model.FirstName
For more details around this, please see the Views (like Details.cshtml, Index.cshtml etc.) created under
/Views/PersonalDetails at the time of creating Controller based on Model in the above points.
To create hidden form element in Razor markup, we follow approach depending on scenario.
If the hidden element is created for the property of the Model in the view here Model is used.
If the view is using Model and we need to create a textbox corresponding to the Model property.
Or
To create radio buttons, we can use @Html.RadioButton helper method. We need to ensure that the name of the
radio buttons are same if we want to make them mutually exclusive.
@using (Html.BeginForm())
{
<text>
@Html.RadioButton("Active", "true")
Yes
@Html.RadioButton("Active", "false", true) No
</text>
}
@Html.RadioButtonFor is not so useful in this context as it only creates one radio button that is not going to be
useful as if it is selected, you can’t de select it.
@Html.CheckBox("Active1")
If the View is using Model and the property is of type Bit (Boolean), we can use @Html.CheckBoxFor
Here, the name of the DropDownList is dropRoles and items will be Yes and No. The first item will be “Select …”.
In case the requirement is to bind the DropDownList items from action method of the Controller, we need to set
the items collection into ViewBag and use it as source code.
VIEW CODE
Here SelectList instance accepts collection of the object as parameter from which the source of the DropDown to
build, the second parameter is the name of the data value field and the third parameter is the text value field that
would be used in the item of the DropDownList.
Creating ListBox is similar to DropDownList except that instead of using @Html.DropDownList, we use
@Html.ListBox or @Html.ListBoxFor. Remaining all other approaches to populate items in the ListBox is same as
DropDownList.
Models
For all above, please refer to point no. 6 (How to create a new model?)
To validate a model field for a particular data type, use DataType attribute like below.
[DataType(DataType.Currency)]
public string Salary { get; set; }
Decorating the model field with DataType ensures that when it is rendered to the browser, it automatically
appears in proper format (like currency format, email format etc.).
To apply a custom label to the model field, Display attribute can be applied.
Here the default label of the Active field appears as “Active” however if we want to change the label in the View,
we can change it with the help of Display attribute as above.
41. How to give a meaningful name to the model property and still map with
the database table field?
[Column("Active")]
[Display(Name = "Is Active?")]
public bool IsActive { get; set; }
Here, the model property name is the IsActive however we are mapping this property to the Active field of the
database table.
42. How to give a different name to the model and still map with the database
table?
To give different name to the Model and still map it with the database table name, we can use Table attribute in
the Model class.
[Table("Files")]
public class FilesModel
{
Here, despite our Model name is FilesModel, however it is mapping with “Files” table of the database.
View Model
View Model is a model class that can hold only those properties that is required for a view. It can also contains
properties from more than one entities (tables) of the database. As the name suggests, this model is created
specific to the View requirements.
1. To list data from more than entities in a view page – we can create a View model and have properties of
all the entities for which we want to list data. Join those database entities and set View model properties
and return to the View to show properties of different entities in one table as one result set.
2. View model may define only specific fields of a single entity that is required for the View.
43. How to list data from more than one tables in ASP.NET MVC?
Creation of View model is similar to the creation of Model. Right click Models folder and go to Add > Class…
Give some meaningful name. It is suggested to suffix the name of View mode to “ViewModel” word so that it is
can be easily distinguished in the Model folder among other Models. In our case, the View model name is
PersonaldetailsFilesViewModel.cs as we are getting properties of from both PersonalDetails and Files entities.
MODEL CODE
Here, top 5 properties are corresponding to the PersonalDetails model and FileName is from Files model.
Important:
In order to generate List scaffolding template, a View model must have a Key field.
return View(listWithEmpty);
}
In this method, we are first joining PersonalDetails and Files entities and creating a collection of Anonymous type
collection and then converting them into the collection of PersonaldetailsFilesViewModel, that intern is being
passed to the View.
Now, right click the controller action method and choose “Add View…”, this gives a Add View dialog box.
Select appropriate Template, Model class and Data context and press Add button. This creates a normal view of
List type that lists the data from PersonaldetailsFilesViewModel view model. The view looks like below.
VIEW CODE
@model IEnumerable<MVCTraining5.Models.PersonaldetailsFilesViewModel>
@{
ViewBag.Title = "ListCompleteDetails";
}
<h2>ListCompleteDetails</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
© SN ITFunda Services LLP – http://sn.itfunda.com 42
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks View Model
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
</table>
Now, build the project and come to this action method and we should be seeing below output depending on the
data from both database tables.
NOTE: If Edit | Details | Delete links are not required, we may delete those columns from the View.
Controller
44. How to access form data into the controller using Request?
VIEW PAGE
In the above code, we are creating two textboxes and a Login button.
CONTROLLER CODE
Above method renders above View. When Login button is clicked below action method of the controller
executes.
[HttpPost]
public ActionResult ReceiveWithRequestFormData()
{
string userName = Request.Form["txtUserName"];
string password = Request.Form["txtPassword"];
if (userName.Equals("user", StringComparison.CurrentCultureIgnoreCase)
&& password.Equals("pass", StringComparison.CurrentCultureIgnoreCase))
{
return Content("Login successful !");
}
else
{
return Content("Login failed !");
}
}
To access the form elements value, we can use Request.Form collection by passing the name of the form
element.
45. How to access form data into the controller using FormCollection?
The other ways to access the form element in the action method of the controller is by using FormCollection.
CONTROLLER CODE
[HttpPost]
public ActionResult ReceiveWithRequestFormCollection(FormCollection form)
{
string userName = form["txtUserName"];
string password = form["txtPassword"];
if (userName.Equals("user", StringComparison.CurrentCultureIgnoreCase)
&& password.Equals("pass", StringComparison.CurrentCultureIgnoreCase))
{
return Content("Login successful !");
}
else
{
return Content("Login failed !");
}
}
In this case, all the form elements comes to this method as FormCollection and we can access them using
element’s name.
To access the form data into the controller action method, we can also use parameters into the action method.
CONTROLLER CODE
[HttpPost]
public ActionResult ReceiveWithParameter(string txtUserName, string
txtPassword)
{
if (txtUserName.Equals("user",
StringComparison.CurrentCultureIgnoreCase) && txtPassword.Equals("pass",
StringComparison.CurrentCultureIgnoreCase))
{
return Content("Login successful !");
}
else
{
return Content("Login failed !");
}
}
Notice that the parameters name of this action method are same as the name of the element. The ASP.NET MVC
Framework is smart enough to detect the name of the parameters and convert the element value as parameter
value.
To rename the Action method of the controller, we use ActionName attribute to the action method of the
controller.
[ActionName("PersonList")]
public ActionResult Index(string txtKeyword = null)
{
return View();
}
Here, despite that our Action method name is Index, it will be accessible from the browser as PersonList.
Eg. http://localhost:8888/PersonalDetails/PersonList
A controller can’t be renamed like an action method, however the route can be changed so that you do not need
to stick with the url that is directly related with the controller name.
ROUTECONFIG CODE
routes.MapRoute(
name: "MyCustomRoute",
url: "MyEmployees/{action}/{id}",
defaults: new { controller = "PersonalDetail", action = "Create",
id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
© SN ITFunda Services LLP – http://sn.itfunda.com 47
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks Partial view
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
Notice the code highlighted above. Even if the controller name is PersonalDetail, the url should look like
http://localhost:63087/MyEmployees in order to go to Create view of PersonalDetailController. Similarly, to
browser any other action method of the PersonalDetailController, we need to browse by prefixing with
MyEmployees as if the controller name is MyEmployeesController.
Eg.
Partial view
To create a partial view, right click the View folder we need to create partial view in.
In the following Dialog box, write the view name (the partial view name generally starts with “_” to distinguish
between normal views and partial views). Select the template needed (same as if you are creating a normal view)
and ensure that Create as a partial view checkbox is checked. Now click Add button.
To render a partial view from the View page, we can either user @Html.Partial or @Html.RenderPartial helper
method.
<hr />
@Html.Partial("_GetFileName")
<hr />
@{ Html.RenderPartial("_GetFileName"); }
<hr />
@Html.Partial returns MvcHtmlString that is the output of the Partial view. However @Html.RenderPartial view
has been called in the code block as @Html.RenderPartial method returns void and its result is written in the
Response stream.
POINT OF INTEREST:
Here, we are assuming that _GetFileName.cshtml partial view exists in the same folder where the calling view
exists. If not, ASP.NET MVC framework search for /Views/Shared folder for this view, if the view is not even found
there then it throws error.
To return a Partial view from the controller action method, we can write return type as PartialViewResult and
return using PartialView method.
In the above code, we are assuming that _GetFileName.cshtml exists in the controller specific folder otherwise
we need to specify the complete file name of the view from the root of the application.
CONTROLLER CODE
@model IEnumerable<MVCTraining5.Models.PersonalDetail>
@{
ViewBag.Title = "IndexWithPartialView";
}
@Html.Partial("_ListPersonalDetail", Model)
Above view accepts the collection as Model that is passed to the _ListPersonalDetail partial view by calling
@Html.Partial method in the 2nd parameter.
PARTIALVIEW CODE
@model IEnumerable<MVCTraining5.Models.PersonalDetail>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.FirstName)
</th>
<th>
@Html.DisplayNameFor(model => model.LastName)
</th>
<th>
@Html.DisplayNameFor(model => model.Age)
</th>
<th>
@Html.DisplayNameFor(model => model.IsActive)
</th>
</tr>
}
</table>
Above partial view accepts collection passed by @Html.Partial method and loops through each item in the list
and creates the list.
Redirect
53. How to redirect the user to another page from controller action method?
To redirect the user to another page (either external or internal), we can use Redirect method like below.
}
Remember that to redirect to external url, we need to provide complete url starting with http. For internal
redirect, url can be provided from root of the application.
54. How to redirect the user to another action method from the controller
action method?
To redirect the user to another action method from the controller action method, we can use RediretToAction
method.
Above method will redirect the user to Edit action method with id parameter value as 1, ie it will bring the record
id 1 in edit mode.
If we do not need to pass any parameter, simply remove the 2nd parameter.
POINT OF INTEREST:
Similarly, we can use various overload methods of the RedirectToAction method to redirect action method of
different controller etc.
To redirect user to another route url from action method of the controller, we can use RedirectToRoute method
by passing route name defined in the App_Start/RouteConfig.cs file.
ROUTECONFIG.CS
routes.MapRoute(
name: "MyCustomRoute",
url: "MyEmployees/{action}/{id}",
defaults: new { controller = "PersonalDetail", action =
"Create", id = UrlParameter.Optional }
);
Here, our Route name is “MyCustomRoute” and if any user comes with the url starting with “MyEmployees”, this
route serves the request.
CONTROLLER CODE
When above action method executes, it gives the url formed by MyCustomRoute defined in the RouteConfig.cs
based in object parameter passed.
POINT OF INTEREST
There are few overloads of RedirectToRoute method that help us to redirect to another routes, try different
overload methods by passing respective parameters.
Passing data
56. How to pass data from one action method to another action method?
Sometimes, we may need to pass some data from one action method to another while redirecting the user to
another action method from calling action method. In this case, we can pass certain data through the
RedirectToAction method by objectParamter. However, there might be scenario where your data may not fit in
the objectParamter as those parameter must be defined into the calling action method.
CONTROLLER CODE
// once you have set the value, you will need to use it otherwise it
remains in the memory and next time this action method will be called
// it throws error "key already exists"
TempData.Add("MyTempData", "This data is coming from calling method.");
return RedirectToAction("TempDataMethod");
}
TempData accepts the value in key and value pair. Value can be any type of object (not necessarily string or
integer but it can be class or collection of classes or any different types of object).
When above action method is called, it saves the data into TempData with the key “MyTempData” and redirects
to the “TempDataMethod”.
TempDataMethod is accessing the TempData by specifying its key and returning to the View.
POINT OF INTEREST
Unless we retrieve the data stored in the TempData, it remains in the memory of the application so next
time if Index method is called it throws following exception.
System.ArgumentException: An item with the same key has already been added.
Passing data with TempData is only useful when we have this specific scenario where we are redirecting
the user from one action method to another.
57. How to pass data from controller action method to the View?
Passing data from action method to the view can be done using two ways (except using return keyword).
ViewData
ViewData is a dictionary where we store the data against a key. The data can be stored as an object so it can be of
any data type.
VIEW CODE
@ViewData["MyViewData"]
Another example
VIEW CODE
To retrieve the integer stored in the collection, we need to unbox it the way it is done above and
retrieve the data in each iteration.
ViewBag
ViewBag is also a dictionary however it is of dynamic dictionary. Where we can set ViewBag.Property (any name
as it is of dynamic type) and access it from the View.
ViewBag.MyViewBag = "This data is coming from ViewBag, that can have a dynamic
property.";
ViewBag also accepts data as object so we can set any type of data.
VIEW CODE
@ViewBag.MyViewBag
Like ViewData, ViewBag can also be set with collection and retrieved by unboxing to that specific type.
58. How to access data from querystring to the controller action method?
There are at least two ways to retrieve querystring data into the Controller action method.
http://localhost:63087/SessionStateManagement/Details?id=50&name=itfunda
VIEW CODE
<h2>Details</h2>
The querystring value is <strong>@ViewBag.Id</strong>
<p>
@Request.QueryString["id"]
</p>
<p>@ViewBag.Name</p>
@Request.QueryString["name"]
Output
To return a view from the controller action method, we can use View() method by passing respective parameters.
60. How to return a model/object to the view from controller action method?
To return a model from the controller action method to the view, we need to pass the model/object in the View()
method.
model.UserName = "user";
model.Password = "Password";
return View(model); // returns view with model
Here, the View gets the model as UserNamePasswordModel object with its property set. To retrieve properties of
this object in the view, we can use @Model; like @Model.UserName or @Model.Password.
Instead of a simple class object we can also pass collection of objects also to the view like
CONTROLLER CODE
To output any content (plain text or with HTML) from controller, we return ContentResult() like below.
CONTROLLER CODE
Notice that we are returning data using the Content function by passing the data as string.
OUTPUT
POINT OF INTEREST
Play with few more overload methods of Content, they help us to pass the ContentType we are returning and
encoding used.
To return JSON (JavaScript Object Notation) content from controller, we use JsonResult content type in the action
method o the controller.
CONTROLLER CODE
In the above code, we are setting the properties of the UserNamePasswordModelk object and converting into
JSON by Json method and returning to the caller. Depending on which browser used, it may download the Json
string or write it as output in the browser window. If called from the AJAX, it returns to the calling JavaScript
function.
OUTPUT
{"UserName":"Tamjid","Password":"India","Active":false}
To demonstrate how to return JavaScript content from the controller, we have created a demonstration here.
Let’s follow that step by step.
@{
ViewBag.Title = "OutputJavaScript";
}
<h2>OutputJavaScript</h2>
When the link “Test JavaScript” is clicked, it calls the OutputJavaScriptAlert action method of the controller.
CONTROLLER CODE
This action method returns JavaScript content that we get it in the new window or to download as displayed in
the above picture (depending on the browser).
In general, these methods are used in the Ajax methods to return partial content.
To output a file content from the controller action method, we use FileResult to send the response to the
browser.
CONTROLLER CODE
In the above code, we are getting the path of the file to return and using File method to pass the file content to
return and the file content type. This in general renders file content in the browser.
If we pass third parameter called “fileDownloadName”, it forces the user to download the file instead of
rendering its content in the browser.
POINT OF INTEREST
Play with different overload methods of the returning File method, it also accepts byte array or Stream in case
you do not want any physical file to send as result and build the file content on the fly.
Route
To define a new route, go to ~/App_Start/RouteConfig.cs file and write your new route just after
routes.IgnoreRoute statement.
ROUTECONFIG.CS CODE
routes.MapRoute(
name: "MyCustomRoute",
url: "MyEmployees/{action}/{id}",
defaults: new { controller = "PersonalDetail", action = "Create", id
= UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
Notice the above code snippet (highlighted), we have defined our MyCustomRoute just after routes.IgnoreRoutes
and the default route “Default”. This is because the default route defined is more of a generic nature that takes
care of any three fragments comes in the url for Controller, Action and Id (optional). So if we define our custom
route after the default routes, the default routes will execute and our custom routes will not. So by defining
routes, we need to define from specific to generic routes.
In our custom route, we have instructed ASP.NET MVC framework that if any url is starting with MyEmployees,
route it through MyCustomRoute paramters.
Sometimes, we need to write a route for catchall type of url where any extra data coming in with the url after url
segments defined in the route, we can write in following way.
ROUTECONFIG.CS CODE
routes.MapRoute("CatchAll", "Route/{controller}/{action}/{id}/{*catchall}",
new { controller = "RoutingStuffs", action = "CatchAll", id =
UrlParameter.Optional });
In above case, any url starting with “Route” is served by this route. For example
http://localhost:63087/Route/RoutingStuffs//CatchAll/50
Above url is served by this route where Controller is “RoutingStuffs”, action is “CatchAll” (name of the action
method) and id is 50 given to the action method.
http://localhost:63087/Route/RoutingStuffs/CatchAll/50/Delete/And/Other/Parameter
The remaining data after “/50/” segments is given to the controller action method as catchall parameter (notice
the “{*catchall}” segments defined in the url pattern.
67. How to catch the route url segments into controller action method?
To catch the route url segments value into controller action method, we use the name of the url parameter as
parameter of the action method in general.
CONTROLLER CODE
return View();
}
http://localhost:63087/Route/RoutingStuffs/CatchAll/50/Delete/And/Other/Parameter
it directly comes to the above action method of the RoutingStuffs controller and note that as per routing
instruction in the previous point
VIEW CODE
@{
ViewBag.Title = "CatchAll";
}
<h2>Catch All</h2>
<p>Controller : @ViewBag.Controller</p>
<p>Action : @ViewBag.Action</p>
<p>Id : @ViewBag.Id</p>
<p>CatchAll : @ViewBag.CatchAll</p>
In the above view we are writing the url segments values passed to the action method.
68. How to perform a browser constraint check in the route and redirect the
user to browser specific page?
To demonstrate this example, we need to create few pages. Please follow below steps carefully without missing
any steps. All steps are mandatory.
APP_START/ROUTECONFIG.CS
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("ConstraintCustom",
"BrowserCheck/{action}/{id}/{*catchall}",
new { controller = "RoutingStuffs", action = "Index", id =
UrlParameter.Optional },
new[] { "MVCTraining5.Controllers" });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
In the above code snippet notice that we have moved the default route mentioned in the RouteConfig.cs file to
the last so that this do not interrupt with the custom route defined by us.
In the first route, notice that till 3rd parameter everything is normal (we have already seen these parameters
earlier). The 4th parameter is the constraint defined by us that exists in the Utility namespace (Utility folder inside
the root of the application, we will see this next) and the 5th parameter is the namespace from which
RoutingStuffs controller should be used for this type of routing (provided the constraint is returning true (we will
see it later).
In the second route, we have skipped the 4th parameter and specified the namespace from which RouteStuffs
controller should be used for this routing (we will define two different controller with the same name in different
namespace; do not worry, we are going to see them all).
/UTILITY/BROWSERDETECTCONSTRAINT.CS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
namespace MVCTraining5.Utility
{
public class BrowserDetectConstraint : IRouteConstraint
{
string _userAgent = string.Empty;
Notice that the class file is implementing IRouteConstraint interface that forces us to implement Match method
which returns true or false based on user agent coming in to this constraint in the constructor.
/CONTROLLERS/ROUTINGSTUFFSCONTROLLER.CS
/VIEWS/ROUTINGSTUFFS/BROWSERCHROMEDETECH.CSHTML
@{
ViewBag.Title = "BrowserChromeDetech";
}
@ViewBag.Browser
Create another controller with the same name in different namespace. We need to create a folder insider
Controllers folder named OtherFolder (you can change the name, if you decided to change the name then you
need to also change the namespaces name in your code wherever I have referred “OtherFolder”).
/CONTROLLERS/OTHERFOLDER/ ROUTINGSTUFFSCONTROLLER.CS
return
View("/Views/RoutingStuffs/OtherStuffs/BrowserChromeDetect.cshtml");
}
/VIEWS/ROUTINGSTUFFS/OTHERSTUFFS/BROWSERCHROMEDETECT.CSHTML
@{
ViewBag.Title = "BrowserChromeDetect";
}
<p>
@ViewBag.Browser
</p>
How it works?
When we request the above url from Google chrome browser, because of “BrowserCheck” string in the starting
of the url (1st fragment in the url), either ConstraintCustomChrome or ConstraintCustom route should execute
(see RouteCongif.cs file) however in this case, the first one will execute as it has a constraint (4th parameter -
BrowserDetectConstraint) and we are passing “Chrome” as its parameter. In the BrowserDetectConstraint, Match
method returns true because the user agent will contain “Chrome” word (as the request is coming from Google
Chrome browser) that will instruct the ASP.NET MVC framework to go ahead and call the BrowserChromeDetect()
action (notice the url 2nd fragment) method of the RoutingStuffs controller from
MVCTraining5.Controllers.OtherFolder namespace.
Now, if the same url is browsed from different browser other than Google Chrome then the 2nd route from
RouteConfig.cs executes as the custom constraint (BrowserDetectConstraint) returns false so even if the url is
same but 1st route doesn’t executes. This intern call the RoutingStuffs controller from MVCTraining5.Controllers
folder that returns the respective view from /Views/RoutingStuffs/BrowserChromeDetect.cshtml (the default
view of this controller action method).
In order to expose a controller action method by a certain url, we can use attribute routing ie. specifying the
route with the help of attribute on action methods. To achieve this we need to modify our
App_Start/RouteConfig.cs file a bit.
APP_START/ROUTECONFIG.CS CODE
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id =
UrlParameter.Optional }
);
}
Notice the highlighted code above. This is important to work with the attribute routing. If this method is not
called in the RouteConfig.cs, attribute routing doesn’t work.
Now here is the action method of the controller that we want to expose with a specific url
CONTROLLER CODE
[Route("ITFunda")]
public ActionResult AttributeRouting()
{
return View("/Views/RoutingStuffs/ITFunda.cshtml");
}
Notice the attribute defined on the AttributeRouting() action method. In this case, we are instructing the ASP.NET
MVC Framework that if a request comes with http://servername/ITFunda, route it to this action method of the
controller.
VIEW CODE
@{
ViewBag.Title = "ITFunda";
<h2>ITFunda</h2>
How it works?
Requesting the above url, gives us below output in the browser as the action method returns ITFunda.cshtml
view that simply displays the ITFunda logo.
POINT OF INTEREST
Apart from just specifying static string in the Route attribute of Action method, we can also specify segments
variables. To learn more about it, please visit http://www.dotnetfunda.com/articles/show/3030/attribute-
routing-in-aspnet-mvc-5 article by me.
70. How to create a custom route handler in ASP.NET MVC to redirect the user
to a specific page for a specific url?
Custom route handler is used in a very specific scenario where we need to redirect the user to any external page
or shorted the long url or making the url more user friendly, readable and memorable.
To create a custom route handler, first create a .cs file and implement IRouteHandler interface. IRouteHandler
interface contains GetHttpHandler method that returns IHttpHandler. In our case, we have created
MyCustomRouteHandler class inside Utility folder.
UTILITY/MYCUSTOMROUTEHANDLER.CS CODE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
namespace MVCTraining5.Utility
{
public class MyCustomRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new MyClassHttpHandler();
}
}
In the above code, we have first created a class MyCustomRouteHandler that inherits IRouteHandler interface.
This interface has a method called GetHttpHandler that returns IHttpHandler interface. In our case, we have
returned MyClassHttpHandler class (defined in the same .cs file that implements IHttpHandler interface).
MyClassHttpHandler class implements two methods IsReusable and ProcessRequest of IHttpHandler. IsReusable
simply instruct the MVC framework whether this instance of IHttpHandler is reusable. The ProcessRequest
method in this case simply redirects the user to http://www.itfunda.com website.
After defining the MyCustomRouteHandler, we need to add it to the RouteCollection (register it).
APP_START/ROUTECONFIG.CS CODE
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id =
UrlParameter.Optional }
);
Here, we have added MyCustomRouteHandler into the Routes collection. Notice the first parameter of the Route
constructor while adding to the Routes collection, it is “itfunda”. Now run the program.
When browser request the url http://localhost:63087/itfunda, the user gets redirected to
“http://www.itfunda.com” website.
URLs
@Url.Action("Contact", "Home")
In the above Url.Action method, the first parameter is the name of the action method and the second parameter
is the name of the controller in which the action method exists.
The above overload method of the Url.Action has 3rd parameter as the object parameter that is used to pass the
parameter to the action method of the controller.
In this case, we are passing id = 54, com = delete and page = 5. If the action (in this case Index) is defined with
these 3 parameters, then the value of these parameter can be retrieved using those parameters like in below
action method.
return View();
}
If the action method is not defined with the parameters then these parameters becomes the querystring in the
url like
/Home/Index/54?com=delete&page=5
Here id is optional in the default route so it is set with the url segment but com and page is not defined in the
route as parameter so it becomes querystring. Note that Url.Action method only creates the url not the complete
hyperlink, to create hyperlink we need to use Html.ActionLink covered next.
return View();
}
As this method has no parameters so we are accessing the “com” and “page” querystring values using
Request.QueryString and “id” value as this.RouteData.Values
If the action method is defined with id as parameter then id value directly comes with the parameter and
remaining querystring values can be retrieved using Request.QueryString.
POINT OF INTEREST
Try different overload methods of the @Url.Action method and you will see that we have ability to pass
objectParameters, protocols etc.
Eg. If we want to create a url starting with https, we can give protocol parameter
Here, as I do not want to pass objectParameter so I have passed null and the 4th parameter is the “https” so our
url would look like https://localhost/Home/Contact
To create a hyperlink based on controller action method, we can use Html helper methods.
POINT OF INTEREST
We can also use different overload methods of the Html.ActionLink to format our hyperlink or apply css styles or
pass object parameters as we have passed in the Url.Action method previously.
Above ActionLink method will create a hyperlink with class attribute as “myCSSClass” and style as “color:red”.
Notice that the 3rd parameter is explicitly mentioning controller parameter as “Home” as in this overload method
the 3rd parameter is the object parameter.
Sometimes, while generating the url using @Html.ActionLink, sometimes the url doesn’t come as expected. Like
following @Html.ActionLink.
http://localhost:63087/?Length=4
The reason for rendering wrong url is the wrong parameter passed. In the above @Html.ActionLink method, the
3rd parameter is passed as “Home”, however the third parameter expected in this overload method of
@Html.ActionLink is routeValues. So the correct parameter for @Html.ActionLink overload method should be
Where 3rd parameter is routeValues and we have passed controller as “Home”. Now this will render the correct
url without “Length” querystring.
To create a url based on Route defined in the App_Start/RouteConfig.cs page, we can use @Url.RouteUrl method.
Let’s assume that following route has been defined in the RouteConfig.cs file
APP_START/ROUTECONFIG.CS
routes.MapRoute(
name: "MyCustomRoute",
url: "MyEmployees/{action}/{id}",
defaults: new { controller = "PersonalDetail", action = "Create",
id = UrlParameter.Optional }
);
To generate the url based on above Route, we can use @Url.RouteUrl method.
@Url.RouteUrl("MyCustomRoute")
Generates
/MyEmployees/outgoingurl
Because, we have not specified any parameters for controller and action method in the above RouteUrl
method so the current page controller and action method is taken as default value.
Generates
/MyEmployees/index/12?Name=Sheo
POINT OF INTEREST
Try different overload methods of the Url.RouteUrl method to get more customized and readymade url.
In ASP.NET MVC 5, ASP.NET Identity provider comes with the default project of ASP.NET MVC that help us
implementing forms authentication in the application. Following are the physical files of the default project that
are responsible to create the forms authentication as well as external (social) authentication.
/Startup.cs This class file is called when the application starts. It by default calls
Configuration method that intern call ConfigureAuth method that is
defined in /App_Start/Startup.Auth.cs file. Notice that both are same class
(partial) placed in two different physical files.
/App_Start/Startup.Auth.cs This file is responsible to call ApplicationUserManager,
ApplicationSignInManager and other classes to configure the
authentication. It is also used to configure cookies to be used for
authentication. Apart from internal authentication, ASP.NET MVC 5 also
allows social login from Google, Facebook, Twitter etc. This page also help
us configuring those by uncommenting respective lines of codes and setting
their keys and secret details.
To perform forms authentication, we do not need to change any setting in the default project. The only thing we
may need to change is the DefaultConnection under connectionStrings setting of root web.config file.
/WEB.CONFIG FILE
<connectionStrings>
<add name="DefaultConnection"
connectionString="Data Source=SNITFunda;Initial
Catalog=TrainingDatabase;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
By default, the connectionString value of DefaultConnction points to a LocalDB under App_Data folder. While
developing a real time application, we may need to set the database connection to any external database on
another server. So here we can change the connectionString.
Now everything is setup. To setup, run the application and click on Register link on the page. It redirects the user
to /Account/Register page that enable user to register to the website. When user clicks on the Register button on
this page, /Controllers/AccountController/Register(RegisterViewModel model) method executes that create a
new user (if database table is not already setup as per ASP.NET Identity provider then it creates following
database table.
Where
The remaining all methods to get confirm the email are already written in the controller, so we do not need to do
anything from our side.
To perform authorization, we can use Authorize attribute in the action method of the controller. We can
authorize users based on their username or role defined in the database.
CONTROLLER CODE
Above action method (corresponding view) will be accessible to only user whose username is “Ram”.
CONTROLLER CODE
Above method will be accessible only to those user whose role is “Admin” defined in the AspNetUserRoles
database table.
CONTROLLER CODE
Above method will be accessible only to those user whose role is “Admin” or “SuperAdmin” defined in the
AspNetUserRoles database table.
To mark a controller to be accessed only by a logged in user, we can use Authorize attribute.
CONTROLLER CODE
[Authorize]
public class AuthorizeController : Controller
{
Above controller action method will only be accessible to those user who are logged in. Despite Index method
doesn’t have Authorize attribute but this method will not be available to the anonymous user.
To make an action method public in secure controller, we can mark them as Anonymous.
CONTROLLER CODE
[Authorize]
public class AuthorizeController : Controller
{
[AllowAnonymous]
public ActionResult PublicPage()
{
return View();
}
In above case, even if the controller is marked as secure (decorated with Authorize attribute), the PublicPage
action method will be accessible for all user even without logging in.
Error handling
79. How to handle error in controller action method and pass error to the
View?
To pass error to the view we can use ModelState.AddModelError method (if the error is Model field specific) or
simply ViewBag or ViewData can also be used.
CONTROLLER CODE
[HttpPost]
[ValidateAntiForgeryToken()]
public ActionResult CreateForValidation(PersonalDetail model)
{
if (ModelState.IsValid)
{
if (model.FirstName == null)
{
ModelState.AddModelError("", "Please write first name.");
// ModelState.AddModelError("FirstName", "Please write first
name.");
}
}
return View(model);
}
Above action method accepts PersonalDetail model whose FirstName is mandatory (We are assuming that
FirstName field is not specified as Required in the PersonalDetail.cs file). If we want to validate this field in the
action method and pass error to the View, we will use ModelState.AddModelError method.
I. Key – if empty, it shows error written in the 2nd parameter at place where
@Html.ValidationSummary(true, "", new { @class = "text-danger" }) is written in
the view.
If key is specified as “FieldName” (in this case “FirstName” – see the commented code) then the error
In this case, simply set the value of VIewBag and print it on the view wherever required.
CONTROLLER CODE
[HttpPost]
[ValidateAntiForgeryToken()]
public ActionResult CreateForValidation(PersonalDetail model)
{
if (ModelState.IsValid)
{
if (model.FirstName == null)
{
ViewBag.FirstNameError = "Please write first name";
}
}
return View(model);
}
VIEW CODE
<p class="text-danger">
@ViewBag.FirstNameError
</p>
80. How to handle error for controller action method and redirect the user to
a default error page?
To handle the error for the controller action method, first set the customError mode “on” under system.web in
the root web.config file.
WEB.CONFIG FILE
<system.web>
<customErrors mode="On"/>
</system.web>
When the customErrors mode is “On”, any unhandled error redirects to the default error view that is under
~/Views/Shared/Error.cshtml
CONTROLLER CODE
Above controller method will throw error and because customErrors mode is set to “On” in web.config file so
user gets redirected to below view page under Shared folder.
VIEW CODE
@model System.Web.Mvc.HandleErrorInfo
@{
ViewBag.Title = "Error";
}
<hgroup class="title">
<h1 class="error">Error.</h1>
<h2 class="error">An error occurred while processing your request.</h2>
</hgroup>
<p>
Controller: @Model.ControllerName
</p>
<p>
Action: @Model.ActionName</p>
<p>
Exception: @Model.Exception</p>
In the above view, the model is System.Web.Mvc.HandleErrorInfo that holds the error exception details like
ControllerName, ActionName in which error occurred and what error occurred.
Above functionality will work only when below settings (comes with default project) remains intact in
~/App_Start/FilterConfig.cs page.
81. How to handle a specific type of error for the controller and redirect user
to an error specific page?
Let’s assume that we have a controller in which different types of errors may occur. In this scenario, redirecting
the user to a generic error page may not make much sense and may not help user solve the problem if the
problem is coming because of data entered by him.
Displaying error page specific to type of error occurred and displaying helpful information on that page would
make much sense so that the user understand what actually is happening and what action he/she may take to
solve the problem.
The other side of this scenario can be showing error page based on error type assigned to team members or
there can be many other scenario one can think of where we need to show error page specific to that type of
error.
CONTROLLER CODE
In the above controller method, we have added a HandleError attribute where first parameter is ExceptionType
(the type of exception we want to catch) and 2nd parameter is the View to show when this type of exception
occurs in this action method.
~/VIEWS/SHARED/NULLREFERENCE.CSHTML
@{
ViewBag.Title = "NullReference";
}
<h2>Null Reference</h2>
Null Reference Error occurred.
Above is the code for the View that renders when NullReferenceException occurs. As this view has been kept
inside the ~/Views/Shared folder so the View name specified as the 2nd parameter of the HandleError attribute of
the action method doesn’t need to specify the path along with the view name.
Similarly, other HandleError attribute can be applied to the same action method for different types of error.
© SN ITFunda Services LLP – http://sn.itfunda.com 82
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks Validation
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
var i = 5;
var j = 0;
var sum1 = i / j;
return View();
}
Notice the above action method where we have two HandleError attributes for different types of error, both with
respective view.
Note that all these will work only when customErrors mode is “On” in the web.config file.
Validation
82. How to prevent Cross-Site Request Forgery (CSRF) attack in ASP.NET MVC?
To avoid cross site scripting attack where a request to submitted to the form that is not originally the form where
the request should be submitted, we can use @Html.AntiForgeryToken() in the form.
VIEW CODE
@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<div class="editor-label">
@Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.FirstName)
@Html.ValidationMessageFor(model => model.FirstName)
</div>
}
Notice the @Html.AntiForgeryToken line in the above form. Because of that line, a hidden element is generated
in the form with encrypted value that is validated in the server side to ensure that CSRF is not happening.
Just keeping the @Html.AntiForgeryToken() in the form is not enough. We also need to add
ValidateAntiForgeryToken attribute in the action method of the controller where the form is being submitted.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(PersonalDetail personaldetail)
{
Now, we can be 100% sure that the request coming to this action method is 100% originating from our own form
and there is no CSRF.
Custom validation is useful when the inbuilt validation attribute doesn’t solve our validation problem. We have
already talked about validation attributes while creating Models in above points. Like Range, StringLength,
Required etc.
In this example, we will create a validation attribute that let us define a Date type of field that only accepts a date
earlier than today’s date.
using System.ComponentModel.DataAnnotations;
public class DateValidationAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
DateTime todayDate = Convert.ToDateTime(value);
return todayDate <= DateTime.Now;
}
}
Notice that above class name ends with “Attribute” word, its a naming convention we should follow while
declaring a class for the attribute. Above class inherits a class named “ValidationAttribute” that has few virtual
method overloads named IsValid (most important, other virtual methods are also there) that we need to override
in our validation class.
In the above class we are overriding IsValid method that accepts the value as object of the field on which this
attribute will be applied.
If the field date value is lesser than current date, it returns true otherwise false (ie. The validation failed).
To use this validation attribute defined, we write as an attribute to the model field as we write other in built
validation attributes
[DateValidation]
public DateTime? BirthDate { get; set; }
OR
In the first case, we have just placed the [DateValidation] attribute on the BirthDate property of the Model. This
gives following error when date is passed later than today.
If we want a custom error to display if the validation fails for this field, then we need to pass the “ErrorMessage”
value with the attribute and it will works like below.
Similarly, we can also overload other IsValid method that accepts ValidationContent as 2nd parameter.
Here, the error message is being sent from this validation class itself.
[AdultAgeValidation]
public int Age { get; set; }
Above Age field only accepts age that is greater than 18.
84. How to mark a form to not validate the input data for any HTML or script
data?
To mark an action method that accepts HTML or scripts data as well, we can decorate that with
[ValidateRequest(false)] attribute.
// try entering html content in the multi area textbox when it is false
[ValidateInput(false)]
[HttpPost]
public ActionResult DoNotValidateInput(FormCollection form)
{
var data = form["txt"];
return Content(data);
}
VIEW
The above form will accepts HTML and other script data too apart from normal data as shown in the picture
below.
If we remove the [ValidateInput(false)] attribute from the above action method and submit the same above form,
it throws below error (A potential dangerous Request.Form value was detected).
Before we start seeing how to implement remote validation, let’s understand what Remote validation is. Remote
validation is a special type of validation that is used on a Model field that can’t be validated on the client side and
is therefore likely to fail validation when the form is submitted.
This is particularly used in the registration scenario when we ask for username from the user. As user types, we
send partial request on the server with current data and check if that username exists and shows “already exists”
message to the user in real time.
To do this, we need to decorate the Model field with [Remote] attribute like this (In this case, I have
demonstrated this on FirstName property of the Model).
MODEL CODE
© SN ITFunda Services LLP – http://sn.itfunda.com 87
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks Validation
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
In this case Remote attribute accepts two parameters “action name” and “controller in which the action method
exists”. In our case action method is “CheckForDuplication” and controller is “Validation”.
if (data != null)
{
return Json("Sorry, this name already exists",
JsonRequestBehavior.AllowGet);
}
else
{
return Json(true, JsonRequestBehavior.AllowGet);
}
}
Above method is the controller action method that accepts the FirstName as parameter and returns JsonResult.
In this method, we are getting the record based on FirstName coming in from the textbox from the form and if
that exists in our database we are returning “Sorry, this name already exists” otherwise we are returning true.
We do not need to do any change in the View and it renders as default with the Scaffolding template.
VIEW CODE (FOR CLARITY PURPOSE, ONLY FOR FIRSTNAME FIELD CODE ID SHOWN HERE)
<div class="editor-label">
@Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.FirstName)
@Html.ValidationMessageFor(model => model.FirstName)
</div>
When user start entering characters, if it is less than 4 characters long the inbuilt StringLength validation executes
and throws error to write at least 4 characters. When user writes at least 4 characters, the partial request goes to
© SN ITFunda Services LLP – http://sn.itfunda.com 88
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks Validation
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
the server as user types to the CheckForDuplication action method of the ValidationController and based on what
the method returns, it shows message.
This is shown when the given name already exists in the database, otherwise no message is shown.
86. How to validate the data passed in url at the routing level itself in ASP.NET
MVC?
Apart from Model validation, custom validation and other validations we have seen, the data can also be
validated at the route level itself when any segment variables data is passed in the url.
Let’s assume that we have to restrict a certain URL pattern for those controllers whose name starts with “R”, we
can specify below routes.
/APP_START/ROUTECONFIG.CS
Notice the 4th parameter in above code. This instructs that if the controller name starts with “R” then this route is
used to serve the request. (Note that default route mechanism doesn’t need to be removed).
{
return View();
}
Similarly, we can also restrict the action method of a specific controller by specifying below route config.
// goes to the url, when the controller starts with R and action is either Index or
About
routes.MapRoute("ConstrainRouteRA",
"{controller}/{action}/{id}/{*catchall}",
new { controller = "RoutingStuffs", action = "Index", id =
UrlParameter.Optional },
new { controller = "^R.*", action = "^Index$|^About$" });
Restricting a request whose controller starts with H, action method is either Index or About and Id segment value
is in between 10 and 20.
In this case, we might need to comment the default route that comes with project template so that it doesn’t
conflict with this.
http://localhost:63087/Home/Index/155 doesn’t work as Id segment value is 155 not between 10 and 20.
http://localhost:63087/Home/Index/15 work as the Id segment value is in between 10 and 20
© SN ITFunda Services LLP – http://sn.itfunda.com 90
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks Validation
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
Fluent validation framework is a small validation library that uses fluent interface and lamda expressions to
building validation rules in the Models. This is an extension of the default validation framework that comes with
ASP.NET MVC. In this, writing validation logics are much easier than writing default framework plus it
accommodates much broader types of validations.
In order to implement fluent validation, we need to plug-in the fluent validation framework into our project by
using “Mange NuGet Packages” by right clicking the project and selecting “Manage NuGet Packages …”.
Now write fluent into the search box that lists the Fluent related plug ins.
Clicking on Install, installs the FluentValidation framework in our project by adding FluentValidation.dll in the .bin
folder.
To demonstrate how to use Fluent Validation framework, here is a new model created. Notice that we do not
have any validation attribute in this model.
MODEL CODE
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MVCTraining5.Models
{
public class FluentModel
{
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOpt
ion.Identity)]
public int AutoId { get; set; }
}
}
To create validation rules for this model, we need to create a Validator class (corresponding to each model).
using FluentValidation;
using MVCTraining5.Models;
namespace MVCTraining5.Validation
{
public class FluentModelValidator : AbstractValidator<FluentModel>
{
public FluentModelValidator()
{
RuleFor(model => model.FullName).NotNull(); // Required
Notice that this class inherits the AbstractValidator class by passing FluentModel we just created. Now we need
to write rules for fields we want to validate. In this case, we have rule for FullName, Email Id (Required), EmailId
to make sure that user enters email id in correct format, Age so that user enters age that is greater than 18.
The view of this Model (FluentModel) remains same as in case of standard model that comes with scaffolding.
}
return View(model);
}
The action method is slightly different as we need to validate it using FluentValidation framework. Instantiate the
FluentModelValidator class and call Validate method that returns ValidationResult object that is IsValid property.
If IsValid is true then validation rules for FluentModel is passed otherwise not. In the else block we are looping
through each error and setting to the AddModelError so that it displays beside each error field.
Notice the above view that is showing the default error message as per the rule.
For more rules of FluentValidation and how to apply them, please visit
http://fluentvalidation.codeplex.com/documentation
Session management
To store data in session, we do as we used to do in ASP.NET Web Form (Please refer to our ASP.NET Tips & Trick
ebook and video tutorials on http://www.ITFunda.com).
Session stores the data in key and value format. Value gets stored in object format, so any type of data can be
stored into the Session.
if (Session["MySession"] == null)
{
Session["MySession"] = DateTime.Now; // specific to user
}
To set the timeout of session (after which the session data expires)
Data stored in the Session for this specific user, gets expired after 30 minutes.
Caching
To cache (temporary store the application specific data to send to the user) the output of the action method, we
can use OutputCache attribute in the action method of the controller.
CONTROLLER METHOD
[OutputCache(Duration=10)]
public string Index()
{
return DateTime.Now.ToString();
}
The output of this action method will be cached for 10 seconds (the current date). Calling this action method
simply show the current date in the browser. The same can be applied any action method that returns
ActionResult.
91. How to specify a profile for the output cache and use it in multiple
actions?
The benefit of creating an output cache profile is to set the same setting in multiple action methods. If change is
needed, changing the profile value affects all action method using this profile.
The cache profile can be created in root web.config file under system.web.
WEB.CONFIG
<system.web>
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="Cache1Minute" duration="60" varyByParam="none"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
</system.web>
Notice the highlighted settings. Here we have created a profile named “Cache1Minute” and set the duration as
60 seconds. The VarByParam is “None” so that the cached data will be saved only once for any parameter passed
to the action method. This works same as ASP.NET Web Form OutputCache directive and VarByParam.
CONTROLLER METHOD
Note that OutpurCache attribute has CacheProfile parameter set as “Cache1Minute” and its location is Server so
the data cached by ASP.NET Framework for this method will be saved into the server. Every time this action
method will be called within 60 seconds, the output of the 1st request will be served. After 60 seconds, the whole
method again executes and the current date time is saved into the server temporary memory again and served
by server memory and so on.
To cache a partial view output, we again use the same OutputCache attribute to the action method that returns
partial view result. To demonstrate this, lets create a example.
CONTROLLER METHOD
@{
ViewBag.Title = "Partial View Cache";
}
@{
Html.RenderAction("PartialViewCacheChild");
}
@*@Html.Action("PartialViewCacheChild")*@
CONTROLLER METHOD
[ChildActionOnly]
[OutputCache(Duration = 10)]
public PartialViewResult PartialViewCacheChild()
{
return PartialView("_PartialViewForCache");
}
The above method is a child action method, it means this method can’t be called directly from the url like any
other action method. It can only be called from within a View with the help of @Html.RenderAction or
@Html.Action
Now create a partial view (follow the steps described in how to create a partial view point above).
_PARTIALVIEWFORCACHE.CSHTML VIEW
Now when the first Action method (PartialViewCache) is called, the PartialViewCache view renders that internally
calls PartialViewCacheChild method of the same controller that returns _PartialViewForCache partial view.
Notice that in both view and partial view, current time is being retuned. Notice the definition of the
PartialViewCacheChild method that is decorated with OutputCache with duration as 10; ie it its output will be
cached for 10 seconds.
Next request within 10 seconds give the same output from the partial view however the current date time of the
View changes
Storing data into Cache in ASP.NET MVC is not as straightforward as it was in ASP.NET Web Form where we used
to use Cache[“key”] and value.
Here, we will need to use HttpContext.Cache object and remaining approach are same.
CONTROLLER METHOD
ViewBag.DateTime = HttpContext.Cache["MyDate"];
return View();
}
Above action method first checks for the null value in HttpContext.Cache[“MyDate”] and it its null then saves
current date in the Cache. Next line simply keep the data from the Cache into ViewBag.DateTime.
VIEW
@{
ViewBag.Title = "Cache Output";
}
<h2>Cache Output</h2>
The same ViewBag.DateTime is being retrieved in the above view and the output looks like below.
Database operations
To list the data from the database, we can use the default scaffolding template generated while we create
Controller and View based on the Model (Explained while how to scaffold Controller and View in above points,
the view pages uses bootstrap classes to make it screen friendly page).
Let’s understand how list of data is working in the Index action method of the controller that is responsible to list
the record from the database.
We will be using Model for the below database table where AutoId is the auto increment field. Remaining fields
are self-understood.
MODEL CODE
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOpt
ion.Identity)]
public int AutoId { get; set; }
}
}
Please read Model related points above to understand above Model class completely, if you do not understand
about it.
We have already gone through steps on how to scaffold Controller template and View based on the Model in the
above points (See how to scaffold a View and Controller based on a Model?) point. If we follow this point, we will
be getting Index action method in the PersonalDetailsController and Index view in the
~/Views/PersonalDetails/Index.cshmlt.
CONTROLLER CODE
// GET: PersonalDetails
public ActionResult Index()
{
return View(db.PersonalDetails.ToList());
}
The above method gets the db object that is nothing but the ApplicationContext (ADO.NET Entity Framework)
object and calls the PersonalDetails (this is the property in the IdentityModel.cs that gets created when we
scaffold the Controller and Model).
This returns all records from the PersonalDetails database table and convert them into List and returns to the
View.
@model IEnumerable<WebApplication1.Models.PersonalDetail>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.FirstName)
</th>
<th>
@Html.DisplayNameFor(model => model.LastName)
</th>
<th>
@Html.DisplayNameFor(model => model.Age)
</th>
<th>
@Html.DisplayNameFor(model => model.Active)
</th>
<th></th>
</tr>
</table>
The above Index view has IEnumerable<WebApplication1.Models.PersonalDetails> Model and then we are using
HTML table element to create header of the list and then iterating through the Model (that is nothing but the
collection of PersonalDetails).
Here
@Html.DisplayNameFor(model => model.FirstName) is used to write the heading of the column that
is nothing but the Name value of Display attribute for a Model property, if Dispay property is not
specified then Model property name is written.
@Html.DisplayFor(modelItem => item.FirstName) is used to write the value of the Model property.
The last column of the HTML table is three links Edit, Details and Delete that redirect to respective
Views.
=> is a Lamda expression, a way to retrieve the property of the Model using.
To insert a record into database we can use the same scaffold view and action method Create.cshtml and Create
action methods in the controller.
// GET: PersonalDetails/Create
public ActionResult Create()
{
return View();
}
// POST: PersonalDetails/Create
// To protect from overposting attacks, please enable the specific
properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include =
"AutoId,FirstName,LastName,Age,Active")] PersonalDetail personalDetail)
{
if (ModelState.IsValid)
© SN ITFunda Services LLP – http://sn.itfunda.com 103
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks Database operations
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
{
db.PersonalDetails.Add(personalDetail);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(personalDetail);
}
The first Create method simply returns the Create.cshtml view from /Views/PersonalDetails folder whose model
is specified as PersonalDetail.
CREATE.CSHTML VIEW
@model WebApplication1.Models.PersonalDetail
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm())
{
<text>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>PersonalDetail</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.FirstName, new { htmlAttributes = new
{ @class = "form-control" } })
@Html.ValidationMessageFor(model => model.FirstName, "", new {
@class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="form-group">
@Html.LabelFor(model => model.Age, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Age, new { htmlAttributes = new {
@class = "form-control" } })
@Html.ValidationMessageFor(model => model.Age, "", new { @class =
"text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Active, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
@Html.EditorFor(model => model.Active)
@Html.ValidationMessageFor(model => model.Active, "", new {
@class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
In the above view we are creating a View using @Html.BeginForm() having @Html.AntiForgeryToken() method
(explained above). There are many more Html helper methods used for different purpose
@Html.ValidationSummary – to show summary of the validation failed error. It generally shows those
error that has been added with Empty key value in the ModelState.AddModelError
@Html.LabelFor – used to create label for that particular property or Html form element
@Html.EditorFor - used to render Html form element corresponding to field type (string, integer,
date type etc.)
@Html.ValidationMessageFor – used to create a placeholder that will show error message for that
field.
Remaining HTML are simple HTML codes used to create Form layout, CSS classes used in this form comes from
bootstrap classes.
The second Create method binds the property of the PersonalDetail method (it is not mandatory however to
avoid over posting attack, this is the way where only those properties of the Model is retrieved from the form
that are used in the Bind.). Inside the action method, we call ModelState.IsValid property that validate each
model property against the validation attribute used and it returns true or false. If validation is passed, the same
PersonalDetail object is added into PersonalDetails collection and SaveChanges() method is called to save the
data into the database. Then user gets redirected to the Index view.
If the validation fails, the user sees the same Create view again with validation errors.
If everything is fine, it create a new record into the database and redirect the user to the Index page.
To update a record into the database, we can use the same scaffolding template we were talking above.
NOTE: In order to understand this completely, you are recommended to read immediate above points, “How to
insert …..) as in this point I have cut short few topics that are repetitive in nature.
// GET: PersonalDetails/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
PersonalDetail personalDetail = db.PersonalDetails.Find(id);
if (personalDetail == null)
{
return HttpNotFound();
}
return View(personalDetail);
}
// POST: PersonalDetails/Edit/5
// To protect from overposting attacks, please enable the specific
properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include =
"AutoId,FirstName,LastName,Age,Active")] PersonalDetail personalDetail)
{
if (ModelState.IsValid)
{
db.Entry(personalDetail).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(personalDetail);
}
In the first action method, id parameter is checked for null, if null it returns Bad Request otherwise record having
primary key value as id is found and returned to the Edit view.
@model WebApplication1.Models.PersonalDetail
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>PersonalDetail</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.AutoId)
<div class="form-group">
@Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.FirstName, new { htmlAttributes = new
{ @class = "form-control" } })
@Html.ValidationMessageFor(model => model.FirstName, "", new {
@class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.LastName, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.LastName, new { htmlAttributes = new
{ @class = "form-control" } })
@Html.ValidationMessageFor(model => model.LastName, "", new { @class
= "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Age, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Age, new { htmlAttributes = new {
@class = "form-control" } })
@Html.ValidationMessageFor(model => model.Age, "", new { @class =
"text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Active, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
@Html.EditorFor(model => model.Active)
@Html.ValidationMessageFor(model => model.Active, "", new {
@class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Above view is almost similar to the Create view except @Html.HiddenFor that renders a hidden element with
current primary key value used to find and update the record.
Clicking on Edit link on the list page (Index) brings us to Edit page for respective record.
Clicking on Save button fires 2nd Edit action method that checks for validation errors in the Model, if OK finds
makes the state of that record to Modified and calls SaveChanges() method to save the record into data. If the
model is not valid, it redirects on the same Edit page and shows validation errors.
Clicking on Save button after modifying records into the form update the record and redirect to the Index view.
To delete a record from database, again we will be using the same scaffolding template.
// GET: PersonalDetails/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
PersonalDetail personalDetail = db.PersonalDetails.Find(id);
if (personalDetail == null)
{
return HttpNotFound();
}
return View(personalDetail);
}
// POST: PersonalDetails/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
PersonalDetail personalDetail = db.PersonalDetails.Find(id);
db.PersonalDetails.Remove(personalDetail);
db.SaveChanges();
return RedirectToAction("Index");
}
In the first Delete action method, we find out the value of id; if null redirects to BadRequest otherwise finds the
record and return to Delete view with PersonalDetail model.
@model WebApplication1.Models.PersonalDetail
@{
ViewBag.Title = "Delete";
}
<h2>Delete</h2>
<dd>
@Html.DisplayFor(model => model.FirstName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.LastName)
</dt>
<dd>
@Html.DisplayFor(model => model.LastName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Age)
</dt>
<dd>
@Html.DisplayFor(model => model.Age)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Active)
</dt>
<dd>
@Html.DisplayFor(model => model.Active)
</dd>
</dl>
@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
This view retrieve the Model data and show the record selected for delete. Read the “How to list …. point above
in this series to understand about @Html.DisplayNameFor and @Html.DisplayFor methods.
Clicking on Delete button calls DeleteConfirmed action method. Notice the attribute ActionName that instruct
the ASP.NET MVC framework that despite the name of the method is DeleteConfirmed, it’s name should be
treated as Delete. This is because we can’t keep the same name of the action method with same parameter. This
is a trick to fool C# compiler.
DeleteConfirmed method finds the record to delete and add into Remove method and calls SaveChanges()
method to physically remove this record from the database.
To upload an image on the server, we need to tweak the Forms element enctype in the Html.BeginForm helper
method.
First let’s create a model that will hold the information about the file uploaded.
{
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOpt
ion.Identity)]
public int AutoId { get; set; }
In the above model, we are not going to use FileContent property for now however we have all above
corresponding fields into our database table.
@model MVCTraining5.Models.Files
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<div class="form-horizontal">
<h4>Files</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.FileName, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
<input type="file" name="FileName" id="FileName" class="form-
control" />
@Html.ValidationMessageFor(model => model.FileName, "", new { @class
= "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Active, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
@Html.EditorFor(model => model.Active)
@Html.ValidationMessageFor(model => model.Active, "", new {
@class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Upload" class="btn btn-default" />
</div>
</div>
</div>
}
In the above code snippet, we have passed custom action method and controller name to submit this form. Apart
from this we have also enctype (encryption type) set as an attribute to the form (to multipart/form-data).
After that remaining codes are normal html form elements and normal asp.net MVC html helper methods. One
small difference is we are using HTML input type=file to provide file upload ability to the user. The name of this
element is same as the name in the model property (FileName).
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include =
"AutoId,FileName,Active,PersonalDetailsId")] Files files, HttpPostedFileBase
FileName)
{
if (ModelState.IsValid)
{
// set the final file name to the files object so the name would get
saved into the database
files.FileName = finalFileName;
db.Files.Add(files);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(files);
}
The controller action method one extra parameter apart from the Model name and that is HttpPostedFileBase
whose name MUST be the name of the input type=file element. This will ensure that the form File element is
accessible through this name.
After validating the ModelState, we are getting the path to save, getting the extension name of the user selected
file (notice that we have generated a random string as file name and suffixed the extension name to ensure that
each uploaded file name is unique on the server) and finally calling the SaveAs method of the File html control by
passing the path and file name.
Next, we are setting the property of the Files object to the name of the file and calling the SaveChanges()
method.
Before proceeding with this example, it is recommended to learn how to upload a single file on the server in the
previous examples.
To upload multiple file, we will follow the same approach as we followed for single file upload however the way
to access the form file element would be little different.
VIEW CODE
<div class="form-group">
@Html.LabelFor(model => model.Active, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
@Html.EditorFor(model => model.Active)
@Html.ValidationMessageFor(model => model.Active, "", new {
@class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Upload Multiple" formnovalidate
class="btn btn-default" />
</div>
</div>
</div>
}
In the above code snippet, we have more than one html file upload element and remaining codes are same as
last point of uploading a single file on the server. When this form will be submitted, it will go to
UploadMultipleFiles action method of the controller. Notice that the name of the file upload elements are same.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UploadMultipleFiles([Bind(Include =
"AutoId,FileName,Active,PersonalDetailsId")] Files files,
IEnumerable<HttpPostedFileBase> fileNames)
{
if (ModelState.IsValid)
© SN ITFunda Services LLP – http://sn.itfunda.com 119
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks Database operations
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
// set the final file name to the files object so the name
would get saved into the database
files.FileName = finalFileName;
db.Files.Add(files);
db.SaveChanges();
}
}
return RedirectToAction("Index");
}
In this action method notice the 2nd parameter that is IEnumerable of HttpPostedFileBase because the form sends
more than one form file element, also the name of this parameter must be exactly same as the name of the form
file element.
After validating the ModelState, we are iterating through each File element of the form and checking for its
length to ensure that file upload code only executes when user has selected any file. Once the file content length
validation is passed, we get the extension name, random file name and saves the file on the disk and then set its
name into the Files property and call the SaveChanges method.
Pagination is useful when we have to list more number of records from the database so that all records doesn’t
show in one page. Clicking on page numbers show records for that page so that it’s easy for users to navigate all
records.
As ASP.NET MVC doesn’t have inbuilt much efficient and easy mechanism to paginate records from the database,
we will use a plugin named PagedList.
Search PagedList using search box and click on Install. Remember to install both PagedList and PagedList.Mvc.
This adds PagedList.dll, PagedList.Mvc.dll into the bin folder and also PagedList.css into ~/Content folder.
CONTROLLER CODE
using PagedList;
This method accepts page as parameter and it’s default value is 1. When we use PagedList namespace, it gives us
ToPagedList method that accepts page and record per page as parameter.
~/VIEWS/PERSONALDETAILS/PAGEING.CSHTML
@using PagedList;
@using PagedList.Mvc;
@model IPagedList<WebApplication1.Models.PersonalDetail>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Age
</th>
<th>
Active
</th>
<th></th>
</tr>
</table>
<div class="pagedList">
@Html.PagedListPager(Model, page => Url.Action("Paging", new { page }),
PagedListRenderOptions.PageNumbersOnly)
</div>
Notice the @using directive where we have used PagedList and PagedList.Mvc. And also @model directive is not
IEnumerable any more but it is IPagedList.
Note that from the heading part of each column we have removed @DisplayNameFor method and hard coded
the heading as @DisplayNameFor is not supported by IPagedList.
Now look carefully the highlighted code that is rendering the Page numbers by using @Html.PagedListPager
method by passing the action method to redirect to with the current page and type of pagination to use. This
renders view like below. Trying clicking Page numbers and we get records for that respective page.
There are many enumerations for PagedListRenderOptions, try different one to get different paging look and feel.
To demonstrate the sorting and paging both functionality, we shall create new action methods and views that
would be easy to explain and understand.
Let’s create an action method in the controller named PagingAndSorting. Understanding the action method
would be difficult for now; but do not worry I would explain all codes line by line.
CONTROLLER CODE
/// <summary>
/// Sort and paginate records from the database
/// </summary>
/// <param name="sortOn">field to sort on field</param>
/// <param name="orderBy">order by ascending or descending</param>
/// <param name="pSortOn">previous sorted on field</param>
/// <param name="page">page number to show</param>
/// <returns></returns>
public ActionResult PagingAndSorting(string sortOn, string orderBy, string
pSortOn, int? page)
{
int recordsPerPage = 3;
if (!page.HasValue)
{
© SN ITFunda Services LLP – http://sn.itfunda.com 124
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks Database operations
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
// override the sort order if the previous sort order and current
request sort order is different
if (!string.IsNullOrWhiteSpace(sortOn) && !sortOn.Equals(pSortOn,
StringComparison.CurrentCultureIgnoreCase))
{
orderBy = "asc";
}
ViewBag.OrderBy = orderBy;
ViewBag.SortOn = sortOn;
switch(sortOn)
{
case "FirstName" :
if (orderBy.Equals("desc"))
{
list = list.OrderByDescending(p => p.FirstName);
}
else
{
list = list.OrderBy(p => p.FirstName);
}
break;
case "LastName":
if (orderBy.Equals("desc"))
{
list = list.OrderByDescending(p => p.LastName);
}
else
{
list = list.OrderBy(p => p.LastName);
}
break;
case "Age":
if (orderBy.Equals("desc"))
{
list = list.OrderByDescending(p => p.Age);
}
else
{
Corresponding view of the above action method looks like below. Notice that the view of this action method is
more or less similar to Pagination view (previous point) however there would be certainly difference in the
header and pagination code as we have to make the header as hyperlink so that it is clickable and user can click
fields to sort on. Paging link also needs a change so that it persist the selected column to sort on.
It goes without saying that we will be using PagedList plugin to achieve pagination however for sorting we will
write our own code.
VIEW CODE
@using PagedList;
@using PagedList.Mvc;
@model IPagedList<WebApplication1.Models.PersonalDetail>
<h2>Pagination</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
Auto Id
</th>
<th>
@Html.ActionLink("First Name", "PagingAndSorting", new { sortOn =
"FirstName", orderBy = ViewBag.OrderBy, pSortOn = ViewBag.SortOn })
</th>
<th>
@Html.ActionLink("Last Name", "PagingAndSorting", new { sortOn =
"LastName", orderBy = ViewBag.OrderBy, pSortOn = ViewBag.SortOn })
</th>
<th>
@Html.ActionLink("Age", "PagingAndSorting", new { sortOn = "Age",
orderBy = ViewBag.OrderBy, pSortOn = ViewBag.SortOn })
</th>
<th>
Active
</th>
© SN ITFunda Services LLP – http://sn.itfunda.com 126
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks Database operations
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
<th></th>
</tr>
</table>
<div class="pagedList">
@Html.PagedListPager(Model, page => Url.Action("PagingAndSorting", new { page,
sortOn = ViewBag.SortOn, orderBy = ViewBag.OrderBy, pSortOn = ViewBag.SortOn }),
PagedListRenderOptions.ClassicPlusFirstAndLast)
</div>
In the above view, we have notice that the header of the table is @Html.ActionLink apart from Auto Id and Action
as we do not want them to be sorted on.
c. pSortOn – is the field name on which the displayed record is sorted on (this is to
ensure that if different column is clicked on the sorted record then it loose the
current sorting order and bring records sorted by new column in ascending order.
As we need to maintain the current sorting order while paginating records as well so we need all above
parameters values along with paging links as well.
Notice the @Html.PagedListPager method in which apart from page, we have also passed sortOn, orderBy and
pSortOn parameters just the same way we have passed in @Html.ActionLink in the header.
Now, when the page runs for the first time, it look like below
In the first run, sortOn, orderBy, pSortOn and page all are null. In the method itself we are setting the
recordsPerPage value. If page doesn’t have value, we are setting default page as 1 and changing orderBy from asc
(ascending order) to desc (for descending order). If order by is null we are setting it to asc.
If the current sort order “sortOn” is not equal to previous field sort order “pSortOn” then we are resetting the
sort order to asc to make the sorting in ascending order. This case will happen in the scenario where let’s say user
has sorted records on “First Name” in descending order and then clicked on “LastName” field, we want the
record to be sorted in “Last Name” ascending order not in the previously sorted order.
Now based on sortOn field value we are getting the sorted data from database either ascending or descending
order.
That sorted record is being passed to PagedList that in turn is being returned to view to display.
102. How to perform a search based on a keyword from the database table in
ASP.NET MVC?
To demonstrate this we are extending the above point example in which we would be implementing search as
well as sorting and paging. Below is the code of action method that accepts one more parameter called
“keyword”.
CONTROLLER CODE
/// <summary>
/// Sort and paginate records from the database
/// </summary>
/// <param name="sortOn">field to sort on field</param>
/// <param name="orderBy">order by ascending or descending</param>
/// <param name="pSortOn">previous sorted on field</param>
/// <param name="keyword">keyword to search from the database</param>
/// <param name="page">page number to show</param>
/// <returns></returns>
public ActionResult PagingSortingAndSearching(string sortOn, string orderBy,
string pSortOn, string keyword, int? page)
{
int recordsPerPage = 3;
© SN ITFunda Services LLP – http://sn.itfunda.com 130
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks Database operations
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
if (!page.HasValue)
{
page = 1; // set initial page value
if (string.IsNullOrWhiteSpace(orderBy) || orderBy.Equals("asc"))
{
orderBy = "desc";
}
else
{
orderBy = "asc";
}
}
// override the sort order if the previous sort order and current
request sort order is different
if (!string.IsNullOrWhiteSpace(sortOn) && !sortOn.Equals(pSortOn,
StringComparison.CurrentCultureIgnoreCase))
{
orderBy = "asc";
}
ViewBag.OrderBy = orderBy;
ViewBag.SortOn = sortOn;
ViewBag.Keyword = keyword;
switch (sortOn)
{
case "FirstName":
if (orderBy.Equals("desc"))
{
list = list.OrderByDescending(p => p.FirstName);
}
else
{
list = list.OrderBy(p => p.FirstName);
}
break;
case "LastName":
if (orderBy.Equals("desc"))
{
list = list.OrderByDescending(p => p.LastName);
}
else
{
list = list.OrderBy(p => p.LastName);
}
break;
case "Age":
if (orderBy.Equals("desc"))
{
list = list.OrderByDescending(p => p.Age);
}
else
{
list = list.OrderBy(p => p.Age);
}
break;
default:
list = list.OrderBy(p => p.AutoId);
break;
}
if (!string.IsNullOrWhiteSpace(keyword))
{
list = list.Where(f => f.FirstName.StartsWith(keyword));
}
var finalList = list.ToPagedList(page.Value, recordsPerPage);
return View(finalList);
}
Notice the highlighted code above. The first is in the parameter of the action method in which we have keyword
parameter that will have the keyword to search in the database. The last highlighted lines checks for the value of
the keyword, if its null or empty it ignores the search filter and gives all records from the database.
If keyword has some value, it search the sorted results based where FirstName starts with keyword. Similarly, we
can also try to search on different fields or more than one fields.
VIEW CODE
@using PagedList;
@using PagedList.Mvc;
@model IPagedList<WebApplication1.Models.PersonalDetail>
@{
ViewBag.Title = "Paging Sorting And Searching";
}
<fieldset>
<legend>Search</legend>
@using (Html.BeginForm())
{
<p>
Keyword : <input type="text" name="keyword" required
value="@ViewBag.Keyword" />
<input type="submit" value="Search" /> @Html.ActionLink("Create New",
"Create")
</p>
}
</fieldset>
<table class="table">
© SN ITFunda Services LLP – http://sn.itfunda.com 132
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks Database operations
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
<tr>
<th>
Auto Id
</th>
<th>
@Html.ActionLink("First Name", "PagingSortingAndSearching", new { sortOn
= "FirstName", orderBy = ViewBag.OrderBy, pSortOn = ViewBag.SortOn, keyword =
ViewBag.Keyword })
</th>
<th>
@Html.ActionLink("Last Name", "PagingSortingAndSearching", new { sortOn
= "LastName", orderBy = ViewBag.OrderBy, pSortOn = ViewBag.SortOn, keyword =
ViewBag.Keyword })
</th>
<th>
@Html.ActionLink("Age", "PagingSortingAndSearching", new { sortOn =
"Age", orderBy = ViewBag.OrderBy, pSortOn = ViewBag.SortOn, keyword =
ViewBag.Keyword })
</th>
<th>Active</th>
<th></th>
</tr>
</table>
<div class="pagedList">
@Html.PagedListPager(Model, page => Url.Action("PagingSortingAndSearching", new
{ page, sortOn = ViewBag.SortOn, orderBy = ViewBag.OrderBy, pSortOn =
Notice the highlighted code above. We have added keyword parameter into the @Html.ActionLink as well that is
the part of the header. Similarly, we have also added keyword parameter in the @Html.PagedListPage method as
we need to persist the keyword both in sorting and paging.
To list database records in the Grid in ASP.NET MVC, we can following below approach in which we shall use
System.Web.UI.WebControls namespace.
CONTROLLER CODE
In the above code snippet, we are instantiating the GridView control class and setting the DataSource to the list
of records from the database and calling the DataBind() method of the GridView. This GridView is the same
control as we used in the ASP.NET Web Forms to list the data.
After setting the DataSource and calling the DataBind() method, we are using StringWriter and HtmlTextWriter
into which the content of the GridView is rendered. Then the same is being set as the ViewBag.GridViewString.
@{
ViewBag.Title = "ListDataInGridView";
}
@Html.Raw(ViewBag.GridViewString)
In the view, we are simply using @Html.Raw method to write the GridView content set into the Action method. If
we do not use @Html.Raw method, the output will be the HTML encoded characters so it will instead of bringing
records into tabular format in the browser will simply writes the html table, rows and columns source code as
output on the browser.
OUTPUT
Note that all the properties of the PersonalDetail class has been converted as heading and records have been
converted into the rows of the GridView. This is the best way to quicly list all records from the DataSource into
ASP.NET MVC.
104. How to insert data into more than one database tables in ASP.NET MVC?
To insert data into more than one database tables, we can take help of View model and transactions. In this
example, we are going to insert data into PersonalDetials and Files tables that we are keep using throughout this
eBook for our database operations.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;
namespace MVCTraining5.Models
{
public class PersonaldetailsFilesViewModel
{
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOpt
ion.Identity)]
public int AutoId { get; set; }
}
}
Above View mode code is pretty simple, it has one primary key that is also marked as Database generated (auto
increment). First 5 columns are form PersonalDetail entity and last one is from Files entity.
The first InsertWithViewModel() method simply returns the PersonaldetailsFilesViewModel view model instance
to the view.
Now, right click this method and create a View corresponding to this action method.
In the above Add View dialog box, we have selected Template as Create, Model class to our View model class.
Clicking Add button creates a View.
VIEW CODE
@model MVCTraining5.Models.PersonaldetailsFilesViewModel
@{
ViewBag.Title = "Insert With View Model";
}
<div class="form-horizontal">
<h4>PersonaldetailsFilesViewModel</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.FirstName, new { htmlAttributes = new
{ @class = "form-control" } })
@Html.ValidationMessageFor(model => model.FirstName, "", new {
@class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.LastName, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.LastName, new { htmlAttributes = new
{ @class = "form-control" } })
@Html.ValidationMessageFor(model => model.LastName, "", new { @class
= "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Age, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Age, new { htmlAttributes = new {
@class = "form-control" } })
@Html.ValidationMessageFor(model => model.Age, "", new { @class =
"text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Active, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
@Html.EditorFor(model => model.Active)
@Html.ValidationMessageFor(model => model.Active, "", new {
@class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.FileName, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
<input type="file" name="FileName" class="form-control" />
@Html.ValidationMessageFor(model => model.FileName, "", new { @class
= "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
Notice the Html.BeginForm helper method where we are passing our action method, controller name, form
action method and the enctype to “multipart/form-data” so that we will be able to upload an image for the
FileName field.
We have also replaced the typical @Html.EditFor of FileName property to the input type=”file”, so that for
FileName field, file upload element appears instead of a normal TextBox in the browser.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult InsertWithViewModel(PersonaldetailsFilesViewModel model,
HttpPostedFileBase FileName)
{
if (!ModelState.IsValid)
{
return View(model);
}
}
return View();
}
Notice the 2nd InsertWithViewModel method that accepts 1st parameter as the PersonaldetailsFilesViewModel
andn 2nd parameter as HttpPostedFileBase (the parameter name for this must match with the name of the html
file upload element).
First, we are checking for the ModelState. If not valid we are returning to the View again with the model (In this
case, we do not have validation in the View model attributes so this doesn’t make much sense).
In this case, we have to insert one record each into PersonalDetials and Files database table and if any error
occurs while inserting record into anyone of these tables, all changes made if any must be rolled. Let’s take an
example – if there is no error while inserting record into PersonalDetail table and an error occurs while inserting
record into Files table, even the PersonalDetail table record should be rolled back. To achieve this functionality,
we will use transaction.
We are beginning the transaction by calling db.Database.BeginTransaction() method and under this scope, we are
using Try block and trying to insert a record into PersonalDetail, uploading the user selected file on the server and
inserting a record into Files table. If all three steps goes well, we are calling transaction.Commit() method and
writing success message into ViewBag. If any error occurs, the program moves into catch block in which we are
calling the transaction.Rollback() method that undo any activity done on the database and then writing the error
message in the ViewBag.
Ajax
In order to work with Ajax helper methods in ASP.NET MVC, we must have Microsoft jQuery Unobtrusive Ajax
plug-in installed. To install it open Mange NuGet Packages … and install it.
To know more about Ajax and how it works, read our jQuery Tips & Tricks ebook and watch the videos.
After installing Microsoft jQuery Unobtrusive Ajax, scaffold Create view as we do normally for the model. In the
Create view, we need to make few changes and below are the code highlighted that needs to be added/modified.
CONTROLLER CODE
// GET: /AjaxStuff/Create
public ActionResult Create()
{
return View();
}
// POST: /AjaxStuff/Create
[HttpPost]
public ActionResult Create(PersonalDetail personalDetail)
{
if (!Request.IsAjaxRequest())
{
Response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
The second method executes when Create button is clicked on the form. We are doing following in this Create
method.
Checking whether the request to this method is Ajax or normal. We do not want normal request to
this method so if the current request is not Ajax request we are throwing error.
In the try block
o We are checking for the ModelState.IsValid, if it is then saving the record into the database
by using normal approach that we have already seen.
o And returns the success message.
o If ModelState is not valid then looping through each error and adding into the StringBuilder
and then returning it.
If any error occurs, in the catch block also we are returning error.
Note that setting the StatusCode of the Response is important to raise the OnFailure event of Ajax (we will see it
later).
VIEW CODE
@model MVCTraining5.Models.PersonalDetail
@{
ViewBag.Title = "Create";
};
<h2>Create</h2>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
@using (Ajax.BeginForm(options))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Personal Detail - Ajax</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.FirstName, new { htmlAttributes = new
{ @class = "form-control" } })
@Html.ValidationMessageFor(model => model.FirstName, "", new {
@class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.LastName, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.LastName, new { htmlAttributes = new
{ @class = "form-control" } })
@Html.ValidationMessageFor(model => model.LastName, "", new { @class
= "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Age, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Age, new { htmlAttributes = new {
@class = "form-control" } })
@Html.ValidationMessageFor(model => model.Age, "", new { @class =
"text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Active, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
@Html.EditorFor(model => model.Active)
@Html.ValidationMessageFor(model => model.Active, "", new {
@class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
<label id="labelAjaxStatus" class="alert-warning"></label>
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
<script type="text/javascript">
var isError = false;
function OnBeginMethod() {
$("#labelAjaxStatus").text("Loading ....");
}
function OnFailtureMethod(error) {
$("#labelAjaxStatus").text("Sorry, an error occured." + error.responseText);
isError = true;
}
function OnSuccessMethod(data) {
$("#labelAjaxStatus").text("Processed the data Successfully!");
$("#FirstName").val('');
$("#LastName").val('');
$("#Age").val('');
}
function OnCompleteMethod(data, status) {
if (!isError) {
$("#labelAjaxStatus").text("Request completed. Here is the status: " +
status);
}
}
</script>
@Scripts.Render("~/bundles/jqueryval")
}
Notice the above view, we have first created the instance of the AjaxOptions and set following properties
i. Confirm - the message to ask from the user before actually submitting the form
ii. OnBegin – function to call when OnBegin event executes (starts sending Ajax request)
iii. OnFailure – function to call when any error occurs on the server side while processing the request
iv. OnSuccess – function to call when request was processed successfully by server
v. OnComplete – function to call when the ajax operation is completed whether after failure or success
The next highlighted line is the reference of the jquery.unobtrusive-ajax.min.js file that is important In order to
work with @Ajax helper method otherwise @Ajax helper method works as if it is @Html helper methods.
Now add a <label> element nearby Create button so that we will be displaying the status of the ajax request.
The last part of the highlighted code is the <script> block where isError variable is declared and used as a flag to
write messages in the OnCompleteMethod.
In
OnBeginMethod – we are writing “Loading …” text to the label just beside Create button.
OnFailureMethod – we are writing error message returned from the server and also setting the isError to true
OnSuccessMethod – we are writing success message and resetting the value of textboxes
OnCompleteMethod – we are checking isError and if it is false (no error occurred, otherwise it will override the
error message written in the OnFailureMethod), writing the complete message and the status returned from the
server.
107. How to search records from the database using Ajax in ASP.NET MVC?
To search records from the database using Ajax, we can use below approach.
CONTROLLER CODE
The first controller action method simply returns the View displayed below. The 2nd method first make the thread
sleep for 2000 milliseconds (2 seconds) – just to get a real time application client server request feeling. In real
time scenario, you must remove this line of code (System.Threading.Thread.Sleep(2000);). This line of
code is just to delay the processing so that “Loading …” message displays so that we know that this functionality
can also be implemented.
After that we search records from the database based on the keyword passed to this method. Remember that
this method return tye is PartialViewResult so it returns PartialView named “SearchPeople” whose code is
displayed below.
@model IEnumerable<MVCTraining5.Models.PersonalDetail>
In the above view, search result from the Action method is taken as model and we iterate through each item in
the model and write a row with columns from the model.
VIEW CODE
@model string
@{
ViewBag.Title = "Index";
AjaxOptions options = new AjaxOptions
{
UpdateTargetId = "searchResult",
Confirm = "Are you sure to start search?",
InsertionMode = InsertionMode.Replace,
LoadingElementId = "divLoading"
};
}
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<h2>Index</h2>
<table style="width:100%;">
<thead>
<tr>
<th>AutoId</th>
<th>First Name</th>
<th>Last Name</th>
<th>Age</th>
<th>Active</th>
</tr>
</thead>
<tbody id="searchResult">
@Html.Action("SearchPeople", new { keyword = "" })
</tbody>
</table>
In the above view, we are creating AjaxOptions object first and set its properties.
Writes the header of the records to be shown. In the <tbody> the SearchPeople action method is called that
returns PartialView SearchPeople.
Now when the page loads for the first time, the whole page looks like below where there is no role of Ajax.
The heading comes from the View and records comes from the SearchPeople partial view.
The next set of codes are @Ajax.BeginForm that sends the request to “SearchPeople” action method (the same
that was requested in the <tbody> element and AjaxOptions is passed that was created at the top.
Inside the form, we have a divLoading element that simply has a “Loading …” text that is hidden initially and it will
be shown only when Ajax request starts and hides again when the Ajax request is complete. Then we have a
textbox “keyword” and a Search button of Submit type.
When Search button is clicked, a ajax request goes to the SearchPeople action method that returns PartialView
(SearchPeople with popupdated data from the search result) that is replaced with the content of “searchResult”
<tbody> element.
108. How to list records from database using JSON in ASP.NET MVC?
To know more about JSON, read our jQuery Tips & Tricks ebook.
In short, JSON is a light weight data format used to communicate from-to server with JavaScript, read more here.
In order to list records from database using JSON in ASP.NET MVC, we can use below approach. This is very useful
as we only get the actual data from database not the data along with formatting from the server (as in above
point). Formatting of the data and displaying it to the user will be the responsibility of the JavaScript/jQuery. This
is considered faster and better than getting formatted data from the server.
CONTROLLER CODE
In the second Action method, we are filtering the data based on keyword from the database and converting the
data into JSON format using Json method and returning to the view. Notice that the return type of this action
method JsonResult.
VIEW CODE
@{
ViewBag.Title = "IndexJson";
AjaxOptions options = new AjaxOptions
{
Confirm = "Are you sure to start search?",
LoadingElementId = "divLoading",
OnSuccess = "processDataMethod",
Url = Url.Action("SearchPeopleJson")
};
}
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<script type="text/javascript">
function processDataMethod(data) {
var output = $("#searchResult");
output.empty();
for (var i = 0; i < data.length ; i++) {
var person = data[i];
output.append("<tr><td>" + person.AutoId + "</td><td>" +
person.FirstName + "</td><td>" + person.LastName + "</td><td>" + person.Age +
"</td><td>" + person.Active + "</td></tr>");
}
}
</script>
<h2>IndexJson</h2>
<table style="width:100%;">
<thead>
<tr>
<th>AutoId</th>
<th>First Name</th>
<th>Last Name</th>
<th>Age</th>
<th>Active</th>
</tr>
</thead>
<tbody id="searchResult">
</tbody>
</table>
@using (Ajax.BeginForm(options))
{
<div id="divLoading" style="color:red;background-color:yellow;font-
size:larger;display:none;">Loading ....</div>
<div>
@Html.TextBox("keyword")
<button type="submit" id="btnSearch">Search</button>
</div>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script>
$("#btnSearch").trigger("click");
</script>
}
In the above view, first we have created the object of AjaxOptions and set its properties
i. Confirm – used to ask a confirmation message from user before sending Ajax request
ii. LoadingElementId – element to display while the Ajax processing is going on
iii. OnSuccess – function to call when Ajax request is successful
iv. Url – URL where to send the Ajax request
Then as usual, we have referenced the jquery.unobtrusive-ajax.min.js file that is needed in order to work with
@Ajax helper methods.
When the Ajax request is successful, we are calling processDataMethod (see above) function. In this function, we
are getting the searchResult element into output variable and making it empty so that new data can be
populated.
We are looping through the Json data being returned from the server and appending to the output variable (that
is nothing the searchResult element). Notice that while appending, we are also using html <tr>, <td> element so
that it would be formatted as per the table structure. In the previous example, responsibility of formatting the
data being returned from the server was on PartialView.
In the following code, a table structure has been formed with the header and <tbody> as searchResult.
Next, we are creating a @Ajax form with AjaxOptions defined above. This form has a div with Loading … message
that shows while the Ajax process is going on.
In the last Script block, we are triggering the “click” event of the button so that as soon as the page loads, the
default data displays on the page.
On click of the Search button after entering any character in the TextBox, the Ajax request is send to
SearchPeopleJson action method defined above that returns the filtered Json data accordingly. The returned data
is converted into <tr>, <td> format by processDataMethod function and set into “searchResult” element.
Asynchronous
To create asynchronous controller, follow almost same steps as we following creating a controller for a Model.
Clicking Add button, opens up another dialog box. Select appropriate Model class.
Select “User async controller actions” checkbox (it is important as this is what creates the Asynchronous
controller, otherwise it creates normal controller.). Now give the Controller name as you wish. No need to suffix
with “Async” word. We have done it just to differentiate with other controller of the same Model in this project.
Now, if you try to differentiate between the normal controller and asynchronous controller action methods,
following things differs
i. Return type is prefixed with async keyword that notifies that this action method returns data
asynchronously.
ii. The return type is Task<ActionResult> that represent an asynchronous operation that can
return a value.
iii. Also notice that any database operation using Entity Framework is prefixed with await
keyword that waits for the data to be retrieved from the database asynchronously.
The views are also similar to the normal controller scaffolding templates.
Bundles
Bundles are a great feature in ASP.NET MVC Framework that provides us option to organize and optimize the
JavaScript and CSS files that is used in Layout and Views pages.
Script and Style bundles are defined in ~/App_Start/BundleConfig.cs file and can be used in Layout and View
pages.
JavaScript bundles can be created only in ~/App_Start/BundleConfig.cs page. To create a JavaScript bundle we
use ScriptBundle class by passing virtual path as parameter in the constructor.
Once the instance has been created, we include the files to be added in this bundle. The files to include can be
In the above code snippet, instead of instantiating and then including the file path, we have done both
work in a single statement. You can follow the same approach as followed in the first point above.
Above bundle will get all file starting with “jquery-“ and any version in between and ends with
“.js”.
To add the bundles created, we can add them into the BundleCollection object in the
~/App_Start/BundleConfig.cs page like below
OR
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
"~/Scripts/modernizr-*"));
To use the script bundler defined above, we can use @Script handler method Render
@Scripts.Render("~/bundles/modernizr")
Where the string passed into the Render method is the virtual path specified exactly in the
~/App_Start/BundleConfig.cs file.
Calling above @Script.Render will render all files from the ~/Scripts folder starts with “modernizr-“ word as while
creating and adding the bundle into the BundleCollection, “~/bundle/modernizr” was used for
“~/Scripts/modernizr-*” files.
The output in the browser source code will be something like below as it could only found one .js file that starts
with “modernizr- “ word. If more than one file starts with “modernizr-“, more than one <script> tag will get
generated.
<script src="/Scripts/modernizr-2.6.2.js"></script>
112. How to create and use a CSS style bundle in ASP.NET MVC?
StyleBundle resembles ScriptBundle. The way we add virtual path and file names / patterns into the
ScriptBunlder, similary we do it in the StyleBundle.
Refer to above points of creating and using ScriptBundle for more details information.
OR
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css"));
@Styles.Render("~/Content/css")
As “~/Content/css” virtual path is including two files while adding into the ~/App_Start/BundleConfig.cs page.
113. How to render Scripts / Styles bundles in the custom format in ASP.NET
MVC?
Sometimes, we may need to render the <script> files defined in the Script bundle in custom format like keeping
async attribute in the script so that the script file loads asynchronously. To do this, we can use RenderFormat
method of the @Script handler method.
VIEW CODE
Similar to @Scripts helper, @Styles helper also has RenderFormat method that can be used to render the <link>
element in custom format.
In general optimization means removing any unnecessary spaces, code alignments, comments etc. (to make the
file size less) from files and combining more than one similar type of files content into one big file to decrease the
number of requests to get the file from the server .
Optimization can be done manually or with the help of online and offline utilities. However, in ASP.NET MVC,
there are few commands and settings through which optimization can be done automatically. We will learn them
in following points.
There are many ways through which script and css files added via ScriptBundle and StyleBundle can be optimized.
The first and better way of optimizing JavaScript and CSS files are to change the compilation settings in root
web.config file.
~/APP_START/BUNDLECONFIG.CS
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css"));
VIEW PAGE
@Styles.Render("~/Content/css")
But when the compilation debug mode is set to false in the root web.config file
~/WEB.CONFIG FILE
~/APP_START/BUNDLECONFIG.CS
BundleTable.EnableOptimizations = true;
The difference between the output of debug true and false in web.config file setting is following
I. Because, the comments, spaces, code alignments have been removed so the file size will become
very less
II. Now, instead of two <link> tag, only one <link> tag is rendered in the browser so only one request
goes to the server and both combined files are loaded in the browser
III. As a result, the speed of downloading the same content from both files and now with only one
combined file will be much better and it will overall increase the performance of the web page.
An ASP.NET Web API Controller can also be created either in the normal ASP.NET MVC project by following steps
Right click the Controllers folder and select Add > Controller…
In the above dialog box, select “Web API 2 Controller with actions, using Entity Framework”.
Now select the Model class, Data context and Controller name. If we want to create asynchronous controller,
then we need to check the “User async controller actions” checkbox.
Clicking Add button adds a controller in the Controllers folder. Notice that this controller is inherited with
ApiController class.
CONTROLLER CODE
// GET: api/PersonalDetailsAPI
© SN ITFunda Services LLP – http://sn.itfunda.com 165
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks ASP.NET Web API
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
// GET: api/PersonalDetailsAPI/5
[ResponseType(typeof(PersonalDetail))]
public IHttpActionResult GetPersonalDetail(int id)
{
PersonalDetail personalDetail = db.PersonalDetails.Find(id);
if (personalDetail == null)
{
return NotFound();
}
return Ok(personalDetail);
}
Apart from this, we also get a WebApiConfig.cs file in the ~/App_Start folder where a default route for the api
controller url is registered. Now, any url starting with “api/” will be routed through this route.
~/APP_START/WEBAPICONFIG.CS
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Now, in order to register/configure this route, we need to add following highlighted line of code inside the
Application_Start event of the Global.asax.cs file.
GLOBAL.ASAX.CS
System.Web.Http.GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Once everything is configured, run the project and try to browse the url something like
http://localhost:54003/api/PersonalDetailsAPI/
and you will notice that, the browse is asking to download the .json file returned by the Index method of the
PersonalDetailsAPI controller.
This shows that our API is working fine and ready to use.
117. How to insert a record into database by consuming ASP.NET Web API from
ASP.NET MVC View?
To insert a record into the database by consuming ASP.NET Web API from ASP.NET MVC view, we can follow
below approach.
Dependency: In order to do this, the Web API must be in the same project where the data is being inserted.
VIEW CODE
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<div>
<label>First Name</label>
@Html.TextBox("FirstName")
</div>
<div>
<label>Last Name</label>
@Html.TextBox("LastName")
</div>
<div>
<label>Age</label>
@Html.TextBox("Age")
</div>
<div>
<label>Active</label>
@Html.DropDownList("Active", new List<SelectListItem>
{
new SelectListItem {Text = "Yes", Value = "true", Selected = true},
new SelectListItem {Text = "No", Value = "false"},
}, "Select ...")
</div>
<div>
<button id="btnAdd">Add</button>
@Html.ActionLink("Back to List", "ListRecords")
</div>
<script type="text/javascript">
$("#btnAdd").click(function () {
var PersonalDetails = {
"FirstName": $("#FirstName").val(),
"LastName": $("#LastName").val(),
"Age": $("#Age").val(),
"Active": $("#Active").val()
};
$.ajax({
type: "POST",
url: 'http://localhost:28206/api/PersonalDetails/PostPersonalDetails',
data: JSON.stringify(PersonalDetails),
contentType: "application/json;charset=utf-8",
success: function (data, status, xhr) {
alert("The result is : " + status + ": " + data);
},
error: function (xhr) {
alert(xhr.responseText);
}
});
});
</script>
In the above code, we have three TextBoxes for FirstName, LastName, Age field of the database table and then a
dropdown for the Active status.
Notice the JavaScript code block now. When the Add button is clicked we are forming a JavaScript object and
setting respective property of the Model with the value of the TextBox and the DropDown. Next we are calling
jQuery Ajax method to post the data on the web api url.
I. type : “POST”
II. url : the url of the Web API that is responsible to accept the Model object and insert the data
III. data: the JavaScript object is being stringify so that it can be posted to the server
IV. contentType : setting the type of content being sent from this page
V. success: function that is giving the alert once the data is processed on the server successfully
VI. error: function that shows the response error text in case error occurred on the server
[HttpPost]
public IHttpActionResult PostPersonalDetails([FromBody] PersonalDetails
personaldetails)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.PersonalDetails.Add(personaldetails);
db.SaveChanges();
return Ok(personaldetails);
}
In the controller action method, notice that the return type of IHttpActionResult. The JavaScript object that is
sent via API gets converted into the PersonalDetails object as the name of the JavaScript object properties and
the Model object properties are same.
In this method, we are checking for ModelState validity, if not valid BadRequest is being returned otherwise data
is being added into the database and Ok(with the PersonalDetails) object is being returned that show success
message to the browser.
118. How to list records from database by consuming ASP.NET Web API from
ASP.NET MVC View?
119. How to delete record from database by consuming ASP.NET Web API from
ASP.NET MVC View?
To demonstrate listing records and deleting records from the database by consuming ASP.NET Web API from
ASP.NET MVC View, we have created a simple controller action method that returns our following view.
return View();
}
Above action method simply returns following view. No record from database is returned to below view.
VIEW CODE
@model IEnumerable<MVC_Web_API.Models.PersonalDetails>
@{
ViewBag.Title = "ListRecords";
}
© SN ITFunda Services LLP – http://sn.itfunda.com 170
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks ASP.NET Web API
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
<h2>ListRecords</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<label>Keyword</label>
@Html.TextBox("keyword")
<button id="btnSearch">Search</button>
<table class="table">
<tr>
<th>Auto ID</th>
<th>
@Html.DisplayNameFor(model => model.FirstName)
</th>
<th>
@Html.DisplayNameFor(model => model.LastName)
</th>
<th>
@Html.DisplayNameFor(model => model.Age)
</th>
<th>
@Html.DisplayNameFor(model => model.Active)
</th>
<th>Delete </th>
</tr>
<tbody id="tableRows"></tbody>
</table>
<script type="text/javascript">
$(function () {
LoadAll();
});
function LoadAll()
{
$.ajax(
{
//url: '/api/PersonalDetails/GetPersonalDetails',
url: 'http://localhost:28206/api/PersonalDetails/',
type: 'GET',
dataType: 'json',
success: function (data, status, xhr) {
processDataMethod(data);
},
error: function (xhr, status, error) {
alert(error);
}
});
}
$("#btnSearch").click(function () {
if ($("#keyword").val().length == 0)
{
alert("Please write keyword to search !");
return;
}
function ShowDetails(id) {
var myurl = 'http://localhost:28206/api/PersonalDetails/GetPersonalDetails/'
+ id
$.ajax(
{
url: myurl,
type: 'GET',
dataType: 'json',
success: function (person, status, xhr) {
var output = $("#tableRows");
output.empty();
output.append("<tr><td><a href='javascript:ShowDetails(" +
person.AutoId + ")' title='Show details'>" + person.AutoId + "</a></td><td>" +
person.FirstName + "</td><td>" + person.LastName + "</td><td>" + person.Age +
"</td><td>" + person.Active + "</td><td><a style='color:red;'
href='javascript:DeleteRecord(" + person.AutoId + ")' title='Delete
details'>Delete</a></td></tr>");
},
error: function (xhr, status, error) {
alert(error);
}
});
}
function DeleteRecord(id)
{
var myurl =
'http://localhost:28206/api/PersonalDetails/DeletePersonalDetails/' + id
$.ajax(
{
url: myurl,
type: 'DELETE',
dataType: 'json',
success: function (person, status, xhr) {
alert("Success result is : " + status)
LoadAll();
},
error: function (xhr, status, error) {
alert(error);
}
});
}
function processDataMethod(data) {
var output = $("#tableRows");
output.empty();
The HTML part of the view just creates a table with heading coming from the Model. After that <tbody> element
is the placeholder where the records returned from the API will be populated.
Listing records
In LoadAll function, we are calling /api/PersonalDetails url that will call the GET method of the PersonalDetails
controller. As in this controller only one GET method is there whose name is GetPersonalDetails() so this method
will be automatically called.
// GET api/PersonalDetails
public IQueryable<PersonalDetails> GetPersonalDetails()
{
var data = db.PersonalDetails;
return data;
}
The above action method returns all records from the PersonalDetails table of the database.
Notice that in the success parameter of the LoadAll() function, we are calling processDataMethod function that
find out the <tbody> element, make it empty and then loop through each data item returned from the ASP.NET
Web API and append it to the <tbody> element.
Deleting record
Notice the above UI where the last column is Delete link. Clicking on Delete link calls DeleteRecord() function with
AutoId parameter. In the DeleteRecord method, we call DeletePersonalDetails action method
// DELETE api/PersonalDetails/5
[HttpDelete]
public IHttpActionResult DeletePersonalDetails(int id)
{
PersonalDetails personaldetails = db.PersonalDetails.Find(id);
if (personaldetails == null)
{
return NotFound();
}
db.PersonalDetails.Remove(personaldetails);
db.SaveChanges();
return Ok(personaldetails);
}
In this action method, first we find the record to delete based on Id and then delete the record from the
database. This method also returns Ok with the record deleted that shows Success message and relist all the
records by calling LoadAll() javascript function.
Similarly, we also have first column as hyperlink, clicking on that calls ShowDetails() javascript function that
internally calls GetPersonalDetails action method of the controller
// GET api/PersonalDetails/5
// [ResponseType(typeof(PersonalDetails))]
public IHttpActionResult GetPersonalDetails(int id)
{
PersonalDetails personaldetails = db.PersonalDetails.Find(id);
if (personaldetails == null)
{
return NotFound();
}
return Ok(personaldetails);
}
This method finds the record to display based on id and returns with Ok, the same is listed in the <tbody>
element as a single row.
120. How to update record to database by consuming ASP.NET Web API from
ASP.NET MVC View?
To demonstrate update record into the database, we have updated the list view of above point to add a Edit link
just beside the Auto ID value as demonstrated below.
Clicking Edit link send the user to Edit action method of the controller with autoid querystring value. The action
method looks like below.
© SN ITFunda Services LLP – http://sn.itfunda.com 176
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks ASP.NET Web API
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
http://localhost:28206/home/edit?autoid=2
VIEW CODE
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
<div>
<label>First Name</label>
@Html.TextBox("FirstName")
</div>
<div>
<label>Last Name</label>
@Html.TextBox("LastName")
</div>
<div>
<label>Age</label>
@Html.TextBox("Age")
</div>
<div>
<label>Active</label>
@Html.DropDownList("Active", new List<SelectListItem>
{
new SelectListItem {Text = "Yes", Value = "true", Selected = true},
new SelectListItem {Text = "No", Value = "false"},
}, "Select ...")
</div>
<div>
<button id="btnAdd">Add</button>
@Html.ActionLink("Back to List", "ListRecords")
</div>
<script type="text/javascript">
$("#btnAdd").click(function () {
var PersonalDetails = {
"FirstName": $("#FirstName").val(),
"LastName": $("#LastName").val(),
"Age": $("#Age").val(),
"Active": $("#Active").val(),
"AutoId": @Request.QueryString["autoid"]
};
$.ajax({
type: "PUT",
url:
'http://localhost:28206/api/PersonalDetails/PutPersonalDetails/@Request.QueryString[
"autoid"]',
data: JSON.stringify(PersonalDetails),
contentType: "application/json;charset=utf-8",
success: function (data, status, xhr) {
alert("The result is : " + status + ": " + data);
},
error: function (xhr) {
alert(xhr.responseText);
}
});
});
function ShowDetails(id) {
var myurl = 'http://localhost:28206/api/PersonalDetails/GetPersonalDetails/'
+ id
$.ajax(
{
url: myurl,
type: 'GET',
dataType: 'json',
success: function (person, status, xhr) {
$("#FirstName").val(person.FirstName);
$("#LastName").val(person.LastName);
$("#Age").val(person.Age);
document.getElementById("Active").value = person.Active;
$("#btnAdd").text("Update");
},
error: function (xhr, status, error) {
alert(error);
}
});
}
ShowDetails(@Request.QueryString["autoid"]);
</script>
The above view is almost same as the Create view, we have made minor changes to fit for Update.
Now, notice the last part of the Script block. When the page loads, the ShowDetails() function is called with
autoid qurystring value that is nothing but the primarly key value of the record selected for edit by the user.
ShowDetails() function calls GetPersonalDetails action method (explained earlier) of the Web API controller that
gets the details of that record and set into the TextBoxes and DropDown respectively.
Now, when the Update button is clicked PutPersonalDetails action method of the Web API controller is called
(remaining code for the button click has been already explained while explaining how to create a new rocord into
database by consuming ASP.NET Web API above), that looks like below.
// PUT api/PersonalDetails/5
public IHttpActionResult PutPersonalDetails(int id, PersonalDetails
personaldetails)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != personaldetails.AutoId)
{
return BadRequest("Sorry, seems something wrong. Couldn't determine
record to update.");
}
db.Entry(personaldetails).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!PersonalDetailsExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return Ok(personaldetails);
}
Above action method checks for the valid state of the Model and then checks set the record state to “Modified”
after validation and then returns Ok that shows the success messge to the user.
To consume external Web API in ASP.NET MVC, we need to take help of HttpClient object exists into
System.Net.Http namespace. Here we are assuming that the Web API is returning json data that it generally does.
CONTROLLER CODE
Notice that the return type of this action method is Task<ActionResult> (it means that this action method can get
executed asynchronously) as external Web API response is dependent on the network traffic and it is RESTFUL.
In the above method, we are instantiating the HttpClient object and setting its BaseAddress. After that we are
clearing any default request headers so that we can set our own header of “application/json”.
Next, we are getting the response from the API by calling client.GetAsync() method. If the status code is success
we are reading the content string returned from the API (ie the json string). Now we are converting the json
string into DataTable using JsonConvert.DeserializeObject method (In case the project doesn’t contains
Newtonsoft.json namespace, we need to install the assembly through Manage NuGet Packages).
Once the json data is converted into DataTable, we are setting it to the GridView and setting the GridView
rendered string into ViewBag that gets written on the View.
@{
ViewBag.Title = "ListDataInGridView";
}
@Html.Raw(ViewBag.GridViewString)
In the view, we are simply using @Html.Raw method to write the GridView content set into the Action method. If
we do not use @Html.Raw method, the output will be the HTML encoded characters so it will instead of bringing
records into tabular format in the browser will simply writes the html table, rows and columns source code as
output on the browser.
OUTPUT
Exporting Data
To export data from database to MS Excel, we can use GridView control of the System.Web.UI.WebControls
namespace that is part of ASP.NET Web Form.
// GET: ExportData
public ActionResult ExportToExcel()
{
// Step 1 - get the data from database
var data = db.PersonalDetails.ToList();
Response.Buffer = true;
// set the header
Response.AddHeader("content-disposition", "attachment;
filename=itfunda.xls");
Response.ContentType = "application/ms-excel";
Response.Charset = "";
// create HtmlTextWriter object with StringWriter
using (StringWriter sw = new StringWriter())
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
// render the GridView to the HtmlTextWriter
gridview.RenderControl(htw);
// Output the GridView content saved into StringWriter
Response.Output.Write(sw.ToString());
Response.Flush();
Response.End();
}
}
return View();
}
In the above action method, most of the codes are documented and self understood however in short we are
doing following
first we are getting the data from the database and setting to the source of the GridView
clearing all the content of the response
setting the response header and ContentType
rendering the GridView conent using HtmlTextWriter and StringWriter
Calling the ExportToExcel action method will ask user to Open or Save the itfunda.xls file like below.
How to limit the number of columns appearing in the exported excel file?
To limit the number of columns appearing in the exported MS Excel file, set the data source of the GridView that
has selected columns like below
{
p.Active,
p.FirstName,
p.LastName
}
);
Now, the exported excel file will have only Active, FirstName and LastName columns data only.
OUTPUT
Exporting the data to MS Word is similar to exporting data into MS Excel, only the ContentType and the file name
extension changes
// GET: ExportData
public ActionResult ExportToWord()
{
// get the data from database
var data = db.PersonalDetails.ToList();
Notice the above code snippet and focus on the highlighted words. Note that Response.ContentType is
“application/ms-word” and the file name extension is “.doc”.
Calling the above action method asks user to save or download the file like below.
OUTPUT
Response.ClearContent();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment;
filename=itfunda.xml");
Response.ContentType = "text/xml";
© SN ITFunda Services LLP – http://sn.itfunda.com 187
For .NET related articles, tutorials, interview questions, discussion & more, visit http://www.DotNetFunda.com.
To avail other IT services like training, videos tutorials and job support, visit http://www.ItFunda.com.
ASP.NET MVC Tips & Tricks Exporting Data
Licensed to: Licensed to TollPlus trainees (Dec 2014 batch only)
In the above action method, we are getting the data from the database and setting almost same properties of the
Response object that we have set into previous points.
Calling above method from browser like http://localhost:63087/ExportData/ExportToXML gives below output in
which browser asks to Open or Save the xml file.
OUTPUT
Unit testing
To create a new ASP.NET MVC Test project, right click the solution and select Add > New Project ….
Select Visual C# > Test > Unit Test Project as displayed below
Add the reference of the Web Application for which we need to write the Unit test by right clicking the Unit test
project and clicking on References > Add Reference ….
After following above steps our basic infrastructure of the Test project is ready and it looks something like below.
By default, the Test project creates a UnitTest.cs file that looks like below
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace WebApplicationTest
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
}
}
}
To mark a class file as a Test class, we need to decorate the class with [TestClass] attribute. To mark a method as
Test method, we need to decorate the method as [TestMethod].
To add a new Test class, right click the Unit Test project and select Add > Unit Test …
This creates a new Unit test class. This can be renamed later on by right clicking and selecting “Rename”.
To create a new Test case method, create a new method in the Unit test class and decorate with [TestMethod].
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace WebApplicationTest
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
[TestMethod]
public void CreateViewTest()
{
}
}
}
See the highlighted code that has a method with [TestMethod] attribute.
First reference necessary .dlls that help us to use classes to test the View. Our ASP.NET MVC Project is already
referenced so we can use the Controller namespace so that we will be able to use its controller for the test.
Now add the reference of the System.Web.Mvc.dll that help us to use VIewResult class.
[TestMethod]
public void TestMethod1()
{
//Arrange
var controller = new PersonalDetailsController();
// Act
var result = controller.Create() as ViewResult;
// Assert
Assert.AreEqual("Create", result.ViewName);
}
Notice the above Arrage / Act and the Assert. Unit test is written in three steps
I. Arrange – Arrange the necessary infra to act. Ie instantiate necessary controller so that its method
can be called for the testing.
II. Act – call the method that needs a test.
III. Assert – Now check whether the expected value is equal to the value returned from the method by
calling Assert class methods.
To view the test method created / updated result. We need to open the Test Explorer. To being the Test Explorer
in front, following below steps
Go to TEST > Windows > Test Explorer that brings below window (Ignore what is showing in the Test Explorer for
now).
To run the Test, Select TEST > Run > All Tests
OR
we can also right click the name of the Test method and select Run Selected Tests
OR
We can also right click in the Test method and select Run Tests
That start running the Test and the Test result is shown in the Test Explorer window.
The above test case will only pass if the Create action method of the PersonalDetailsController looks like below
// GET: PersonalDetails/Create
public ActionResult Create()
{
//return View(); // will fail the test case
return View("Create");
}
If we just return View() without the name of the View as parameter, the above Test method fails. However, the
action method is correct in both cases and it gives the same result whether we pass View name as parameter or
just return the View.
To debug the Unit test method, right click the method select Debug Tests.
The debugging works as it works in the normal C# project. We can use F10, F11 or F5 keys for the same
functionality as we do for normal C# project / ASP.NET Project debugging.
130. How to test a controller method that is accessing data from database?
In order to test a Unit test method that access the action method of the controller that uses database, we need
to make some changes in the app.config and other files into the Test project as well as Web application we are
going to test.
We need few more .dlls in the reference, below are highlighted .dlls into the Unit test project.
Make following necessary changes to the App.config file of the Unit test project.
APP.CONFIG FILE
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=SNITFunda;Initial
Catalog=TrainingDatabase;Integrated Security=True;Integrated
Security=SSPI;MultipleActiveResultSets=true" providerName="System.Data.SqlClient"/>
</connectionStrings>
<entityFramework>
<defaultConnectionFactory
type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="System.Data.SqlClient"
type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"
/>
</providers>
</entityFramework>
</configuration>
Notice the changes in the above file that is highlighted. Change the database connection string, it should be same
as the Web application web.config connection string.
In the Web Application project go to ~/Models/IdentityModels.cs and look for following DbConnext code block
~/MODELS/IDENTITYMODELS.CS CODE
Database.SetInitializer<WebApplication1.Models.ApplicationDbContext>(null);
}
Look at the highlighted code statement. This is mandatory to write otherwise we get following errors.
System.InvalidOperationException: The model backing the 'ApplicationDbContext' context has changed since the
database was created. Consider using Code First Migrations to update the database
(http://go.microsoft.com/fwlink/?LinkId=238269).
[TestMethod]
public void CheckFirstName()
{
// Arrange
var controller = new PersonalDetailsController();
// Act
var result = controller.Details(1) as ViewResult;
WebApplication1.Models.PersonalDetail person =
(WebApplication1.Models.PersonalDetail) result.Model;
// Assert
Assert.AreEqual("Sheo", person.FirstName);
}
Running the above unit test gives success result as the record from the PersonalDetails table having AutoId 1
having first name as “Sheo”.
If we change the first parameter value (I have changed to “Sheo0”) of Assert.AreEqual method (the expected
parameter), and run the test it gives following error.
131. How to create a method that is not a test method in the Test class?
To create a method that is not a test method, do not decorate it with [TestMethod]. It can be declared as we
declare in normal class.
This can be called from inside the TestMethod the way it is called from a normal class.
Important request: If you are facing any other problems in ASP.NET MVC that have not been covered here, do let
us know so that we can solve it and update this eBook to make it more useful.
Visit
http://www.ITFunda.com
Phone: +91-40-4222-2291
Mobile: +91-768-088-9888
Email: [email protected]
Website: http://www.itfunda.com