In this article i will show you how you can integrate html textbox editor in you mvc application and how you can retrieve the value entered in the html textbox editor.
So for this first you needed to create a new mvc3 application. and add new controller and create view for the index method. Now create the model. Your model Code.
using System;
using System.Collections.Generic; using System.Linq; using System.Web; namespace Demo_Application.Models { public class EditorTextModel { public string TextData { get; set; } } } Now in you view add the below code.
@model Demo_Application.Models.EditorTextModel
@{ ViewBag.Title = "How To Integrate HTML Textbox Editor and How You Can Retrive Textbox Value In MVC3"; } <script src="../../Scripts/Editor/nicEdit.js" type="text/javascript"></script> <script type="text/javascript"> bkLib.onDomLoaded(function () { new nicEditor({ iconsPath: `../../Scripts/Editor/nicEditorIcons.gif`, maxHeight: 100 }).panelInstance(`txtdetail`); }); function Validateform() { if ($("#txttitle").attr(`value`) == "") { alert("Please enter title"); return false; } return true; } </script> @using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" })) { <div style="color: Red; font-weight: bold;">@ViewBag.Message</div> <table width="100%" cellpadding="5" cellspacing="2" border="0" style="background-color: White;"> <tr> <td class="headertitle-contect" valign="middle"> How To Integrate HTML Textbox Editor and <br />How You Can Retrive Textbox Value In MVC3 </td> </tr> <tr> <td align="left"> <table width="99%" cellpadding="5" cellspacing="0" border="0"> <tr> <td align="left"> Detail </td> </tr> <tr> <td align="left"> @Html.TextAreaFor(m => m.TextData, new { @id = "txtdetail", @rows = "20", @cols = "50" }) </td> </tr> <tr> <td align="left"> <input type="submit" name="Command" value="Submit"/> </td> </tr> </table> </td> </tr> </table> } Now create he post method for the index actionresult.
[HttpPost]
public ActionResult Index(EditorTextModel objeditortextmodel) { ViewBag.Text = objeditortextmodel.TextData; return View(); } Now run the application and enter some value as you make the post you will get the below error.
A potentially dangerous Request.Form value was detected from the client (TextData="<p>This is a <strong...").
Now i will tell how you can handle the above error. Just by making small modification in you model code.
using System;
using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Demo_Application.Models { public class EditorTextModel { [AllowHtml] public string TextData { get; set; } } } Now run the application Now add data and submit the form Now add data and make post. Here we are getting the text in our model. Now here is your final output. ___________________________________ |
Tuesday, July 30, 2013
How To Integrate HTML Textbox Editor and How You Can Retrive Textbox Value In MVC3
How to Bind Image in WebGrid using MVC3 with example
In this article i will tell you how you can a bind image in a mvc webgrid.
So for this first you needed to create a new mvc3 web application. Add controller and create view for actionresult method of the controller.
Now add a model file in you model folder and add the below code.
Now In you controller add the below code.
In above code i have created a static collection of list for data. You can user you collection of data by making connection with database.
Here are some of my articles which you must look.
Now in you view Add the below code.
Here i have binded the web grid .
Now run the application for desired output.

So for this first you needed to create a new mvc3 web application. Add controller and create view for actionresult method of the controller.
Now add a model file in you model folder and add the below code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Demo_Application.Models
{
public class CountryModel
{
public List<Coutry> CoutryModelList { get; set; }
}
public class Coutry
{
public int Id { get; set; }
public string Name { get; set; }
public string CountryFlagImage { get; set; }
public int Population { get; set; }
}
}
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Demo_Application.Models
{
public class CountryModel
{
public List<Coutry> CoutryModelList { get; set; }
}
public class Coutry
{
public int Id { get; set; }
public string Name { get; set; }
public string CountryFlagImage { get; set; }
public int Population { get; set; }
}
}
Now In you controller add the below code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Demo_Application.Models;
namespace Demo_Application.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
CountryModel objcountrymodel = new CountryModel();
objcountrymodel.CoutryModelList = GetAllCountry();
return View(objcountrymodel);
}
public List<Coutry> GetAllCountry()
{
List<Coutry> objcountry = new List<Coutry>();
objcountry.Add(new Coutry { Id = 1, Name = "India", Population = 100000, CountryFlagImage = "Content/images/1.jpg" });
objcountry.Add(new Coutry { Id = 2, Name = "Unites States", Population = 384545, CountryFlagImage = "Content/images/2.jpg" });
objcountry.Add(new Coutry { Id = 3, Name = "Iran", Population = 2354999, CountryFlagImage = "Content/images/3.jpg" });
return objcountry;
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Demo_Application.Models;
namespace Demo_Application.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
CountryModel objcountrymodel = new CountryModel();
objcountrymodel.CoutryModelList = GetAllCountry();
return View(objcountrymodel);
}
public List<Coutry> GetAllCountry()
{
List<Coutry> objcountry = new List<Coutry>();
objcountry.Add(new Coutry { Id = 1, Name = "India", Population = 100000, CountryFlagImage = "Content/images/1.jpg" });
objcountry.Add(new Coutry { Id = 2, Name = "Unites States", Population = 384545, CountryFlagImage = "Content/images/2.jpg" });
objcountry.Add(new Coutry { Id = 3, Name = "Iran", Population = 2354999, CountryFlagImage = "Content/images/3.jpg" });
return objcountry;
}
}
}
In above code i have created a static collection of list for data. You can user you collection of data by making connection with database.
Here are some of my articles which you must look.
Now in you view Add the below code.
@model Demo_Application.Models.CountryModel
@{
ViewBag.Title = "How To Bind Image In MVC3 Webgrid";
}
<!-- CSS goes in the document HEAD or added to your external stylesheet -->
<style type="text/css">
table.gridtable {
font-family: verdana,arial,sans-serif;
font-size:11px;
color:#333333;
border-width: 1px;
border-color: #666666;
border-collapse: collapse;
}
table.gridtable th {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #666666;
background-color: #dedede;
}
table.gridtable td {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #666666;
background-color: #ffffff;
}
</style>
<table width="100%" cellpadding="5" cellspacing="2" border="0" style="background-color: White;">
<tr>
<td>
@{
var grid = new WebGrid(source: Model.CoutryModelList,
rowsPerPage: 10);
}
@grid.GetHtml(
tableStyle: "gridtable",
alternatingRowStyle: "even",
columns: grid.Columns(
grid.Column("Id", "Id"),
grid.Column("Name", "Name"),
grid.Column("Population", "Population"),
grid.Column("CountryFlagImage", header: "Country Flag Image", format: @<text><img src="../../@item.CountryFlagImage" alt="@item.CountryFlagImage" width="100px" height="50px"></img></text>)
)
)
</td>
</tr>
</table>
@{
ViewBag.Title = "How To Bind Image In MVC3 Webgrid";
}
<!-- CSS goes in the document HEAD or added to your external stylesheet -->
<style type="text/css">
table.gridtable {
font-family: verdana,arial,sans-serif;
font-size:11px;
color:#333333;
border-width: 1px;
border-color: #666666;
border-collapse: collapse;
}
table.gridtable th {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #666666;
background-color: #dedede;
}
table.gridtable td {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #666666;
background-color: #ffffff;
}
</style>
<table width="100%" cellpadding="5" cellspacing="2" border="0" style="background-color: White;">
<tr>
<td>
@{
var grid = new WebGrid(source: Model.CoutryModelList,
rowsPerPage: 10);
}
@grid.GetHtml(
tableStyle: "gridtable",
alternatingRowStyle: "even",
columns: grid.Columns(
grid.Column("Id", "Id"),
grid.Column("Name", "Name"),
grid.Column("Population", "Population"),
grid.Column("CountryFlagImage", header: "Country Flag Image", format: @<text><img src="../../@item.CountryFlagImage" alt="@item.CountryFlagImage" width="100px" height="50px"></img></text>)
)
)
</td>
</tr>
</table>
Here i have binded the web grid .
Now run the application for desired output.
How to make simple login form in MVC3 with Example
In this article i will show you how you can create login page in mvc3 using c#. For creating login page i have used mvc3, c# and jquery for validation.
So for this create a new mvc3 application,in this add model file in your model folder . Now in your model file add the below code.
Now come you your controller . Add the below code in your controller.
In above i have used a collection for user id and password. You can user own collection for validating.
Now create a view for your index action and add the below code.
Now we have done. run the application.

Now click on login you will get error message.

Now add user id and password and click on login. your index post method will hit.

in your var you will get the value

In this you will get value in your variable (var) only in case of correct user id and password.

Now we will add wring user id and password.
you will get null in your var.

This will indicate wrong user id password.

So for this create a new mvc3 application,in this add model file in your model folder . Now in your model file add the below code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace mvc_login.Models
{
public class UserLoginModel
{
public string UserId { get; set; }
public string Password { get; set; }
}
}
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace mvc_login.Models
{
public class UserLoginModel
{
public string UserId { get; set; }
public string Password { get; set; }
}
}
Now come you your controller . Add the below code in your controller.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using mvc_login.Models;
namespace mvc_login.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
UserLoginModel objuserlogin = new UserLoginModel();
return View(objuserlogin);
}
[HttpPost]
public ActionResult Index(UserLoginModel objuserlogin)
{
var validate = UserLoginIds().Where(m => m.UserId == objuserlogin.UserId && m.Password == objuserlogin.Password).FirstOrDefault();
if (validate != null)
{
ViewBag.Status = "You have enterred CORRECT userid and password.";
}
else
{
ViewBag.Status = "You have enterred WRONG userid and password.";
}
return View(objuserlogin);
}
public List<UserLoginModel> UserLoginIds()
{
List<UserLoginModel> objUserLoginModel = new List<UserLoginModel>();
objUserLoginModel.Add(new UserLoginModel { UserId="user1",Password="password1"});
objUserLoginModel.Add(new UserLoginModel { UserId = "user2", Password = "password2" });
objUserLoginModel.Add(new UserLoginModel { UserId = "user3", Password = "password3" });
objUserLoginModel.Add(new UserLoginModel { UserId = "user4", Password = "password4" });
objUserLoginModel.Add(new UserLoginModel { UserId = "user5", Password = "password5" });
return objUserLoginModel;
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using mvc_login.Models;
namespace mvc_login.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
UserLoginModel objuserlogin = new UserLoginModel();
return View(objuserlogin);
}
[HttpPost]
public ActionResult Index(UserLoginModel objuserlogin)
{
var validate = UserLoginIds().Where(m => m.UserId == objuserlogin.UserId && m.Password == objuserlogin.Password).FirstOrDefault();
if (validate != null)
{
ViewBag.Status = "You have enterred CORRECT userid and password.";
}
else
{
ViewBag.Status = "You have enterred WRONG userid and password.";
}
return View(objuserlogin);
}
public List<UserLoginModel> UserLoginIds()
{
List<UserLoginModel> objUserLoginModel = new List<UserLoginModel>();
objUserLoginModel.Add(new UserLoginModel { UserId="user1",Password="password1"});
objUserLoginModel.Add(new UserLoginModel { UserId = "user2", Password = "password2" });
objUserLoginModel.Add(new UserLoginModel { UserId = "user3", Password = "password3" });
objUserLoginModel.Add(new UserLoginModel { UserId = "user4", Password = "password4" });
objUserLoginModel.Add(new UserLoginModel { UserId = "user5", Password = "password5" });
return objUserLoginModel;
}
}
}
In above i have used a collection for user id and password. You can user own collection for validating.
public List<UserLoginModel> UserLoginIds()
{
List<UserLoginModel> objUserLoginModel = new List<UserLoginModel>();
objUserLoginModel.Add(new UserLoginModel { UserId="user1",Password="password1"});
objUserLoginModel.Add(new UserLoginModel { UserId = "user2", Password = "password2" });
objUserLoginModel.Add(new UserLoginModel { UserId = "user3", Password = "password3" });
objUserLoginModel.Add(new UserLoginModel { UserId = "user4", Password = "password4" });
objUserLoginModel.Add(new UserLoginModel { UserId = "user5", Password = "password5" });
return objUserLoginModel;
}
{
List<UserLoginModel> objUserLoginModel = new List<UserLoginModel>();
objUserLoginModel.Add(new UserLoginModel { UserId="user1",Password="password1"});
objUserLoginModel.Add(new UserLoginModel { UserId = "user2", Password = "password2" });
objUserLoginModel.Add(new UserLoginModel { UserId = "user3", Password = "password3" });
objUserLoginModel.Add(new UserLoginModel { UserId = "user4", Password = "password4" });
objUserLoginModel.Add(new UserLoginModel { UserId = "user5", Password = "password5" });
return objUserLoginModel;
}
Now create a view for your index action and add the below code.
@model mvc_login.Models.UserLoginModel
@{
ViewBag.Title = "Index";
}
<script language="javascript">
function validate() {
if ($("#txtuserid").attr(`value`) == "") {
alert("Please enter user id.");
return false;
} else if ($("#txtpassword").attr(`value`) == "") {
alert("Please enter password.");
return false;
}
return true;
}
</script>
<h3>Simple MVC3 Login Form Using C#</h3>
@using (Html.BeginForm("Index", "Home"))
{
<table width="30%" cellpadding="0" cellspacing="5">
<tr>
<td colspan="2" style="color:Red;font-size:larger">@ViewBag.Status</td>
</tr>
<tr>
<td align="right">User Id :</td>
<td>@Html.TextBoxFor(m => m.UserId, new {@style="width:200px",@id="txtuserid" })</td>
</tr>
<tr>
<td align="right">Password :</td>
<td>@Html.PasswordFor(m => m.Password, new {@style="width:200px",@id="txtpassword" })</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Login" title="login" onclick="javascript:return validate();"/>
</td>
</tr>
</table>
}
@{
ViewBag.Title = "Index";
}
<script language="javascript">
function validate() {
if ($("#txtuserid").attr(`value`) == "") {
alert("Please enter user id.");
return false;
} else if ($("#txtpassword").attr(`value`) == "") {
alert("Please enter password.");
return false;
}
return true;
}
</script>
<h3>Simple MVC3 Login Form Using C#</h3>
@using (Html.BeginForm("Index", "Home"))
{
<table width="30%" cellpadding="0" cellspacing="5">
<tr>
<td colspan="2" style="color:Red;font-size:larger">@ViewBag.Status</td>
</tr>
<tr>
<td align="right">User Id :</td>
<td>@Html.TextBoxFor(m => m.UserId, new {@style="width:200px",@id="txtuserid" })</td>
</tr>
<tr>
<td align="right">Password :</td>
<td>@Html.PasswordFor(m => m.Password, new {@style="width:200px",@id="txtpassword" })</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Login" title="login" onclick="javascript:return validate();"/>
</td>
</tr>
</table>
}
Now we have done. run the application.
Now click on login you will get error message.
Now add user id and password and click on login. your index post method will hit.
in your var you will get the value
In this you will get value in your variable (var) only in case of correct user id and password.
Now we will add wring user id and password.
you will get null in your var.
This will indicate wrong user id password.
How to upload multiple files in MVC3 with Examples
Step - 1
In View :--
@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<h3>Multiple file upload with asp.net mvc3, C# and HTML5 </h3>
<input type="file" name="files" value="" multiple="multiple"/>
<input type="submit" value="Upload You Image" title="Uplad"/>
<div style="color:Red;font-size:14px">@ViewBag.Message</div>
}
Step - 2
In .CS code section please see this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MultiplefileUploadinmvc3.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(HttpPostedFileBase[] files)
{
try
{
foreach (HttpPostedFileBase file in files)
{
//Geting the file name
string filename = System.IO.Path.GetFileName(file.FileName);
//Saving the file in server folder
file.SaveAs(Server.MapPath("~/Images/" + filename));
string filepathtosave = "Images/" + filename;
//--HERE WILL BE YOUR CODE TO SAVE THE FILE DETAIL IN DATA BASE--------------
}
ViewBag.Message = "File Uploaded successfully.";
}
catch
{
ViewBag.Message = "Error while uploading the files.";
}
return View();
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MultiplefileUploadinmvc3.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(HttpPostedFileBase[] files)
{
try
{
foreach (HttpPostedFileBase file in files)
{
//Geting the file name
string filename = System.IO.Path.GetFileName(file.FileName);
//Saving the file in server folder
file.SaveAs(Server.MapPath("~/Images/" + filename));
string filepathtosave = "Images/" + filename;
//--HERE WILL BE YOUR CODE TO SAVE THE FILE DETAIL IN DATA BASE--------------
}
ViewBag.Message = "File Uploaded successfully.";
}
catch
{
ViewBag.Message = "Error while uploading the files.";
}
return View();
}
}
}
Calender Control in MVC3 with Examples
Now for this article first create a an mvc3 article. In this add the model and add the below code in it.
Now create controller and add the below code.
Now create view and add the below code.
Now add the below modified code in your controller.
In above code we have written code for post method also. Now we have done run the aplication.

Now we will check the system date.

Now click on text box to view the calender. in this user will now able to select beyond current date.

Now select the date and click on submit to get the selected date in controller.

Now in controller you will the selected date as shown below.

Now here is the final output.

The above date in mm/dd/YYYYY format....
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MvcApplication1.Models
{
public class UserDate
{
public string SelectedDateFromCander { get; set; }
}
}
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MvcApplication1.Models
{
public class UserDate
{
public string SelectedDateFromCander { get; set; }
}
}
Now create controller and add the below code.
[HttpGet]
public ActionResult Index()
{
UserDate _objmodel = new UserDate();
return View(_objmodel);
}
public ActionResult Index()
{
UserDate _objmodel = new UserDate();
return View(_objmodel);
}
Now create view and add the below code.
@model MvcApplication1.Models.UserDate
@{
ViewBag.Title = "jQuery UI Datepicker Restrict date range In MVC3 TextBoxFor Control | Code To Allow User Select Previous Date in MVC3";
}
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script>
$(function () {
$("#txtdatepicker").datepicker({ maxDate: "+0D" });
});
</script>
@using (Html.BeginForm("index", "Home"))
{
<h3>
Select Date Before Current Date</h3>
<p>
Select Date: @Html.TextBoxFor(m => m.SelectedDateFromCander, new { id = "txtdatepicker" })</p>
<input type="submit" value="Submit" />
<br />
<h3>Your Selected Date : @ViewBag.SelectedDate </h3>
}
@{
ViewBag.Title = "jQuery UI Datepicker Restrict date range In MVC3 TextBoxFor Control | Code To Allow User Select Previous Date in MVC3";
}
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script>
$(function () {
$("#txtdatepicker").datepicker({ maxDate: "+0D" });
});
</script>
@using (Html.BeginForm("index", "Home"))
{
<h3>
Select Date Before Current Date</h3>
<p>
Select Date: @Html.TextBoxFor(m => m.SelectedDateFromCander, new { id = "txtdatepicker" })</p>
<input type="submit" value="Submit" />
<br />
<h3>Your Selected Date : @ViewBag.SelectedDate </h3>
}
Now add the below modified code in your controller.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
[HttpGet]
public ActionResult Index()
{
UserDate _objmodel = new UserDate();
return View(_objmodel);
}
[HttpPost]
public ActionResult Index(UserDate _objmodel)
{
ViewBag.SelectedDate = _objmodel.SelectedDateFromCander;
return View(_objmodel);
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
[HttpGet]
public ActionResult Index()
{
UserDate _objmodel = new UserDate();
return View(_objmodel);
}
[HttpPost]
public ActionResult Index(UserDate _objmodel)
{
ViewBag.SelectedDate = _objmodel.SelectedDateFromCander;
return View(_objmodel);
}
}
}
In above code we have written code for post method also. Now we have done run the aplication.
Now we will check the system date.
Now click on text box to view the calender. in this user will now able to select beyond current date.
Now select the date and click on submit to get the selected date in controller.
Now in controller you will the selected date as shown below.
Now here is the final output.
The above date in mm/dd/YYYYY format....
CRUD Operation in MVC3 using Store Procedure's with Example
DataBase :
USE [SampleDatabse]
GO
/****** Object: Table [dbo].[Student] Script Date: 07/31/2013 01:34:47 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Student](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NULL,
[City] [varchar](50) NULL,
[Address] [varchar](50) NULL,
CONSTRAINT [PK_Student] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object: StoredProcedure [dbo].[Student_Update] Script Date: 07/31/2013 01:35:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create proc [dbo].[Student_Update]
@Id int,
@Name varchar(50),
@City varchar(50),
@Address varchar(50)
as
begin
update Student set
Name=@Name,
City=@City,Address=@Address
where Id=@Id
End
GO
/****** Object: StoredProcedure [dbo].[Student_LoadByPrimaryKey] Script Date: 07/31/2013 01:35:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create proc [dbo].[Student_LoadByPrimaryKey]
@Id int
as
begin
select *from Student where Id=@Id
End
GO
/****** Object: StoredProcedure [dbo].[Student_LoadAll] Script Date: 07/31/2013 01:35:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create proc [dbo].[Student_LoadAll]
as
begin
select *from Student
End
GO
/****** Object: StoredProcedure [dbo].[Student_Insert] Script Date: 07/31/2013 01:35:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create proc [dbo].[Student_Insert]
@Name varchar(50),
@City varchar(50),
@Address varchar(50)
as
begin
insert into Student values(@Name,@City,@Address)
End
GO
/****** Object: StoredProcedure [dbo].[Student_Delete] Script Date: 07/31/2013 01:35:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create proc [dbo].[Student_Delete]
@Id int
as
begin
delete from Student where Id=@Id
End
GO
Download SampleCode
USE [SampleDatabse]
GO
/****** Object: Table [dbo].[Student] Script Date: 07/31/2013 01:34:47 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Student](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NULL,
[City] [varchar](50) NULL,
[Address] [varchar](50) NULL,
CONSTRAINT [PK_Student] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object: StoredProcedure [dbo].[Student_Update] Script Date: 07/31/2013 01:35:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create proc [dbo].[Student_Update]
@Id int,
@Name varchar(50),
@City varchar(50),
@Address varchar(50)
as
begin
update Student set
Name=@Name,
City=@City,Address=@Address
where Id=@Id
End
GO
/****** Object: StoredProcedure [dbo].[Student_LoadByPrimaryKey] Script Date: 07/31/2013 01:35:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create proc [dbo].[Student_LoadByPrimaryKey]
@Id int
as
begin
select *from Student where Id=@Id
End
GO
/****** Object: StoredProcedure [dbo].[Student_LoadAll] Script Date: 07/31/2013 01:35:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create proc [dbo].[Student_LoadAll]
as
begin
select *from Student
End
GO
/****** Object: StoredProcedure [dbo].[Student_Insert] Script Date: 07/31/2013 01:35:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create proc [dbo].[Student_Insert]
@Name varchar(50),
@City varchar(50),
@Address varchar(50)
as
begin
insert into Student values(@Name,@City,@Address)
End
GO
/****** Object: StoredProcedure [dbo].[Student_Delete] Script Date: 07/31/2013 01:35:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create proc [dbo].[Student_Delete]
@Id int
as
begin
delete from Student where Id=@Id
End
GO
Select project and click ok button. As you press ok a new window will open in this you have to select type of project. select internet application and click ok.
After creating project we will add an entity file in our project. In this entity file we will include our table and Store procedures.
For creating the model file just follow the step.
Step 1:
Right click on you project and select add->New Item. click on new item as window will open.
Now form list select ADO.NET Entity Data Model. Rename the file and click ok. As you click on a new window will open where we have to select the generate db option and click next.
Saturday, July 27, 2013
eCommerce Project using MVC3 with EF 4.1
Chapter - 1
What You'll Build
You'll implement a simple movie-listing application that supports creating, editing, and listing movies from a database. Below are two screenshots of the application you’ll build. It includes a page that displays a list of movies from a database:The application also lets you add, edit, and delete movies, as well as see details about individual ones. All data-entry scenarios include validation to ensure that the data stored in the database is correct.
Skills You'll Learn
Here's what you'll learn:- How to create a new ASP.NET MVC project.
- How to create ASP.NET MVC controllers and views.
- How to create a new database using the Entity Framework Code First paradigm.
- How to retrieve and display data.
- How to edit data and enable data validation.
Getting Started
Start by running Visual Web Developer 2010 Express ("Visual Web Developer" for short) and select New Project from the Start page.Visual Web Developer is an IDE, or integrated development environment. Just like you use Microsoft Word to write documents, you'll use an IDE to create applications. In Visual Web Developer there's a toolbar along the top showing various options available to you. There's also a menu that provides another way to perform tasks in the IDE. (For example, instead of selecting New Project from the Start page, you can use the menu and select File > New Project.)
Creating Your First Application
You can create applications using either Visual Basic or Visual C# as the programming language. Select Visual C# on the left and then select ASP.NET MVC 3 Web Application. Name your project "MvcMovie" and then click OK. (If you prefer Visual Basic, switch to the Visual Basic version of this tutorial.)In the New ASP.NET MVC 3 Project dialog box, select Internet Application. Check Use HTML5 markup and leave Razor as the default view engine.
Click OK. Visual Web Developer used a default template for the ASP.NET MVC project you just created, so you have a working application right now without doing anything! This is a simple "Hello World!" project, and it's a good place to start your application.
From the Debug menu, select Start Debugging.
Notice that the keyboard shortcut to start debugging is F5.
F5 causes Visual Web Developer to start a development web server and run your web application. Visual Web Developer then launches a browser and opens the application's home page. Notice that the address bar of the browser says
localhost and not something like example.com. That's because localhost
always points to your own local computer, which in this case is running
the application you just built. When Visual Web Developer runs a web
project, a random port is used for the web server. In the image below,
the random port number is 43246. When you run the application, you'll
probably see a different port number.Right out of the box this default template gives you two pages to visit and a basic login page. The next step is to change how this application works and learn a little bit about ASP.NET MVC in the process. Close your browser and let's change some code.
Chapter -2
Adding a Controller (C#)
MVC stands for model-view-controller. MVC is a pattern for developing applications that are well architected and easy to maintain. MVC-based applications contain:
Let's begin by creating a controller class. In Solution Explorer, right-click the Controllers folder and then select Add Controller.

Name your new controller "HelloWorldController". Leave the default template as Empty controller and click Add.

Notice in Solution Explorer that a new file has been created named HelloWorldController.cs. The file is open in the IDE.

Inside the

ASP.NET MVC invokes different controller classes (and different action methods within them) depending on the incoming URL. The default mapping logic used by ASP.NET MVC uses a format like this to determine what code to invoke:
The first part of the URL determines the controller class to execute. So /HelloWorld maps to the
Browse to http://localhost:xxxx/HelloWorld/Welcome. The

Let's modify the example slightly so that you can pass some parameter information from the URL to the controller (for example, /HelloWorld/Welcome?name=Scott&numtimes=4). Change your

In both these examples the controller has been doing the "VC" portion of MVC — that is, the view and controller work. The controller is returning HTML directly. Ordinarily you don't want controllers returning HTML directly, since that becomes very cumbersome to code. Instead we'll typically use a separate view template file to help generate the HTML response. Let's look next at how we can do this.
- Controllers: Classes that handle incoming requests to the application, retrieve model data, and then specify view templates that return a response to the client.
- Models: Classes that represent the data of the application and that use validation logic to enforce business rules for that data.
- Views: Template files that your application uses to dynamically generate HTML responses.
Let's begin by creating a controller class. In Solution Explorer, right-click the Controllers folder and then select Add Controller.
Name your new controller "HelloWorldController". Leave the default template as Empty controller and click Add.
Notice in Solution Explorer that a new file has been created named HelloWorldController.cs. The file is open in the IDE.
Inside the
public class HelloWorldController block, create two methods that look like the following code. The controller will return a string of HTML as an example.using System.Web; using System.Web.Mvc; namespace MvcMovie.Controllers { public class HelloWorldController : Controller { // // GET: /HelloWorld/ public string Index() { return "This is my <b>default</b> action..."; } // // GET: /HelloWorld/Welcome/ public string Welcome() { return "This is the Welcome action method..."; } } }Your controller is named
HelloWorldController and the first method above is named Index.
Let’s invoke it from a browser. Run the application (press F5 or
Ctrl+F5). In the browser, append "HelloWorld" to the path in the address
bar. (For example, in the illustration below, it's http://localhost:43246/HelloWorld.)
The page in the browser will look like the following screenshot. In the
method above, the code returned a string directly. You told the system
to just return some HTML, and it did!ASP.NET MVC invokes different controller classes (and different action methods within them) depending on the incoming URL. The default mapping logic used by ASP.NET MVC uses a format like this to determine what code to invoke:
/[Controller]/[ActionName]/[Parameters]The first part of the URL determines the controller class to execute. So /HelloWorld maps to the
HelloWorldController class. The second part of the URL determines the action method on the class to execute. So /HelloWorld/Index would cause the Index method of the HelloWorldController class to execute. Notice that we only had to browse to /HelloWorld and the Index method was used by default. This is because a method named Index is the default method that will be called on a controller if one is not explicitly specified.Browse to http://localhost:xxxx/HelloWorld/Welcome. The
Welcome method runs and returns the string "This is the Welcome action method...". The default MVC mapping is /[Controller]/[ActionName]/[Parameters]. For this URL, the controller is HelloWorld and Welcome is the action method. You haven't used the [Parameters] part of the URL yet.Let's modify the example slightly so that you can pass some parameter information from the URL to the controller (for example, /HelloWorld/Welcome?name=Scott&numtimes=4). Change your
Welcome
method to include two parameters as shown below. Note that the code
uses the C# optional-parameter feature to indicate that the numTimes parameter should default to 1 if no value is passed for that parameter.public string Welcome(string name, int numTimes = 1) { return HttpUtility.HtmlEncode("Hello " + name + ", NumTimes is: " + numTimes); }Run your application and browse to the example URL (http://localhost:xxxx/HelloWorld/Welcome?name=Scott&numtimes=4). You can try different values for
name and numtimes
in the URL. The system automatically maps the named parameters from the
query string in the address bar to parameters in your method.In both these examples the controller has been doing the "VC" portion of MVC — that is, the view and controller work. The controller is returning HTML directly. Ordinarily you don't want controllers returning HTML directly, since that becomes very cumbersome to code. Instead we'll typically use a separate view template file to help generate the HTML response. Let's look next at how we can do this.
Chapter - 3
Adding a View (C#)
In this section you're going to modify the
You'll create a view template file using the new Razor view engine introduced with ASP.NET MVC 3. Razor-based view templates have a .cshtml file extension, and provide an elegant way to create HTML output using C#. Razor minimizes the number of characters and keystrokes required when writing a view template, and enables a fast, fluid coding workflow.
Start by using a view template with the

The Add View dialog box appears. Leave the defaults the way they are and click the Add button:

The MvcMovie\Views\HelloWorld folder and the MvcMovie\Views\HelloWorld\Index.cshtml file are created. You can see them in Solution Explorer:

The following shows the Index.cshtml file that was created:

Add some HTML under the

Looks pretty good. However, notice that the browser's title bar says "Index" and the big title on the page says "My MVC Application." Let's change those.

Layout templates allow you to specify the HTML container layout of your site in one place and then apply it across multiple pages in your site. Note the

The complete _Layout.cshtml file is shown below:
Open MvcMovie\Views\HelloWorld\Index.cshtml. There are two places to make a change: first, the text that appears in the title of the browser, and then in the secondary header (the
Run the application and browse to http://localhost:xx/HelloWorld. Notice that the browser title, the primary heading, and the secondary headings have changed. (If you don't see changes in the browser, you might be viewing cached content. Press Ctrl+F5 in your browser to force the response from the server to be loaded.)
Also notice how the content in the Index.cshtml view template was merged with the _Layout.cshtml view template and a single HTML response was sent to the browser. Layout templates make it really easy to make changes that apply across all of the pages in your application.

Our little bit of "data" (in this case the "Hello from our View Template!" message) is hard-coded, though. The MVC application has a "V" (view) and you've got a "C" (controller), but no "M" (model) yet. Shortly, we'll walk through how create a database and retrieve model data from it.
Controllers are responsible for providing whatever data or objects are required in order for a view template to render a response to the browser. A view template should never perform business logic or interact with a database directly. Instead, it should work only with the data that's provided to it by the controller. Maintaining this "separation of concerns" helps keep your code clean and more maintainable.
Currently, the
Return to the HelloWorldController.cs file and change the
Next, you need a Welcome view template! In the Debug menu, select Build MvcMovie to make sure the project is compiled.

Then right-click inside the

Click Add, and then add the following code under the
http://localhost:xx/HelloWorld/Welcome?name=Scott&numtimes=4
Now data is taken from the URL and passed to the controller automatically. The controller packages the data into a

Well, that was a kind of an "M" for model, but not the database kind. Let's take what we've learned and create a database of movies.
Chapter - 4
You’ll use a .NET Framework data-access technology known as the Entity Framework to define and work with these model classes. The Entity Framework (often referred to as EF) supports a development paradigm called Code First. Code First allows you to create model objects by writing simple classes. (These are also known as POCO classes, from "plain-old CLR objects.") You can then have the database created on the fly from your classes, which enables a very clean and rapid development workflow.

Name the class "Movie".

Add the following five properties to the
In the same file, add the following
In order to be able to reference
Open the application root Web.config file. (Not the Web.config file in the Views folder.) The image below show both Web.config files; open the Web.config file circled in red.

Next, you'll build a new
Chapter - 5
Chapter -6
HelloWorldController class to use view template files to cleanly encapsulate the process of generating HTML responses to a client.You'll create a view template file using the new Razor view engine introduced with ASP.NET MVC 3. Razor-based view templates have a .cshtml file extension, and provide an elegant way to create HTML output using C#. Razor minimizes the number of characters and keystrokes required when writing a view template, and enables a fast, fluid coding workflow.
Start by using a view template with the
Index method in the HelloWorldController class. Currently the Index method returns a string with a message that is hard-coded in the controller class. Change the Index method to return a View object, as shown in the following:public ActionResult Index() { return View(); }This code uses a view template to generate an HTML response to the browser. In the project, add a view template that you can use with the
Index method. To do this, right-click inside the Index method and click Add View.The Add View dialog box appears. Leave the defaults the way they are and click the Add button:
The MvcMovie\Views\HelloWorld folder and the MvcMovie\Views\HelloWorld\Index.cshtml file are created. You can see them in Solution Explorer:
The following shows the Index.cshtml file that was created:
Add some HTML under the
<h2> tag. The modified MvcMovie\Views\HelloWorld\Index.cshtml file is shown below.@{ ViewBag.Title = "Index"; } <h2>Index</h2> <p>Hello from our View Template!</p>Run the application and browse to the
HelloWorld controller (http://localhost:xxxx/HelloWorld). The Index method in your controller didn't do much work; it simply ran the statement return View(),
which specified that the method should use a view template file to
render a response to the browser. Because you didn't explicitly specify
the name of the view template file to use, ASP.NET MVC defaulted to
using the Index.cshtml view file in the \Views\HelloWorld folder. The image below shows the string hard-coded in the view.Looks pretty good. However, notice that the browser's title bar says "Index" and the big title on the page says "My MVC Application." Let's change those.
Changing Views and Layout Pages
First, you want to change the "My MVC Application" title at the top of the page. That text is common to every page. It actually is implemented in only one place in the project, even though it appears on every page in the application. Go to the /Views/Shared folder in Solution Explorer and open the _Layout.cshtml file. This file is called a layout page and it's the shared "shell" that all other pages use.Layout templates allow you to specify the HTML container layout of your site in one place and then apply it across multiple pages in your site. Note the
@RenderBody() line near the bottom of the file. RenderBody
is a placeholder where all the view-specific pages you create show up,
"wrapped" in the layout page. Change the title heading in the layout
template from "My MVC Application" to "MVC Movie App".<div id="title"> <h1>MVC Movie App</h1> </div>Run the application and notice that it now says "MVC Movie App". Click the About link, and you see how that page shows "MVC Movie App", too. We were able to make the change once in the layout template and have all pages on the site reflect the new title.
The complete _Layout.cshtml file is shown below:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>@ViewBag.Title</title> <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" /> <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script> </head> <body> <div class="page"> <header> <div id="title"> <h1>MVC Movie App</h1> </div> <div id="logindisplay"> @Html.Partial("_LogOnPartial") </div> <nav> <ul id="menu"> <li>@Html.ActionLink("Home", "Index", "Home")</li> <li>@Html.ActionLink("About", "About", "Home")</li> </ul> </nav> </header> <section id="main"> @RenderBody() </section> <footer> </footer> </div> </body> </html>Now, let's change the title of the Index page (view).
Open MvcMovie\Views\HelloWorld\Index.cshtml. There are two places to make a change: first, the text that appears in the title of the browser, and then in the secondary header (the
<h2> element). You'll make them slightly different so you can see which bit of code changes which part of the app.@{ ViewBag.Title = "Movie List"; } <h2>My Movie List</h2> <p>Hello from our View Template!</p>To indicate the HTML title to display, the code above sets a
Title property of the ViewBag object (which is in the Index.cshtml
view template). If you look back at the source code of the layout
template, you’ll notice that the template uses this value in the <title> element as part of the <head> section of the HTML. Using this approach, you can easily pass other parameters between your view template and your layout file.Run the application and browse to http://localhost:xx/HelloWorld. Notice that the browser title, the primary heading, and the secondary headings have changed. (If you don't see changes in the browser, you might be viewing cached content. Press Ctrl+F5 in your browser to force the response from the server to be loaded.)
Also notice how the content in the Index.cshtml view template was merged with the _Layout.cshtml view template and a single HTML response was sent to the browser. Layout templates make it really easy to make changes that apply across all of the pages in your application.
Our little bit of "data" (in this case the "Hello from our View Template!" message) is hard-coded, though. The MVC application has a "V" (view) and you've got a "C" (controller), but no "M" (model) yet. Shortly, we'll walk through how create a database and retrieve model data from it.
Passing Data from the Controller to the View
Before we go to a database and talk about models, though, let's first talk about passing information from the controller to a view. Controller classes are invoked in response to an incoming URL request. A controller class is where you write the code that handles the incoming parameters, retrieves data from a database, and ultimately decides what type of response to send back to the browser. View templates can then be used from a controller to generate and format an HTML response to the browser.Controllers are responsible for providing whatever data or objects are required in order for a view template to render a response to the browser. A view template should never perform business logic or interact with a database directly. Instead, it should work only with the data that's provided to it by the controller. Maintaining this "separation of concerns" helps keep your code clean and more maintainable.
Currently, the
Welcome action method in the HelloWorldController class takes a name and a numTimes
parameter and then outputs the values directly to the browser. Rather
than have the controller render this response as a string, let’s change
the controller to use a view template instead. The view template will
generate a dynamic response, which means that you need to pass
appropriate bits of data from the controller to the view in order to
generate the response. You can do this by having the controller put the
dynamic data that the view template needs in a ViewBag object that the view template can then access.Return to the HelloWorldController.cs file and change the
Welcome method to add a Message and NumTimes value to the ViewBag object. ViewBag is a dynamic object, which means you can put whatever you want in to it; the ViewBag object has no defined properties until you put something inside it. The complete HelloWorldController.cs file looks like this:using System.Web; using System.Web.Mvc; namespace MvcMovie.Controllers { public class HelloWorldController : Controller { public ActionResult Index() { return View(); } public ActionResult Welcome(string name, int numTimes = 1) { ViewBag.Message = "Hello " + name; ViewBag.NumTimes = numTimes; return View(); } } }Now the
ViewBag object contains data that will be passed to the view automatically.Next, you need a Welcome view template! In the Debug menu, select Build MvcMovie to make sure the project is compiled.
Then right-click inside the
Welcome method and click Add View. Here's what the Add View dialog box looks like:Click Add, and then add the following code under the
<h2> element in the new Welcome.cshtml file. You'll create a loop that says "Hello" as many times as the user says it should. The complete Welcome.cshtml file is shown below.@{ ViewBag.Title = "Welcome"; } <h2>Welcome</h2> <ul> @for (int i=0; i < ViewBag.NumTimes; i++) { <li>@ViewBag.Message</li> } </ul>Run the application and browse to the following URL:
http://localhost:xx/HelloWorld/Welcome?name=Scott&numtimes=4
Now data is taken from the URL and passed to the controller automatically. The controller packages the data into a
ViewBag object and passes that object to the view. The view then displays the data as HTML to the user.Well, that was a kind of an "M" for model, but not the database kind. Let's take what we've learned and create a database of movies.
Chapter - 4
Adding a Model (C#)
Adding a Model
In this section you'll add some classes for managing movies in a database. These classes will be the "model" part of the ASP.NET MVC application.You’ll use a .NET Framework data-access technology known as the Entity Framework to define and work with these model classes. The Entity Framework (often referred to as EF) supports a development paradigm called Code First. Code First allows you to create model objects by writing simple classes. (These are also known as POCO classes, from "plain-old CLR objects.") You can then have the database created on the fly from your classes, which enables a very clean and rapid development workflow.
Adding Model Classes
In Solution Explorer, right click the Models folder, select Add, and then select Class.Name the class "Movie".
Add the following five properties to the
Movie class:public class Movie { public int ID { get; set; } public string Title { get; set; } public DateTime ReleaseDate { get; set; } public string Genre { get; set; } public decimal Price { get; set; } }We'll use the
Movie class to represent movies in a database. Each instance of a Movie object will correspond to a row within a database table, and each property of the Movie class will map to a column in the table. In the same file, add the following
MovieDBContext class:public class MovieDBContext : DbContext { public DbSet<Movie> Movies { get; set; } }The
MovieDBContext class represents the Entity Framework movie database context, which handles fetching, storing, and updating Movie class instances in a database. The MovieDBContext derives from the DbContext base class provided by the Entity Framework. For more information about DbContext and DbSet, see Productivity Improvements for the Entity Framework. In order to be able to reference
DbContext and DbSet, you need to add the following using statement at the top of the file:using System.Data.Entity;The complete Movie.cs file is shown below.
using System; using System.Data.Entity; namespace MvcMovie.Models { public class Movie { public int ID { get; set; } public string Title { get; set; } public DateTime ReleaseDate { get; set; } public string Genre { get; set; } public decimal Price { get; set; } } public class MovieDBContext : DbContext { public DbSet<Movie> Movies { get; set; } } }
Creating a Connection String and Working with SQL Server Compact
TheMovieDBContext class you created handles the task of connecting to the database and mapping Movie
objects to database records. One question you might ask, though, is how
to specify which database it will connect to. You'll do that by adding
connection information in the Web.config file of the application.Open the application root Web.config file. (Not the Web.config file in the Views folder.) The image below show both Web.config files; open the Web.config file circled in red.
Add the following connection string to the
<connectionStrings> element in the Web.config file.<add name="MovieDBContext" connectionString="Data Source=|DataDirectory|Movies.sdf" providerName="System.Data.SqlServerCe.4.0"/>The following example shows a portion of the Web.config file with the new connection string added:
<configuration> <connectionStrings> <add name="MovieDBContext" connectionString="Data Source=|DataDirectory|Movies.sdf" providerName="System.Data.SqlServerCe.4.0"/> <add name="ApplicationServices" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient" /> </connectionStrings>This small amount of code and XML is everything you need to write in order to represent and store the movie data in a database.
Next, you'll build a new
MoviesController class that you can use to display the movie data and allow users to create new movie listings.Chapter - 5
Accessing your Model's Data from a Controller (C#)
In this section, you'll create a new
Right-click the Controllers folder and create a new

Click Add. Visual Web Developer creates the following files and folders:

The ASP.NET MVC 3 scaffolding mechanism automatically created the CRUD (create, read, update, and delete) action methods and views for you. You now have a fully functional web application that lets you create, list, edit, and delete movie entries.
Run the application and browse to the


Clicking the Create button causes the form to be posted to the server, where the movie information is saved in the database. You're then redirected to the /Movies URL, where you can see the newly created movie in the listing.

Create a couple more movie entries. Try the Edit, Details, and Delete links, which are all functional.
ASP.NET MVC also provides the ability to pass strongly typed data or objects to a view template. This strongly typed approach enables better compile-time checking of your code and richer IntelliSense in the Visual Web Developer editor. We're using this approach with the
Notice how the code creates a


Double-click Movies.sdf to open Server Explorer. Then expand the Tables folder to see the tables that have been created in the database.

There are two tables, one for the
Right-click the

Right-click the


Notice how the schema of the
When you're finished, close the connection. (If you don't close the connection, you might get an error the next time you run the project).

You now have the database and a simple listing page to display content from it. In the next tutorial, we'll examine the rest of the scaffolded code and add a
MoviesController
class and write code that retrieves the movie data and displays it in
the browser using a view template. Be sure to build your application
before proceeding.Right-click the Controllers folder and create a new
MoviesController controller. Select the following options:- Controller name: MoviesController. (This is the default. )
- Template: Controller with read/write actions and views, using Entity Framework.
- Model class: Movie (MvcMovie.Models).
- Data context class: MovieDBContext (MvcMovie.Models).
- Views: Razor (CSHTML). (The default.)
Click Add. Visual Web Developer creates the following files and folders:
- A MoviesController.cs file in the project's Controllers folder.
- A Movies folder in the project's Views folder.
- Create.cshtml, Delete.cshtml, Details.cshtml, Edit.cshtml, and Index.cshtml in the new Views\Movies folder.
The ASP.NET MVC 3 scaffolding mechanism automatically created the CRUD (create, read, update, and delete) action methods and views for you. You now have a fully functional web application that lets you create, list, edit, and delete movie entries.
Run the application and browse to the
Movies controller by appending /Movies to the URL in the address bar of your browser. Because the application is relying on the default routing (defined in the Global.asax file), the browser request http://localhost:xxxxx/Movies is routed to the default Index action method of the Movies controller. In other words, the browser request http://localhost:xxxxx/Movies is effectively the same as the browser request http://localhost:xxxxx/Movies/Index. The result is an empty list of movies, because you haven't added any yet.Creating a Movie
Select the Create New link. Enter some details about a movie and then click the Create button.Clicking the Create button causes the form to be posted to the server, where the movie information is saved in the database. You're then redirected to the /Movies URL, where you can see the newly created movie in the listing.
Create a couple more movie entries. Try the Edit, Details, and Delete links, which are all functional.
Examining the Generated Code
Open the Controllers\MoviesController.cs file and examine the generatedIndex method. A portion of the movie controller with the Index method is shown below.public class MoviesController : Controller { private MovieDBContext db = new MovieDBContext(); // // GET: /Movies/ public ViewResult Index() { return View(db.Movies.ToList()); }The following line from the
MoviesController class
instantiates a movie database context, as described previously. You can
use the movie database context to query, edit, and delete movies.private MovieDBContext db = new MovieDBContext();A request to the
Movies controller returns all the entries in the Movies table of the movie database and then passes the results to the Index view.Strongly Typed Models and the @model Keyword
Earlier in this tutorial, you saw how a controller can pass data or objects to a view template using theViewBag object. The ViewBag is a dynamic object that provides a convenient late-bound way to pass information to a view.ASP.NET MVC also provides the ability to pass strongly typed data or objects to a view template. This strongly typed approach enables better compile-time checking of your code and richer IntelliSense in the Visual Web Developer editor. We're using this approach with the
MoviesController class and Index.cshtml view template.Notice how the code creates a
List object when it calls the View helper method in the Index action method. The code then passes this Movies list from the controller to the view:public ViewResult Index() { return View(db.Movies.ToList()); }By including a
@model statement at the top of the view
template file, you can specify the type of object that the view expects.
When you created the movie controller, Visual Web Developer
automatically included the following @model statement at the top of the Index.cshtml file:@model IEnumerable<MvcMovie.Models.Movie>This
@model directive allows you to access the list of movies that the controller passed to the view by using a Model object that's strongly typed. For example, in the Index.cshtml template, the code loops through the movies by doing a foreach statement over the strongly typed Model object:@foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.Title) </td> <td> @Html.DisplayFor(modelItem => item.ReleaseDate) </td> <td> @Html.DisplayFor(modelItem => item.Genre) </td> <td> @Html.DisplayFor(modelItem => item.Price) </td> <td> @Html.ActionLink("Edit", "Edit", new { id=item.ID }) | @Html.ActionLink("Details", "Details", new { id=item.ID }) | @Html.ActionLink("Delete", "Delete", new { id=item.ID }) </td> </tr> }Because the
Model object is strongly typed (as an IEnumerable<Movie> object), each item object in the loop is typed as Movie.
Among other benefits, this means that you get compile-time checking of
the code and full IntelliSense support in the code editor:Working with SQL Server Compact
Entity Framework Code First detected that the database connection string that was provided pointed to aMovies
database that didn’t exist yet, so Code First created the database
automatically. You can verify that it's been created by looking in the App_Data folder. If you don't see the Movies.sdf file, click the Show All Files button in the Solution Explorer toolbar, click the Refresh button, and then expand the App_Data folder.Double-click Movies.sdf to open Server Explorer. Then expand the Tables folder to see the tables that have been created in the database.
Note If you get an error when you double-click Movies.sdf, make sure you've installed SQL Server Compact 4.0 (runtime
+ tools support). (For links to the software, see the list of
prerequisites in part 1 of this tutorial series.) If you install the
release now, you'll have to close and re-open Visual Web Developer.
There are two tables, one for the
Movie entity set and then the EdmMetadata table. The EdmMetadata table is used by the Entity Framework to determine when the model and the database are out of sync. Right-click the
Movies table and select Show Table Data to see the data you created.Right-click the
Movies table and select Edit Table Schema.Notice how the schema of the
Movies table maps to the Movie class you created earlier. Entity Framework Code First automatically created this schema for you based on your Movie class.When you're finished, close the connection. (If you don't close the connection, you might get an error the next time you run the project).
You now have the database and a simple listing page to display content from it. In the next tutorial, we'll examine the rest of the scaffolded code and add a
SearchIndex method and a SearchIndex view that lets you search for movies in this database.Chapter -6
Examining the Edit Methods and Edit View (C#)
In this section, you'll examine the generated action methods
and views for the movie controller. Then you'll add a custom search
page.
Run the application and browse to the

The Edit link was generated by the

The
The generated link shown in the previous image is http://localhost:xxxxx/Movies/Edit/4. The default route takes the URL pattern
You can also pass action method parameters using a query string. For example, the URL http://localhost:xxxxx/Movies/Edit?ID=4 also passes the parameter

Open the
The
The scaffolded code uses several helper methods to streamline the HTML markup. The
Run the application and navigate to the /Movies URL. Click an Edit link. In the browser, view the source for the page. The HTML in the page looks like the following example. (The menu markup was excluded for clarity.)
If the posted values aren't valid, they are redisplayed in the form. The


A user could also pass an ID that doesn't exist in the database, such as http://localhost:xxxxx/Movies/Edit/1234. You can make two changes to the
All the
If the
Now you can implement the

When you click the Add button, the Views\Movies\SearchIndex.cshtml view template is created. Because you selected List in the Scaffold template list, Visual Web Developer automatically generated (scaffolded) some default content in the view. The scaffolding created an HTML form. It examined the

If you change the signature of the

However, you can't expect users to modify the URL every time they want to search for a movie. So now you you'll add UI to help them filter movies. If you changed the signature of the
Run the application and try searching for a movie.
There's no
You could add the following

However, even if you add this
The solution is to use an overload of

Now when you submit a search, the URL contains a search query string. Searching will also go to the

Next, you'll add a feature to let users search for movies by genre. Replace the
The following code is a LINQ query that retrieves all the genres from the database.
The following code shows how to check the
In this section you examined the CRUD action methods and views generated by the framework. You created a search action method and view that let users search by movie title and genre. In the next section, you'll look at how to add a property to the
Chapter -6
Run the application and browse to the
Movies controller by appending /Movies to the URL in the address bar of your browser. Hold the mouse pointer over an Edit link to see the URL that it links to.The Edit link was generated by the
Html.ActionLink method in the Views\Movies\Index.cshtml view: @Html.ActionLink("Edit", "Edit", new { id=item.ID })
The
Html object is a helper that's exposed using a property on the WebViewPage base class. The ActionLink method
of the helper makes it easy to dynamically generate HTML hyperlinks
that link to action methods on controllers. The first argument to the ActionLink method is the link text to render (for example, <a>Edit Me</a>). The second argument is the name of the action method to invoke. The final argument is an anonymous object that generates the route data (in this case, the ID of 4). The generated link shown in the previous image is http://localhost:xxxxx/Movies/Edit/4. The default route takes the URL pattern
{controller}/{action}/{id}. Therefore, ASP.NET translates http://localhost:xxxxx/Movies/Edit/4 into a request to the Edit action method of the Movies controller with the parameter ID equal to 4. You can also pass action method parameters using a query string. For example, the URL http://localhost:xxxxx/Movies/Edit?ID=4 also passes the parameter
ID of 4 to the Edit action method of the Movies controller.Open the
Movies controller. The two Edit action methods are shown below.// // GET: /Movies/Edit/5 public ActionResult Edit(int id) { Movie movie = db.Movies.Find(id); return View(movie); } // // POST: /Movies/Edit/5 [HttpPost] public ActionResult Edit(Movie movie) { if (ModelState.IsValid) { db.Entry(movie).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Index"); } return View(movie); }Notice the second
Edit action method is preceded by the HttpPost attribute. This attribute specifies that that overload of the Edit method can be invoked only for POST requests. You could apply the HttpGet
attribute to the first edit method, but that's not necessary because
it's the default. (We'll refer to action methods that are implicitly
assigned the HttpGet attribute as HttpGet methods.)The
HttpGet Edit method takes the movie ID parameter, looks up the movie using the Entity Framework Find method, and returns the selected movie to the Edit view. When the scaffolding system created the Edit view, it examined the Movie class and created code to render <label> and <input> elements for each property of the class. The following example shows the Edit view that was generated:@model MvcMovie.Models.Movie @{ ViewBag.Title = "Edit"; } <h2>Edit</h2> <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> @using (Html.BeginForm()) { @Html.ValidationSummary(true) <fieldset> <legend>Movie</legend> @Html.HiddenFor(model => model.ID) <div class="editor-label"> @Html.LabelFor(model => model.Title) </div> <div class="editor-field"> @Html.EditorFor(model => model.Title) @Html.ValidationMessageFor(model => model.Title) </div> <div class="editor-label"> @Html.LabelFor(model => model.ReleaseDate) </div> <div class="editor-field"> @Html.EditorFor(model => model.ReleaseDate) @Html.ValidationMessageFor(model => model.ReleaseDate) </div> <div class="editor-label"> @Html.LabelFor(model => model.Genre) </div> <div class="editor-field"> @Html.EditorFor(model => model.Genre) @Html.ValidationMessageFor(model => model.Genre) </div> <div class="editor-label"> @Html.LabelFor(model => model.Price) </div> <div class="editor-field"> @Html.EditorFor(model => model.Price) @Html.ValidationMessageFor(model => model.Price) </div> <p> <input type="submit" value="Save" /> </p> </fieldset> } <div> @Html.ActionLink("Back to List", "Index") </div>Notice how the view template has a
@model MvcMovie.Models.Movie statement at the top of the file — this specifies that the view expects the model for the view template to be of type Movie.The scaffolded code uses several helper methods to streamline the HTML markup. The
Html.LabelFor helper displays the name of the field ("Title", "ReleaseDate", "Genre", or "Price"). The Html.EditorFor helper displays an HTML <input> element. The Html.ValidationMessageFor helper displays any validation messages associated with that property. Run the application and navigate to the /Movies URL. Click an Edit link. In the browser, view the source for the page. The HTML in the page looks like the following example. (The menu markup was excluded for clarity.)
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Edit</title> <link href="/Content/Site.css" rel="stylesheet" type="text/css" /> <script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script> <script src="/Scripts/modernizr-1.7.min.js" type="text/javascript"></script> </head> <body> <div class="page"> <header> <div id="title"> <h1>MVC Movie App</h1> </div> ... </header> <section id="main"> <h2>Edit</h2> <script src="/Scripts/jquery.validate.min.js" type="text/javascript"></script> <script src="/Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script> <form action="/Movies/Edit/4" method="post"> <fieldset> <legend>Movie</legend> <input data-val="true" data-val-number="The field ID must be a number." data-val-required="The ID field is required." id="ID" name="ID" type="hidden" value="4" /> <div class="editor-label"> <label for="Title">Title</label> </div> <div class="editor-field"> <input class="text-box single-line" id="Title" name="Title" type="text" value="Rio Bravo" /> <span class="field-validation-valid" data-valmsg-for="Title" data-valmsg-replace="true"></span> </div> <div class="editor-label"> <label for="ReleaseDate">ReleaseDate</label> </div> <div class="editor-field"> <input class="text-box single-line" data-val="true" data-val-required="The ReleaseDate field is required." id="ReleaseDate" name="ReleaseDate" type="text" value="4/15/1959 12:00:00 AM" /> <span class="field-validation-valid" data-valmsg-for="ReleaseDate" data-valmsg-replace="true"></span> </div> <div class="editor-label"> <label for="Genre">Genre</label> </div> <div class="editor-field"> <input class="text-box single-line" id="Genre" name="Genre" type="text" value="Western" /> <span class="field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span> </div> <div class="editor-label"> <label for="Price">Price</label> </div> <div class="editor-field"> <input class="text-box single-line" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Price" name="Price" type="text" value="9.99" /> <span class="field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span> </div> <p> <input type="submit" value="Save" /> </p> </fieldset> </form> <div> <a href="/Movies">Back to List</a> </div> </section> <footer> </footer> </div> </body> </html>The
<input> elements are in an HTML <form> element whose action attribute is set to post to the /Movies/Edit URL. The form data will be posted to the server when the Edit button is clicked.Processing the POST Request
The following listing shows theHttpPost version of the Edit action method.[HttpPost] public ActionResult Edit(Movie movie) { if (ModelState.IsValid) { db.Entry(movie).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Index"); } return View(movie); }The ASP.NET framework model binder takes the posted form values and creates a
Movie object that's passed as the movie parameter. The ModelState.IsValid check in the code verifies that the data submitted in the form can be used to modify a Movie object. If the data is valid, the code saves the movie data to the Movies collection of the MovieDBContext instance. The code then saves the new movie data to the database by calling the SaveChanges method of MovieDBContext, which persists changes to the database. After saving the data, the code redirects the user to the Index action method of the MoviesController class, which causes the updated movie to be displayed in the listing of movies.If the posted values aren't valid, they are redisplayed in the form. The
Html.ValidationMessageFor helpers in the Edit.cshtml view template take care of displaying appropriate error messages.
Note about locales If you normally work with a locale other than English, see Supporting ASP.NET MVC 3 Validation with Non-English Locales.
Making the Edit Method More Robust
TheHttpGet Edit method generated by the
scaffolding system doesn't check that the ID that's passed to it is
valid. If a user removes the ID segment from the URL (http://localhost:xxxxx/Movies/Edit), the following error is displayed:A user could also pass an ID that doesn't exist in the database, such as http://localhost:xxxxx/Movies/Edit/1234. You can make two changes to the
HttpGet Edit action method to address this limitation. First, change the ID parameter to have a default value of zero when an ID isn't explicitly passed. You can also check that the Find method actually found a movie before returning the movie object to the view template. The updated Edit method is shown below.public ActionResult Edit(int id = 0) { Movie movie = db.Movies.Find(id); if (movie == null) { return HttpNotFound(); } return View(movie); }If no movie is found, the
HttpNotFound method is called.All the
HttpGet methods follow a similar pattern. They get a movie object (or list of objects, in the case of Index), and pass the model to the view. The Create
method passes an empty movie object to the Create view. All the methods
that create, edit, delete, or otherwise modify data do so in the HttpPost overload of the method. Modifying data in an HTTP GET method is a security risk, as described in the blog post entry ASP.NET MVC Tip #46 – Don’t use Delete Links because they create Security Holes.
Modifying data in a GET method also violates HTTP best practices and
the architectural REST pattern, which specifies that GET requests should
not change the state of your application. In other words, performing a
GET operation should be a safe operation that has no side effects.Adding a Search Method and Search View
In this section you'll add aSearchIndex action method that lets you search movies by genre or name. This will be available using the /Movies/SearchIndex
URL. The request will display an HTML form that contains input elements
that a user can fill in in order to search for a movie. When a user
submits the form, the action method will get the search values posted by
the user and use the values to search the database.Displaying the SearchIndex Form
Start by adding aSearchIndex action method to the existing MoviesController class. The method will return a view that contains an HTML form. Here's the code:public ActionResult SearchIndex(string searchString) { var movies = from m in db.Movies select m; if (!String.IsNullOrEmpty(searchString)) { movies = movies.Where(s => s.Title.Contains(searchString)); } return View(movies); }The first line of the
SearchIndex method creates the following LINQ query to select the movies: var movies = from m in db.Movies select m;The query is defined at this point, but hasn't yet been run against the data store.
If the
searchString parameter contains a string, the
movies query is modified to filter on the value of the search string,
using the following code:if (!String.IsNullOrEmpty(searchString)) { movies = movies.Where(s => s.Title.Contains(searchString)); }LINQ queries are not executed when they are defined or when they are modified by calling a method such as
Where or OrderBy.
Instead, query execution is deferred, which means that the evaluation
of an expression is delayed until its realized value is actually
iterated over or the ToList method is called. In the SearchIndex sample, the query is executed in the SearchIndex view. For more information about deferred query execution, see Query Execution.Now you can implement the
SearchIndex view that will display the form to the user. Right-click inside the SearchIndex method and then click Add View. In the Add View dialog box, specify that you're going to pass a Movie object to the view template as its model class. In the Scaffold template list, choose List, then click Add.When you click the Add button, the Views\Movies\SearchIndex.cshtml view template is created. Because you selected List in the Scaffold template list, Visual Web Developer automatically generated (scaffolded) some default content in the view. The scaffolding created an HTML form. It examined the
Movie class and created code to render <label> elements for each property of the class. The listing below shows the Create view that was generated:@model IEnumerable<MvcMovie.Models.Movie> @{ ViewBag.Title = "SearchIndex"; } <h2>SearchIndex</h2> <p> @Html.ActionLink("Create New", "Create") </p> <table> <tr> <th> Title </th> <th> ReleaseDate </th> <th> Genre </th> <th> Price </th> <th></th> </tr> @foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.Title) </td> <td> @Html.DisplayFor(modelItem => item.ReleaseDate) </td> <td> @Html.DisplayFor(modelItem => item.Genre) </td> <td> @Html.DisplayFor(modelItem => item.Price) </td> <td> @Html.ActionLink("Edit", "Edit", new { id=item.ID }) | @Html.ActionLink("Details", "Details", new { id=item.ID }) | @Html.ActionLink("Delete", "Delete", new { id=item.ID }) </td> </tr> } </table>Run the application and navigate to /Movies/SearchIndex. Append a query string such as
?searchString=ghost to the URL. The filtered movies are displayed.If you change the signature of the
SearchIndex method to have a parameter named id, the id parameter will match the {id} placeholder for the default routes set in the Global.asax file.{controller}/{action}/{id}The modified
SearchIndex method would look as follows:public ActionResult SearchIndex(string id) { string searchString = id; var movies = from m in db.Movies select m; if (!String.IsNullOrEmpty(searchString)) { movies = movies.Where(s => s.Title.Contains(searchString)); } return View(movies); }You can now pass the search title as route data (a URL segment) instead of as a query string value.
However, you can't expect users to modify the URL every time they want to search for a movie. So now you you'll add UI to help them filter movies. If you changed the signature of the
SearchIndex method to test how to pass the route-bound ID parameter, change it back so that your SearchIndex method takes a string parameter named searchString:public ActionResult SearchIndex(string searchString) { var movies = from m in db.Movies select m; if (!String.IsNullOrEmpty(searchString)) { movies = movies.Where(s => s.Title.Contains(searchString)); } return View(movies); }Open the Views\Movies\SearchIndex.cshtml file, and just after
@Html.ActionLink("Create New", "Create"), add the following:@using (Html.BeginForm()){ <p> Title: @Html.TextBox("SearchString") <input type="submit" value="Filter" /></p> }The following example shows a portion of the Views\Movies\SearchIndex.cshtml file with the added filtering markup.
@model IEnumerable<MvcMovie.Models.Movie> @{ ViewBag.Title = "SearchIndex"; } <h2>SearchIndex</h2> <p> @Html.ActionLink("Create New", "Create") @using (Html.BeginForm()){ <p> Title: @Html.TextBox("SearchString") <br /> <input type="submit" value="Filter" /></p> } </p>The
Html.BeginForm helper creates an opening <form> tag. The Html.BeginForm helper causes the form to post to itself when the user submits the form by clicking the Filter button.Run the application and try searching for a movie.
There's no
HttpPost overload of the SearchIndex method. You don't need it, because the method isn't changing the state of the application, just filtering data.You could add the following
HttpPost SearchIndex method. In that case, the action invoker would match the HttpPost SearchIndex method, and the HttpPost SearchIndex method would run as shown in the image below.[HttpPost] public string SearchIndex(FormCollection fc, string searchString) { return "<h3> From [HttpPost]SearchIndex: " + searchString + "</h3>"; }
However, even if you add this
HttpPost version of the SearchIndex method,
there's a limitation in how this has all been implemented. Imagine that
you want to bookmark a particular search or you want to send a link to
friends that they can click in order to see the same filtered list of
movies. Notice that the URL for the HTTP POST request is the same as the
URL for the GET request (localhost:xxxxx/Movies/SearchIndex) -- there's
no search information in the URL itself. Right now, the search string
information is sent to the server as a form field value. This means you
can't capture that search information to bookmark or send to friends in a
URL.The solution is to use an overload of
BeginForm that
specifies that the POST request should add the search information to the
URL and that is should be routed to the HttpGet version of the SearchIndex method. Replace the existing parameterless BeginForm method with the following: @using (Html.BeginForm("SearchIndex","Movies",FormMethod.Get))
Now when you submit a search, the URL contains a search query string. Searching will also go to the
HttpGet SearchIndex action method, even if you have a HttpPost SearchIndex method.Adding Search by Genre
If you added theHttpPost version of the SearchIndex method, delete it now. Next, you'll add a feature to let users search for movies by genre. Replace the
SearchIndex method with the following code:public ActionResult SearchIndex(string movieGenre, string searchString) { var GenreLst = new List<string>(); var GenreQry = from d in db.Movies orderby d.Genre select d.Genre; GenreLst.AddRange(GenreQry.Distinct()); ViewBag.movieGenre = new SelectList(GenreLst); var movies = from m in db.Movies select m; if (!String.IsNullOrEmpty(searchString)) { movies = movies.Where(s => s.Title.Contains(searchString)); } if (string.IsNullOrEmpty(movieGenre)) return View(movies); else { return View(movies.Where(x => x.Genre == movieGenre)); } }This version of the
SearchIndex method takes an additional parameter, namely movieGenre. The first few lines of code create a List object to hold movie genres from the database. The following code is a LINQ query that retrieves all the genres from the database.
var GenreQry = from d in db.Movies orderby d.Genre select d.Genre;The code uses the
AddRange method of the generic List collection to add all the distinct genres to the list. (Without the Distinct
modifier, duplicate genres would be added — for example, comedy would
be added twice in our sample). The code then stores the list of genres
in the ViewBag object.The following code shows how to check the
movieGenre parameter. If it's not empty the code further constrains the movies query to limit the selected movies to the specified genre.if (string.IsNullOrEmpty(movieGenre)) return View(movies); else { return View(movies.Where(x => x.Genre == movieGenre)); }
Adding Markup to the SearchIndex View to Support Search by Genre
Add anHtml.DropDownList helper to the Views\Movies\SearchIndex.cshtml file, just before the TextBox helper. The completed markup is shown below:<p> @Html.ActionLink("Create New", "Create") @using (Html.BeginForm()){ <p>Genre: @Html.DropDownList("movieGenre", "All") Title: @Html.TextBox("SearchString") <input type="submit" value="Filter" /></p> } </p>Run the application and browse to /Movies/SearchIndex. Try a search by genre, by movie name, and by both criteria.
In this section you examined the CRUD action methods and views generated by the framework. You created a search action method and view that let users search by movie title and genre. In the next section, you'll look at how to add a property to the
Movie model and how to add an initializer that will automatically create a test database.Chapter -6
- Adding a New Field to the Movie Model and Table (C#)
In this section you'll make some changes to the model classes
and learn how you can update the database schema to match the model
changes.
Now that you've updated the
Open the \Views\Movies\Index.cshtml file and add a
Now run the application and navigate to the /Movies URL. When you do this, though, you'll see the following error:

You're seeing this error because the updated
By default, when you use Entity Framework Code First to automatically create a database, as you did earlier in this tutorial, Code First adds a table to the database to help track whether the schema of the database is in sync with the model classes it was generated from. If they aren't in sync, the Entity Framework throws an error. This makes it easier to track down issues at development time that you might otherwise only find (by obscure errors) at run time. The sync-checking feature is what causes the error message to be displayed that you just saw.
There are two approaches to resolving the error:

Name the class "MovieInitializer". Update the
Now that you've defined the
Open the Global.asax file that's at the root of the

The Global.asax file contains the class that defines the entire application for the project, and contains an
Let's add two using statements to the top of the file. The first references the Entity Framework namespace, and the second references the namespace where our
Close the Global.asax file.
Re-run the application and navigate to the /Movies URL. When the application starts, it detects that the model structure no longer matches the database schema. It automatically re-creates the database to match the new model structure and populates the database with the sample movies:

Click the Create New link to add a new movie. Note that you can add a rating.

Click Create. The new movie, including the rating, now shows up in the movies listing:

In this section you saw how you can modify model objects and keep the database in sync with the changes. You also learned a way to populate a newly created database with sample data so you can try out scenarios. Next, let's look at how you can add richer validation logic to the model classes and enable some business rules to be enforced.
Adding a Rating Property to the Movie Model
Start by adding a newRating property to the existing Movie class. Open the Movie.cs file and add the Rating property like this one:public string Rating { get; set; }The complete
Movie class now looks like the following code:public class Movie { public int ID { get; set; } public string Title { get; set; } public DateTime ReleaseDate { get; set; } public string Genre { get; set; } public decimal Price { get; set; } public string Rating { get; set; } }Recompile the application using the Debug > Build Movie menu command.
Now that you've updated the
Model class, you also need to update the \Views\Movies\Index.cshtml and \Views\Movies\Create.cshtml view templates in order to support the new Rating property.Open the \Views\Movies\Index.cshtml file and add a
<th>Rating</th> column heading just after the Price column. Then add a <td> column near the end of the template to render the @item.Rating value. Below is what the updated Index.cshtml view template looks like:<table> <tr> <th></th> <th>Title</th> <th>Release Date</th> <th>Genre</th> <th>Price</th> <th>Rating</th> </tr> @foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.Title) </td> <td> @Html.DisplayFor(modelItem => item.ReleaseDate) </td> <td> @Html.DisplayFor(modelItem => item.Genre) </td> <td> @Html.DisplayFor(modelItem => item.Price) </td> <td> @Html.DisplayFor(modelItem => item.Rating ) </td> <td> @Html.ActionLink("Edit Me", "Edit", new { id=item.ID }) | @Html.ActionLink("Details", "Details", new { id=item.ID }) | @Html.ActionLink("Delete", "Delete", new { id=item.ID }) </td> </tr> } </table>Next, open the \Views\Movies\Create.cshtml file and add the following markup near the end of the form. This renders a text box so that you can specify a rating when a new movie is created.
<div class="editor-label"> @Html.LabelFor(model => model.Rating) </div> <div class="editor-field"> @Html.EditorFor(model => model.Rating) @Html.ValidationMessageFor(model => model.Rating) </div>
Managing Model and Database Schema Differences
You've now updated the application code to support the newRating property.Now run the application and navigate to the /Movies URL. When you do this, though, you'll see the following error:
You're seeing this error because the updated
Movie model class in the application is now different than the schema of the Movie table of the existing database. (There's no Rating column in the database table.)By default, when you use Entity Framework Code First to automatically create a database, as you did earlier in this tutorial, Code First adds a table to the database to help track whether the schema of the database is in sync with the model classes it was generated from. If they aren't in sync, the Entity Framework throws an error. This makes it easier to track down issues at development time that you might otherwise only find (by obscure errors) at run time. The sync-checking feature is what causes the error message to be displayed that you just saw.
There are two approaches to resolving the error:
- Have the Entity Framework automatically drop and re-create the
database based on the new model class schema. This approach is very
convenient when doing active development on a test database, because it
allows you to quickly evolve the model and database schema together. The
downside, though, is that you lose existing data in the database — so
you don't want to use this approach on a production database!
- Explicitly modify the schema of the existing database so that it matches the model classes. The advantage of this approach is that you keep your data. You can make this change either manually or by creating a database change script.
Automatically Re-Creating the Database on Model Changes
Let's update the application so that Code First automatically drops and re-creates the database anytime you change the model for the application.
Warning You should enable this approach of
automatically dropping and re-creating the database only when you're
using a development or test database, and never on a production database that contains real data. Using it on a production server can lead to data loss.
In Solution Explorer, right click the Models folder, select Add, and then select Class.Name the class "MovieInitializer". Update the
MovieInitializer class to contain the following code:using System; using System.Collections.Generic; using System.Data.Entity; namespace MvcMovie.Models { public class MovieInitializer : DropCreateDatabaseIfModelChanges<MovieDBContext> { protected override void Seed(MovieDBContext context) { var movies = new List<Movie> { new Movie { Title = "When Harry Met Sally", ReleaseDate=DateTime.Parse("1989-1-11"), Genre="Romantic Comedy", Rating="R", Price=7.99M}, new Movie { Title = "Ghostbusters ", ReleaseDate=DateTime.Parse("1984-3-13"), Genre="Comedy", Rating="R", Price=8.99M}, new Movie { Title = "Ghostbusters 2", ReleaseDate=DateTime.Parse("1986-2-23"), Genre="Comedy", Rating="R", Price=9.99M}, new Movie { Title = "Rio Bravo", ReleaseDate=DateTime.Parse("1959-4-15"), Genre="Western", Rating="R", Price=3.99M}, }; movies.ForEach(d => context.Movies.Add(d)); } } }The
MovieInitializer class specifies that the database
used by the model should be dropped and automatically re-created if the
model classes ever change. The code includes a Seed method
to specify some default data to automatically add to the database any
time it's created (or re-created). This provides a useful way to
populate the database with some sample data, without requiring you to
manually populate it each time you make a model change.Now that you've defined the
MovieInitializer class,
you'll want to wire it up so that each time the application runs, it
checks whether the model classes are different from the schema in the
database. If they are, you can run the initializer to re-create the
database to match the model and then populate the database with the
sample data.Open the Global.asax file that's at the root of the
MvcMovies project:The Global.asax file contains the class that defines the entire application for the project, and contains an
Application_Start event handler that runs when the application first starts.Let's add two using statements to the top of the file. The first references the Entity Framework namespace, and the second references the namespace where our
MovieInitializer class lives:using System.Data.Entity; // Database.SetInitialize using MvcMovie.Models; // MovieInitializerThen find the
Application_Start method and add a call to Database.SetInitializer at the beginning of the method, as shown below:protected void Application_Start() { Database.SetInitializer<MovieDBContext>(new MovieInitializer()); AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); }The
Database.SetInitializer statement you just added indicates that the database used by the MovieDBContext
instance should be automatically deleted and re-created if the schema
and the database don't match. And as you saw, it will also populate the
database with the sample data that's specified in the MovieInitializer class.Close the Global.asax file.
Re-run the application and navigate to the /Movies URL. When the application starts, it detects that the model structure no longer matches the database schema. It automatically re-creates the database to match the new model structure and populates the database with the sample movies:
Click the Create New link to add a new movie. Note that you can add a rating.
Click Create. The new movie, including the rating, now shows up in the movies listing:
In this section you saw how you can modify model objects and keep the database in sync with the changes. You also learned a way to populate a newly created database with sample data so you can try out scenarios. Next, let's look at how you can add richer validation logic to the model classes and enable some business rules to be enforced.
Chapter -7
Adding Validation to the Model (C#)
In this section you'll add validation logic to the
The validation support provided by ASP.NET MVC and Entity Framework Code First is a great example of the DRY principle in action. You can declaratively specify validation rules in one place (in the model class) and then those rules are enforced everywhere in the application.
Let's look at how you can take advantage of this validation support in the movie application.
Open the Movie.cs file. Add a
Now update the
Code First ensures that the validation rules you specify on a model class are enforced before the application saves changes in the database. For example, the code below will throw an exception when the
Here's a complete code listing for the updated Movie.cs file:
Click the Create Movie link to add a new movie. Fill out the form with some invalid values and then click the Create button.

Notice how the form has automatically used a background color to highlight the text boxes that contain invalid data and has emitted an appropriate validation error message next to each one. The error messages match the error strings you specified when you annotated the
A real benefit is that you didn't need to change a single line of code in the
Below is the Create.cshtml view template that you scaffolded earlier in the tutorial. It's used by the action methods shown above both to display the initial form and to redisplay it in the event of an error.
What's really nice about this approach is that neither the controller nor the Create view template knows anything about the actual validation rules being enforced or about the specific error messages displayed. The validation rules and the error strings are specified only in the
If you want to change the validation logic later, you can do so in exactly one place. You won't have to worry about different parts of the application being inconsistent with how the rules are enforced — all validation logic will be defined in one place and used everywhere. This keeps the code very clean, and makes it easy to maintain and evolve. And it means that that you'll be fully honoring the DRY principle.

In the next part of the series, we'll review the application and make some improvements to the automatically generated
Chapter -8
Improving the Details and Delete Methods (C#)
In this part of the tutorial, you'll make some improvements to the automatically generated
Open the
Similarly, change the
The
To sort this out, you can do a couple of things. One is to give the methods different names. That's what we did in he preceding example. However, this introduces a small problem: ASP.NET maps segments of a URL to action methods by name, and if you rename a method, routing normally wouldn't be able to find that method. The solution is what you see in the example, which is to add the
Another way to avoid a problem with methods that have identical names and signatures is to artificially change the signature of the POST method to include an unused parameter. For example, some developers add a parameter type

This basic tutorial got you started making controllers, associating them with views, and passing around hard-coded data. Then you created and designed a data model. Entity Framework Code First created a database from the data model on the fly, and the ASP.NET MVC scaffolding system automatically generated the action methods and views for basic CRUD operations. You then added a search form that let users search the database. You changed the database to include a new column of data, and then updated two pages to create and display this new data. You added validation by marking the data model with attributes from the
Movie
model, and you'll ensure that the validation rules are enforced any
time a user attempts to create or edit a movie using the application.Keeping Things DRY
One of the core design tenets of ASP.NET MVC is DRY ("Don't Repeat Yourself"). ASP.NET MVC encourages you to specify functionality or behavior only once, and then have it be reflected everywhere in an application. This reduces the amount of code you need to write and makes the code you do write much easier to maintain.The validation support provided by ASP.NET MVC and Entity Framework Code First is a great example of the DRY principle in action. You can declaratively specify validation rules in one place (in the model class) and then those rules are enforced everywhere in the application.
Let's look at how you can take advantage of this validation support in the movie application.
Adding Validation Rules to the Movie Model
You'll begin by adding some validation logic to theMovie class. Open the Movie.cs file. Add a
using statement at the top of the file that references the System.ComponentModel.DataAnnotations namespace:using System.ComponentModel.DataAnnotations;The namespace is part of the .NET Framework. It provides a built-in set of validation attributes that you can apply declaratively to any class or property.
Now update the
Movie class to take advantage of the built-in Required, StringLength, and Range validation attributes. Use the following code as an example of where to apply the attributes.public class Movie { public int ID { get; set; } [Required(ErrorMessage = "Title is required")] public string Title { get; set; } [Required(ErrorMessage = "Date is required")] public DateTime ReleaseDate { get; set; } [Required(ErrorMessage = "Genre must be specified")] public string Genre { get; set; } [Required(ErrorMessage = "Price Required")] [Range(1, 100, ErrorMessage = "Price must be between $1 and $100")] public decimal Price { get; set; } [StringLength(5)] public string Rating { get; set; } }The validation attributes specify behavior that you want to enforce on the model properties they are applied to. The
Required attribute indicates that a property must have a value; in this sample, a movie has to have values for the Title, ReleaseDate, Genre, and Price properties in order to be valid. The Range attribute constrains a value to within a specified range. The StringLength attribute lets you set the maximum length of a string property, and optionally its minimum length.Code First ensures that the validation rules you specify on a model class are enforced before the application saves changes in the database. For example, the code below will throw an exception when the
SaveChanges method is called, because several required Movie property values are missing and the price is zero (which is out of the valid range).MovieDBContext db = new MovieDBContext(); Movie movie = new Movie(); movie.Title = "Gone with the Wind"; movie.Price = 0.0M; db.Movies.Add(movie); db.SaveChanges(); // <= Will throw validation exceptionHaving validation rules automatically enforced by the .NET Framework helps make your application more robust. It also ensures that you can't forget to validate something and inadvertently let bad data into the database.
Here's a complete code listing for the updated Movie.cs file:
using System; using System.Data.Entity; using System.ComponentModel.DataAnnotations; namespace MvcMovie.Models { public class Movie { public int ID { get; set; } [Required(ErrorMessage = "Title is required")] public string Title { get; set; } [Required(ErrorMessage = "Date is required")] public DateTime ReleaseDate { get; set; } [Required(ErrorMessage = "Genre must be specified")] public string Genre { get; set; } [Required(ErrorMessage = "Price Required")] [Range(1, 100, ErrorMessage = "Price must be between $1 and $100")] public decimal Price { get; set; } [StringLength(5)] public string Rating { get; set; } } public class MovieDBContext : DbContext { public DbSet<Movie> Movies { get; set; } } }
Validation Error UI in ASP.NET MVC
Re-run the application and navigate to the /Movies URL.Click the Create Movie link to add a new movie. Fill out the form with some invalid values and then click the Create button.
Notice how the form has automatically used a background color to highlight the text boxes that contain invalid data and has emitted an appropriate validation error message next to each one. The error messages match the error strings you specified when you annotated the
Movie class. The errors are enforced both client-side (using JavaScript) and server-side (in case a user has JavaScript disabled).A real benefit is that you didn't need to change a single line of code in the
MoviesController class or in the Create.cshtml
view in order to enable this validation UI. The controller and views
you created earlier in this tutorial automatically picked up the
validation rules that you specified using attributes on the Movie model class.How Validation Occurs in the Create View and Create Action Method
You might wonder how the validation UI was generated without any updates to the code in the controller or views. The next listing shows what theCreate methods in the MovieController class look like. They're unchanged from how you created them earlier in this tutorial.// // GET: /Movies/Create public ActionResult Create() { return View(); } // // POST: /Movies/Create [HttpPost] public ActionResult Create(Movie movie) { if (ModelState.IsValid) { db.Movies.Add(movie); db.SaveChanges(); return RedirectToAction("Index"); } return View(movie); }The first action method displays the initial Create form. The second handles the form post. The second
Create method calls ModelState.IsValid
to check whether the movie has any validation errors. Calling this
method evaluates any validation attributes that have been applied to the
object. If the object has validation errors, the Create method redisplays the form. If there are no errors, the method saves the new movie in the database.Below is the Create.cshtml view template that you scaffolded earlier in the tutorial. It's used by the action methods shown above both to display the initial form and to redisplay it in the event of an error.
@model MvcMovie.Models.Movie @{ ViewBag.Title = "Create"; } <h2> Create</h2> <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> @using (Html.BeginForm()) { @Html.ValidationSummary(true) <fieldset> <legend>Movie</legend> <div class="editor-label"> @Html.LabelFor(model => model.Title) </div> <div class="editor-field"> @Html.EditorFor(model => model.Title) @Html.ValidationMessageFor(model => model.Title) </div> <div class="editor-label"> @Html.LabelFor(model => model.ReleaseDate) </div> <div class="editor-field"> @Html.EditorFor(model => model.ReleaseDate) @Html.ValidationMessageFor(model => model.ReleaseDate) </div> <div class="editor-label"> @Html.LabelFor(model => model.Genre) </div> <div class="editor-field"> @Html.EditorFor(model => model.Genre) @Html.ValidationMessageFor(model => model.Genre) </div> <div class="editor-label"> @Html.LabelFor(model => model.Price) </div> <div class="editor-field"> @Html.EditorFor(model => model.Price) @Html.ValidationMessageFor(model => model.Price) </div> <div class="editor-label"> @Html.LabelFor(model => model.Rating) </div> <div class="editor-field"> @Html.EditorFor(model => model.Rating) @Html.ValidationMessageFor(model => model.Rating) </div> <p> <input type="submit" value="Create" /> </p> </fieldset> } <div> @Html.ActionLink("Back to List", "Index") </div>Notice how the code uses an
Html.EditorFor helper to output the <input> element for each Movie property. Next to this helper is a call to the Html.ValidationMessageFor
helper method. These two helper methods work with the model object
that's passed by the controller to the view (in this case, a Movie object). They automatically look for validation attributes specified on the model and display error messages as appropriate.What's really nice about this approach is that neither the controller nor the Create view template knows anything about the actual validation rules being enforced or about the specific error messages displayed. The validation rules and the error strings are specified only in the
Movie class.If you want to change the validation logic later, you can do so in exactly one place. You won't have to worry about different parts of the application being inconsistent with how the rules are enforced — all validation logic will be defined in one place and used everywhere. This keeps the code very clean, and makes it easy to maintain and evolve. And it means that that you'll be fully honoring the DRY principle.
Adding Formatting to the Movie Model
Open the Movie.cs file. TheSystem.ComponentModel.DataAnnotations namespace provides formatting attributes in addition to the built-in set of validation attributes. You'll apply the DisplayFormat attribute and a DataType enumeration value to the release date and to the price fields. The following code shows the ReleaseDate and Price properties with the appropriate DisplayFormat attribute.[DataType(DataType.Date)] public DateTime ReleaseDate { get; set; } [DataType(DataType.Currency)] public decimal Price { get; set; }Alternatively, you could explicitly set a
DataFormatString
value. The following code shows the release date property with a date
format string (namely, "d"). You'd use this to specify that you don't
want to time as part of the release date.[DisplayFormat(DataFormatString = "{0:d}")] public DateTime ReleaseDate { get; set; }The following code formats the
Price property as currency.[DisplayFormat(DataFormatString = "{0:c}")] public decimal Price { get; set; }The complete
Movie class is shown below.public class Movie { public int ID { get; set; } [Required(ErrorMessage = "Title is required")] public string Title { get; set; } [Required(ErrorMessage = "Date is required")] [DisplayFormat(DataFormatString = "{0:d}")] public DateTime ReleaseDate { get; set; } [Required(ErrorMessage = "Genre must be specified")] public string Genre { get; set; } [Required(ErrorMessage = "Price Required")] [Range(1, 100, ErrorMessage = "Price must be between $1 and $100")] [DisplayFormat(DataFormatString = "{0:c}")] public decimal Price { get; set; } [StringLength(5)] public string Rating { get; set; } }Run the application and browse to the
Movies controller.In the next part of the series, we'll review the application and make some improvements to the automatically generated
Details and Delete methods.Chapter -8
Improving the Details and Delete Methods (C#)
In this part of the tutorial, you'll make some improvements to the automatically generated
Details and Delete methods. These changes aren't required, but with just a few small bits of code, you can easily enhance the application.Improving the Details and Delete Methods
When you scaffolded theMovie controller, ASP.NET MVC generated code that worked great, but that can be made more robust with just a few small changes.Open the
Movie controller and modify the Details method by returning HttpNotFound when a movie isn't found. You should also modify the Details method to set a default value for the ID that's passed to it. (You made similar changes to the Edit method in part 6 of this tutorial.) However, you must change the return type of the Details method from ViewResult to ActionResult, because the HttpNotFound method doesn't return a ViewResult object. The following example shows the modified Details method.public ActionResult Details(int id = 0) { Movie movie = db.Movies.Find(id); if (movie == null) { return HttpNotFound(); } return View(movie); }Code First makes it easy to search for data using the
Find method. An important security feature that we built into the method is that the code verifies that the Find
method has found a movie before the code tries to do anything with it.
For example, a hacker could introduce errors into the site by changing
the URL created by the links from http://localhost:xxxx/Movies/Details/1 to something like http://localhost:xxxx/Movies/Details/12345
(or some other value that doesn't represent an actual movie). If you
don't the check for a null movie, this could result in a database error.Similarly, change the
Delete and DeleteConfirmed methods to specify a default value for the ID parameter and to return HttpNotFound when a movie isn't found. The updated Delete methods in the Movie controller are shown below.// GET: /Movies/Delete/5 public ActionResult Delete(int id = 0) { Movie movie = db.Movies.Find(id); if (movie == null) { return HttpNotFound(); } return View(movie); } // // POST: /Movies/Delete/5 [HttpPost, ActionName("Delete")] public ActionResult DeleteConfirmed(int id = 0) { Movie movie = db.Movies.Find(id); if (movie == null) { return HttpNotFound(); } db.Movies.Remove(movie); db.SaveChanges(); return RedirectToAction("Index"); }Note that the
Delete method doesn't delete the data.
Performing a delete operation in response to a GET request (or for that
matter, performing an edit operation, create operation, or any other
operation that changes data) opens up a security hole. For more
information about this, see Stephen Walther's blog entry ASP.NET MVC Tip #46 — Don't use Delete Links because they create Security Holes. The
HttpPost method that deletes the data is named DeleteConfirmed to give the HTTP POST method a unique signature or name. The two method signatures are shown below:// GET: /Movies/Delete/5 public ActionResult Delete(int id = 0) // // POST: /Movies/Delete/5 [HttpPost, ActionName("Delete")] public ActionResult DeleteConfirmed(int id = 0)The common language runtime (CLR) requires overloaded methods to have a unique signature (same name, different list of parameters). However, here you need two Delete methods -- one for GET and one for POST -- that both require the same signature. (They both need to accept a single integer as a parameter.)
To sort this out, you can do a couple of things. One is to give the methods different names. That's what we did in he preceding example. However, this introduces a small problem: ASP.NET maps segments of a URL to action methods by name, and if you rename a method, routing normally wouldn't be able to find that method. The solution is what you see in the example, which is to add the
ActionName("Delete") attribute to the DeleteConfirmed method. This effectively performs mapping for the routing system so that a URL that includes /Delete/ for a POST request will find the DeleteConfirmed method.Another way to avoid a problem with methods that have identical names and signatures is to artificially change the signature of the POST method to include an unused parameter. For example, some developers add a parameter type
FormCollection that is passed to the POST method, and then simply don't use the parameter:public ActionResult Delete(FormCollection fcNotUsed, int id = 0) { Movie movie = db.Movies.Find(id); if (movie == null) { return HttpNotFound(); } db.Movies.Remove(movie); db.SaveChanges(); return RedirectToAction("Index"); }
Wrapping Up
You now have a complete ASP.NET MVC application that stores data in a SQL Server Compact database. You can create, read, update, delete, and search for movies.This basic tutorial got you started making controllers, associating them with views, and passing around hard-coded data. Then you created and designed a data model. Entity Framework Code First created a database from the data model on the fly, and the ASP.NET MVC scaffolding system automatically generated the action methods and views for basic CRUD operations. You then added a search form that let users search the database. You changed the database to include a new column of data, and then updated two pages to create and display this new data. You added validation by marking the data model with attributes from the
DataAnnotations namespace. The resulting validation runs on the client and on the server.
Subscribe to:
Posts (Atom)