一. MVC简介
1.MVC是ASP.NET WebForm之外另一种WEB应用程序的开发方式.设计模式为Model-View-Controller.
1.1 Model 模型
操作资料或处理资料逻辑.
1.2 View 视图
用户介面.
1.3 Controllerr 控制器
控制应用程序流程,并指定要呈现的View或存取哪个Model.
2. MVC架构的主要优点
2.1 主要分为M-V-C三个部分,使用项目更方便管理与维护.
2.2 MVC不使用ViewState和服务器控件,所以执行速度较快,所耗费的流量也相对小.
2.3 支持测试导向开发工作,要同时建立测试方案,为单元的每一个动作生成测试代码进行测试工作.
3.MVC的运行模式
3.1 用户通过浏览器发送请求(Request)
3.2 应用服务器收到请求后,与MVC的Rounting进行比对,执行对应的控制器(Controller)的动作(Action).
3.3 控制器通过Model存取数据.
3.4 控制器将结果传递给指定的View并呈现给用户.
二. 建立一个CRUD的MVC例子
-
新建项目
-
加入数据库及表
2.1 在APP_Data 目录右击加入新项目SQL Server Database
文件在APP_Data目录下
甲、 右击[Tables]增加新表[Update]
- 通过ENTITY FRAMEWORK 加入模型
右击Models加入新项目ADO.NET Entity Data ModelEF Designer from database加入对应的表\项目\存储过程
- 数据读取,建立控件器Controller,增加新增,查询列表,修改,删除Action.
// GET: Home (查询列表,带分页控件PagedList.)
public ActionResult Index(int page =1)
{
int pagesize = 3;
int pagecur = page < 1 ? 1 : page;
var tToDo = dbentity.tToDoes.OrderByDescending(o => o.fDate).ToList().ToPagedList(pagecur,pagesize);
return View(tToDo);
}
//-------新增 的代码开始
//显示新增的页面-------------------------------------
public ActionResult Create()
{
return View();
}
[HttpPost] //注:参数变量的名称与前端控件的名称一致,会自动对应.
public ActionResult Create(String fTitle, string fImage, DateTime fDate)
{
tToDo todo = new tToDo();
todo.fTitle = fTitle;
todo.fImage = fImage;
todo.fDate = fDate;
dbentity.tToDoes.Add(todo);
dbentity.SaveChanges();
return RedirectToAction("Index");
}
[HttpPost] //前端的控件为 @Html.EditFor (Model的属性名),会自动对应.
public ActionResult Create(tToDo todo)
{
dbentity.tToDoes.Add(todo);
dbentity.SaveChanges();
return RedirectToAction("Index");
}
[HttpGet] //用Ajax Get 的方式把数据从前端传过来.
public string CreateInAjax(string data)
{
try
{
dynamic obj = JsonConvert.DeserializeObject<dynamic>(data);
tToDo todo = new tToDo();
todo.fTitle = obj.fTitle;
todo.fImage = obj.fImage;
todo.fDate = obj.fDate;
dbentity.tToDoes.Add(todo);
dbentity.SaveChanges();
return "Save.";
}
catch
{
return "Fail to save.";
}
}
[HttpPost] //用Ajax Post 的方式把数据从前端传过来.
public string CreateInAjaxPost(string data)
{
try
{
dynamic obj = JsonConvert.DeserializeObject<dynamic>(data);
tToDo todo = new tToDo();
todo.fTitle = obj.fTitle;
todo.fImage = obj.fImage;
todo.fDate = obj.fDate;
dbentity.tToDoes.Add(todo);
dbentity.SaveChanges();
return "Save.";
}
catch
{
return "Fail to save.";
}
//-------新增 的代码结束
//显示修改的页面
public ActionResult Edit(int id)
{
var todo = dbentity.tToDoes.Where(o => o.Id == id).FirstOrDefault();
return View(todo);
}
//保存修改
[HttpPost]
public ActionResult Edit(int id,string fTitle,string fImage,DateTime fDate)
{
var todo = dbentity.tToDoes.Where(o => o.Id == id).FirstOrDefault();
todo.fTitle = fTitle;
todo.fImage = fImage;
todo.fDate = fDate;
dbentity.SaveChanges();
return RedirectToAction("Index");
}
//删除
public ActionResult Delete(int id)
{
var todo = dbentity.tToDoes.Where(o => o.Id == id).FirstOrDefault();
dbentity.tToDoes.Remove(todo);
dbentity.SaveChanges();
return RedirectToAction("Index");
}
}
- 数据新增VIEW
@model prjMVC20210420.Models.tToDo
@{
ViewBag.Title = "Create To do list";
}
<script>
function SaveData() { //Ajax Get
var data = '{ fTitle: "How to learn MVC", fImage: "1.png", fDate: "2025-05-06" }';
$.ajax(
{
url: "http://localhost:63534/Home/CreateInAjax?data=" + data,
type: 'GET',
success: function (data) {
alert(data);
location.href = "http://localhost:63534/Home/Index";
}
}
);
}
function SaveDataPost() { //Ajax Post
var data = 'data={ fTitle: "How to learn MVC", fImage: "1.png", fDate: "2025-05-06" }';
$.ajax(
{
url: "http://localhost:63534/Home/CreateInAjaxPost",
data:data,
type: 'POST',
dataType:'text',
success: function (data) {
alert(data);
location.href = "http://localhost:63534/Home/Index";
}
}
);
}
</script>
<h2>Create to do list</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>tToDo</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
<label class="control-label col-md-2">Title</label>
<div class="col-md-10">
@Html.EditorFor(model => model.fTitle, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.fTitle, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" >Image</label>
<div class="col-md-10">
<select id="fImage" name="fImage" class="form-control">
<option value="0.png">Important</option>
<option value="1.png">Common</option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2">Date</label>
<div class="col-md-10">
@Html.EditorFor(model => model.fDate, new { htmlAttributes = new { @class = "form-control"
,type="date",required="required"} })
@Html.ValidationMessageFor(model => model.fDate, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
<input type="button" value="Ajax Submit" onclick="SaveDataPost();" class="btn btn-danger " />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
- 数据查询列表, 删除 VIEW
@using PagedList.Mvc; <!--引入分页控件-->
@using PagedList;
@model IPagedList<prjMVC20210420.Models.tToDo>
@{
ViewBag.Title = "Index";
}
<link href="~/Content/PagedList.css" rel="stylesheet" />
<p>
@Html.ActionLink("Create New", "Create") <!--到新增页面-->
</p>
<table class="table">
<tr> <th> Title </th> <th> Image </th> <th> Date </th> <th></th> </tr>
@foreach (var item in Model)
{
<tr>
<td>
@item.fTitle
</td>
<td>
@item.fImage
</td>
<td>
@item.fDate
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id = @item.Id }) |
@Html.ActionLink("Delete", "Delete", new { id = @item.Id })
</td>
</tr>
}
</table>
@Html.PagedListPager(Model, page => Url.Action("Index", new { page })) <!--分页-->
7.数据修改VIEW
@model prjMVC20210420.Models.tToDo
@{
ViewBag.Title = "Edit to do list";
}
<h2>Edit to do list</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.Id)
<div class="form-group">
<label class="control-label col-md-2">Title</label>
<div class="col-md-10">
@Html.EditorFor(model => model.fTitle, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.fTitle, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2">Image</label>
<div class="col-md-10">
<select id="fImage" name="fImage" class="form-control">
<option value="0.png" @(Model.fImage =="0.png" ? "selected" : "")>Important</option>
<option value="1.png" @(Model.fImage=="1.png" ? "selected" : "")>Common</option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2">Date</label>
<div class="col-md-10">
@Html.EditorFor(model => model.fDate, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.fDate, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
三. 控制器 Controller介绍
控制器是MVC Web应用程序的核心内容之一. 一个控制器中包含多个公开(public)的动作(action),这些公开的动作对应于指定的url,透过这些动作与用户操作进行互动,对model资料进行逻辑处理后返回view给用户.
一个Controller的例子:
public class HomeController : Controller
{
DbEntities dbentity = new DbEntities();
// GET: Home
public ActionResult Index()
{
var tToDo = dbentity.tToDoes.OrderByDescending(o => o.fDate).ToList();
return View(tToDo);
}
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(String fTitle, string fImage, DateTime fDate)
{
tToDo todo = new tToDo();
todo.fTitle = fTitle;
todo.fImage = fImage;
todo.fDate = fDate;
dbentity.tToDoes.Add(todo);
dbentity.SaveChanges();
return RedirectToAction("Index");
}
public ActionResult Delete(int id)
{
var todo = dbentity.tToDoes.Where(o => o.Id == id).FirstOrDefault();
dbentity.tToDoes.Remove(todo);
dbentity.SaveChanges();
return RedirectToAction("Index");
}
public ActionResult Edit(int id)
{
var todo = dbentity.tToDoes.Where(o => o.Id == id).FirstOrDefault();
return View(todo);
}
[HttpPost]
public ActionResult Edit(int id,string fTitle,string fImage,DateTime fDate)
{
var todo = dbentity.tToDoes.Where(o => o.Id == id).FirstOrDefault();
todo.fTitle = fTitle;
todo.fImage = fImage;
todo.fDate = fDate;
dbentity.SaveChanges();
RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
dbentity.Dispose();
}
base.Dispose(disposing);
}
}
(一)注意控制器的写法:
1. 控制器的类别必须是Public.
2. 控制器的名称必须是Controller结尾.例如HomeController…
3. 控制器类别必须继承Controller,或是实例化IController接口
4. Action方法必须是Public才能被前端呼叫执行,否则为一般方法.
(二)控制器主要负责:
1. 找出要执行的动作并验证执行;
2. 取得动作方法的参数;
3. 处理执行期间发生的错误;
4. 向用户返回view.
(三)action动作
1.常用action方法
例如:http://webname/Home/Index
对应HomeController的Index 方法
Public class HomeController:Controller
{
Public ActionResult Index()
{
……
}
}
也可以:
[ActionName(“Index”)]
Public ActionResult Show()
{
…
}
如果加入[NonAction],则会被当作一般的方法
[NonAction]
Public ActionResult Index()
{}
2.Action 的附加属性
常用的附加属性有
属性名称 说明
HttpGet 用户端使用GET方法向服务器发送请求.SELECT
HttpPost 用户端使用POST方法向服务器发送请求.Insert
HttpDelete 请求服务器删除资料.DELETE
HttpPut 请求服务器更新,新增 资料.INSERT ,UPDATE
客户端使用GET的方法是以QUERYSTRING的方式将数据加在URL后面向服务器请求,此种方法安全性低且数据有长度限制,例如:
http://website/Home/Show?index=1&name=’Jacky’
对应于以下Controller Show
Public class HomeController:Controller
{
[HttpGet] //注:预设为GET,所以可以省略不写
Public ActionResult Show(int index,string name)
{
…
}
}
客户端使用POST的方法是将资料放在数据主体内(request body)进行传输,经常配合表单使用,相比较为安全且没有长度限制.例如:
前端:
<form method = “post” action=”Home/Create”>
<p>Company<input type =”text” name=”Company” id = “txtCompany”></p>
<p>Address<input type=”text” name =”Address” id=”txtAddress”></p>
<p><input type=”submit” value=”Save”></p>
</form>
//注意:的name 是表单的字段,与后台对应.Id 属性由前端js交互使用.
后台Controller:
Public class HomeController:Controller
{
[HttpPost]
Public ActionResult Create(string Company,string Address) //对应页面的控件 name
{ }
}
}
再举一个粟子:
Public class HomeController:Controller
{
[HttpPost]
Public ActionResult Create(string Company,string Address) //对应页面的控件 name
{ }
}
public string ShowArray()
{
int[] arrScore = { 10, 65, 98, 45, 73 };
string rtnString = "";
arrScore.ToList().ForEach(o =>
{
rtnString += "," + o.ToString();
});
rtnString += "<br />";
rtnString += "Total:" + arrScore.Sum().ToString();
return rtnString;
}
}
http://website/Home/ShowArray
(四) ViewData , ViewBag , TempData 的使用.从服务器Controller传输资料到View.适合少量的数据传递.
1. ViewData : 继承自Dictionary类别,以键/值的方式存取资料
ViewData的只在当前当前的请求中有效,生命周期和View相同,其值不能在多个请求中共享。
ViewBag和ViewData存储的值的生命周期只有在从Controller到View中
在重定向(redirection)后,ViewData中存储的变量值将变为null。
在取出ViewData中的变量值是,必须进行合适的类型转换(隐式或显式)和空值检查
Eg:
Code:
Public class HomeController:Controller
{
Public ActionResult Index()
{
ViewData[“Company”] = “ETS company”;
return View();
}
}
Cshtml Page:
<div>
<h1>@ViewData[“Company”]</h1> /* ETS company */
</div>
2.ViewBag: 使用dynamic类型,当然速度和损耗上比ViewData差.
使用:
Code:
ViewBag.Company = “ETS company”;
CSHTML PAGE:
@ViewBag.Company
**3.TempData:**与ViewData一样也是属于Dictionay类型.但是TempData是将资料存储在Session中,它的生命周期默认是一个请求(Request), 並將在訪問資料的第一個請求結束時自動刪除。如果從未讀過,它將一直保留到最後讀取或會話超時。通过TempData ,可以将资料跨不同Controller 和Action方法并传递到View.
儲存到 TempData 的資料儲存在會話中,
Eg1:
public ActionResult Index()
{
TempData["tempdata"] = "this is a test";
var tToDo = dbentity.tToDoes.OrderByDescending(o => o.fDate).ToList();
return View(tToDo);
}
public string GetTempData()
{
var tempStr = TempData["tempdata"].ToString();//第二次访问时会报null object错误
return tempStr;
}
Eg2:
CODE:
public ActionResult DisplayCustomer1()
{
Customer customer = new Customer
{
Id = 1001,
Code = "100101",
Amount = 100
};
TempData["OneCustomer"] = customer;
return RedirectToAction("DisplayCustomer2");
}
public ActionResult DisplayCustomer2()
{
Customer customer = TempData["OneCustomer"] as Customer;
return View(customer);
}
Page:
如果要将TempData的资料持久化,可以使用keep或peek的方法
例子:keep
public class TempDataController : Controller
{
public ActionResult Index()
{
TempData["cnblogs"] = "xpy0928";
TempData.Keep();
return View();
}
public ActionResult GetTemData()
{
var blogName = TempData["cnblogs"].ToString();
TempData.Keep("cnblogs");
return View();
}
}
例子: Peek,你可以檢索儲存在 TempData 中的資料,而不會將其標記為刪除,因此將來的請求仍然可以使用資料
//first request, save value to TempData
TempData["value"] = "someValueForNextRequest";
//second request, PEEK value so it is not deleted at the end of the request
object value = TempData.Peek("value");
//third request, read value and mark it for deletion
object value = TempData["value"];
总结:
1)当利用TempData对象存储值而未调用TempData.Keep方法时,此时只要该对象被已读,然后该对象中的所有项将被标记为删除状态。
(2)若调用TempData.Keep(string key)方法,此时不会进行标记删除。
(3)RedirectToRouteResult和RedirectResult总是会调用TempData.Keep()方法,保证该对象中的所有项不会被移除。
4.Session
• Session也是ASP.NET MVC程序传递值的一种方式,在用户的整个会话中Session都不会过期。
• Session在同一用户会话过程中的所有请求中有效,比如,刷新页面。
• Session中的值也需要进行类型转换(隐式或显式)和非空检查。
• Session的生命周期是最长的,但是它默认使用的是Cookies来存储数据,所以使用的时候必须注意数据保密的问题。Session主要用在需要在多个Controllers, Actions and Views共享数据(非敏感数据)时使用。
Eg:
public ActionResult DisplayCustomer1()
{
Customer customer = new Customer
{
Id = 1001,
Code = "100101",
Amount = 100
};
Session["OneCustomer"] = customer;
return RedirectToAction("DisplayCustomer2");
}
public ActionResult DisplayCustomer2()
{
Customer customer = Session["OneCustomer"] as Customer;
return View(customer);
}
总结,各种传递方式
ViewData / ViewBag TempData Session
Controller to Controller NO YES YES
Controller to View YES YES YES
View to Controller NO NO YES
(五) 模型关联
MVC可以使用模型关联的方式来取得用户端的资料.
1. 简单模型关联
前端:
<form method = “post” action=”Home/Create”>
<p>Company<input type =”text” name=”Company” id = “txtCompany”></p>
<p>Address<input type=”text” name =”Address” id=”txtAddress”></p>
<p><input type=”submit” value=”Save”></p>
</form>
//注意:的name 是表单的字段,与后台对应.Id 属性由前端js交互使用.
后台Controller:
Public class HomeController:Controller
{
[HttpPost]
Public ActionResult Create(string Company,string Address) //对应页面的控件 name
tCompany tcompany = new tCompany();
tcompany. Company = Company;
tcompany. Address = Address;
db. tCompany.Add(todo);
db.SaveChanges();
return RedirectToAction("Index");
}
}
2.复杂模型关联
前端:
<form method = “post” action=”Home/Create”>
<p>Company<input type =”text” name=”Company” id = “txtCompany”></p>
<p>Address<input type=”text” name =”Address” id=”txtAddress”></p>
<p><input type=”submit” value=”Save”></p>
</form>
//注意:的name 是表单的字段,与后台对应.Id 属性由前端js交互使用.
后台:
- Company.cs模型
Public class Company
{
Public string Company{get;set;}
Public string Address{get;set;}
}
2) Controller:
Public class HomeController:Controller
{
[HttpPost]
Public ActionResult Create(Company company)
{
db. tCompany.Add(company);
db.SaveChanges();
return RedirectToAction("Index");
}
}
(六) ActionResult 类型
ActionResult(基类) Helper方法 说明
1.ViewResult View Reurn view web page
Eg:
Public class HomeController :Controller
Public ViewResult Index()
{
Reurn View();//return View Page
Return View(db.Company.ToList());//return View with list
Return View(“About”);
Return View(“About”,db.Company.ToList());
}
2.PartialViewResult PartialView 返回部分视图,可放在其它视图的指定位置
3.RedirectResult Redirect 使用url的方式重新导向到其它动作方法
Public RedirectResult Index()
{
Return Redirect(“~/Home/Login”) //redirect to home login action
Return Redirect(“http://.....”)
}
4.RedirectToRouteResult RedirectToAction
5.RedirectToRoute 重新定向到其它动作方法
Public RedirectToRouteResult Index()
{
Return RedirectToAction(“Login”);
Return RedirectToAction(“Page”,new {index=1});//Redirect to Home/Page?index=1
Return RedirectToAction(“Page”,”Default”,new {index=1});//Default is router name
}
6.ContentResult Content 传回用户自定义的内容型别
7.JsonResult Json Return json object
Public JsonResult Index()
{
Company company = new Company();
company.Company = “ETL”;
company.Address = “HK”;
return Json(company,JsonRequestBehavior.AllowGet); //retrun json string {“Company”:”ETL”,”Address”:”HK”}
}
8.JavaScriptResult JavaScript Return javascript script
Public JavaScriptResult Index()
{
String myConfirm = “confirm(‘delete?’)”;
Return JavaScript(myConfirm);
}
9.FileResult File Return binary stream
Front page:
<body>
<form method="post" action="@Url.Action("PostFILE")" enctype="multipart/form-data">
<div>
<p>file1:<input type="file" name="files" id="jfiles" /></p>
<p>file2:<input type="file" name="files" id="jfiles" /></p>
<input type="submit" value="Save" />
</div>
</form>
</body>
后臺Code:
public ActionResult PostFile()
{
return View();
}
[HttpPost]
public ActionResult PostFile(HttpPostedFileBase[] files)
{
string fname = "";
foreach (var file in files)
{
if (files != null)
{
fname = file.FileName.Substring(file.FileName.LastIndexOf("\\") + 1);
file.SaveAs(Server.MapPath("~/TempFiles") + "\\" + fname);
}
}
return RedirectToAction("ShowFile");
}
public string ShowFile()
{
string rtnStr = "";
DirectoryInfo dir = new DirectoryInfo(Server.MapPath("~/TempFiles"));
FileInfo[] fileInfo = dir.GetFiles();
foreach (var file in fileInfo)
{
rtnStr += file.FullName + "<br />";
}
return rtnStr;
}
10.EmptyResult Return null
四. View视图
view负责资料显示,主要由HTML语法构建. .Net提供了HTML Helper 和 Razor可以更方便构建View.
可以从 Controller 的 Action 中快速生成view
1. 使用 Razor
Razor是专门为asp.net web应用程序而设计的语言,是写在客户端页面但执行在服务器端的. 以@开头
例如:
@DateTime.Now
显示当前时间1.1 注解
@* 注解的内容 *@
1.2 C#程序段落
@{
程序代码...
}
Eg:
@{
String name = “Jacky”;
@: My name is @name //@: 输出;@变量名
}
@*Razor使用 if 语句*@
@if(ViewBag.IsLogin) {
<span> Login </span> // or @:Login
}
Else
{<span> Un Login </span>
}
@*要注意:以下这样写是错误的,因为Razor会认为 Login ,UnLogin是后台c#语句*@
@if(ViewBag.IsLogin) {
Login
}
Else
{
Un Login
}
@*Razor使用 for or foreach*@
@*Eg:*@
@{
String[] names = {“Jacky”,”Mandy”,”Weny”};
}
<ul>
@foreach(var item in names)
{
<li>
@item
</li>
}
</ul>
@*Or for*@
<ul>
@for(int i=p;i< names.Length;i++)
{
<li>
@names[i]
</li>
}
</ul>
2. 使用 HTML Helper
在前端页面中可以使用 html helper快速生成html标签,它与HTML标签是可以共存的.
3. 强类型HTML Helper的使用
与一般的HTML Helper不同 ,强类型主要是为了避免程序中有无效的资料使用存在,它可以与Model模型的属性进行关联.
Eg:
前端View page 代码
@model db.Models.User
@Html.TextBoxFor(model => model.UserName,new {@class=”form-control”,placeholder=”please input user name”})
注意:
1. 需和model搭配,@model必须有明确的类别
2. 控件与model类别的属性进行关联,Html Helper产生的控件id,name名称与model类别的属性名称一样.
3. 可以指定控件的属性,例如 css
优点:
1. 执行速度快.
2. 容易除错.
3. 有intellisense辅助,代码编写速度更快.
@model prjMVC20210420.Models.MemberShip
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>MemberShip</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Account, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.Account, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Account, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Pwd, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.PasswordFor(model => model.Pwd, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Pwd, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.Email, new { @class = "form-control",type="email" })
@Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.BirthDay, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.BirthDay, new { @class = "form-control" ,type="date" })
@Html.ValidationMessageFor(model => model.BirthDay, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
4. @helper辅助方法的使用
Razor可以在View中创建函数使用.
Eg:
@helper AvgScore(int math,int eng)
{
Int avg = (math + eng)/2;
@:avg
}
<p>Jacky’s avg score:@ AvgScore(80,90)</p>
<p>Linda’s avg score:@AvgScore(75,93)</p>
5. 一对多的资料表查询
我们经常会用到,从Controller返回的data是几个表的联接而成的数据,而不仅仅是某个指定的Model.
第一 种方法:可以使用ViewModel,即将N个Model合并为一个VIEW.
Eg:
Pulic class tDeptment //department model
{
Public int DeptId {set ;get;}
Public string DeptName {set;get;}
}
Public class tEmployee //employee model
{
Public int EmpId {set ;get}
Public string EmpName {set ;get;}
Public int DeptId {set;get;}
}
新建一个ViewModel ,包含上述两个model
Public class VwDeptEmp
{
Public List<tDeptment> department {set;get;}
Public List<tEmployee> employee{get;set;}
}
Controller:
Public ActionResult Index(int deptId = 1)
{
VwDeptEmp vm = {
department = db.tDeptment.where(o=>o.DeptId == deptId).ToList(),
employee = db.tEmployee.where(o=>o.DeptId == deptId).ToList()
};
Return View(vm);
}
Cshtml
@model prjName.Models. VwDeptEmp
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.employee.EmpName</td>
<td>@Html.DisplayFor(modelItem => item. department. DeptName </td>
</tr>
}
第二种方法: 如果表之间(Model之间)存在外键关联,例如上述两个model存在deptId 关联,则可以使用 inclue
Eg:
Controller:
Public ActionResult Index(int deptId = 1)
{
Var emp = db. tEmployee
.Include(p=>p.tDeptment);
Return View(emp);
}
第三种: 当然也可以使用dynamic 传给VIEW一个动态松散型的结果(当然,这回到了弱类型的开发方式,个人并不推荐)
Eg. (注:未作实际测试)
Controller:
Public ActionResult Index(int deptId = 1)
{ //
ViewBag.employee = db. tEmployee.Where (o=>o.DeptId==deptId).GroupJoin(db.tDeptMent,
item1=>item1.DeptId,
item2=>item2.DeptId,
(item1,item2)=>new {
EmpId = item1.EmpId,
EmpName = item1.EmpName,
DeptName = item2.DeptName.FirstOrNull()
}).ToList();
Return View();
}
Cshtml
@foreach (var item in ViewBag.employee as List<dynamic>)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.EmpName</td>
<td>@Html.DisplayFor(modelItem => item. DeptName </td>
</tr>
}
第四種:使用 dynamic sampleObject = new ExpandoObject(); 將model 作為dynamic 變量的屬性
Controller:
public ActionResult Index()
{
dynamic rtnData = new ExpandoObject();
rtnData.tCRUD = dbEnti.tCRUDs.ToList(); //第1個model
rtnData.tProj = dbEnti.Projects.ToList(); //第2個model
return View(“vProjectIndex”, “_Layout”, rtnData );
}
View:vProjectIndex
@*@foreach (var item in new List<prjMVC.Models.Project>(Model.tProj)) *@
@foreach (prjMVC.Models.Project item in Model.tProj)
{
@Html.DisplayFor(modelItem => item.ProjectNo)
@Html.DisplayFor(modelItem => item.ProjectDesc)
}
6. View index 资料列表的分页显示
GuGet安装控件 PagedList.Mvc
Eg:
View:
@using PagedList.Mvc;
@using PagedList;
@model IPagedList<prjMVC20210420.Models.tToDo>
@{
ViewBag.Title = "Index";
}
<link href="~/Content/PagedList.css" rel="stylesheet" />
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
Title
</th>
<th>
Image
</th>
<th>
Date
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@item.fTitle
</td>
<td>
@item.fImage
</td>
<td>
@item.fDate
</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>
@Html.PagedListPager(Model, page => Url.Action("Index", new { page }))
Controller code:
using PagedList.Mvc;
using PagedList;
namespace prjMVC20210420.Controllers
{
public class HomeController : Controller
{
DbEntities dbentity = new DbEntities();
// GET: Home
public ActionResult Index(int page =1)
{
int pagesize = 3;
int pagecur = page < 1 ? 1 : page;
var tToDo = dbentity.tToDoes.OrderByDescending(o => o.fDate).ToList().ToPagedList(pagecur,pagesize);
return View(tToDo);
}
}
}
7. 使用 Bootstrap 美化网页(http://getbootstrap.com)
Bootstrap base on HTML,Javascript,CSS的一套前端网页框架套件.提供各种常用页面控件,自适应各种设备屏幕长宽度显示等.
以下是_Layout.cshtml
8. MVC 前端VIEW的数据檢查
對于HTML5 頁面,在頁面Submit前會自動進相應的控件進行數據檢查.
Eg:
@Html.TextBoxFor(model => model.BirthDay, new { @class = "form-control" ,type="date",required = “required” placeholder=”please input birth day” })
Type: type = date ,email,url,number,range,time,required=”required” etc.
9. Ajax簡單介紹
(Asynchronous Javascript and XML)是一種瀏覽器端的技術,可以不刷新整個頁面的方式與服務器進行數據交換并進行頁面(或頁面部分)刷新.
例子1: Get 方式
前端 JS
<script>
function SaveData() {
var data = '{ fTitle: "How to learn MVC", fImage: "1.png", fDate: "2025-05-06" }';
$.ajax(
{
url: "http://localhost:63534/Home/CreateInAjax?data=" + data,
type: 'GET',
success: function (data) {
alert(data);
location.href = "http://localhost:63534/Home/Index";
}
}
);
}
</script>
后臺 Controller code:
public string CreateInAjax(string data)
{
try
{ //insert a new record.
dynamic obj = JsonConvert.DeserializeObject(data);
tToDo todo = new tToDo();
todo.fTitle = obj.fTitle;
todo.fImage = obj.fImage;
todo.fDate = obj.fDate;
dbentity.tToDoes.Add(todo);
dbentity.SaveChanges();
return “Save.”;
}
catch
{
return “Fail to save.”;
}
}
例子2:POST 方式
前端 JS
function SaveDataPost() {
var data = 'data={ fTitle: "How to learn MVC", fImage: "1.png", fDate: "2025-05-06" }';
$.ajax(
{
url: "http://localhost:63534/Home/CreateInAjaxPost",
data:data,
type: 'POST',
dataType:'text',
success: function (data) {
alert(data);
location.href = "http://localhost:63534/Home/Index";
}
}
);
}
后臺 Controller code:
[HttpPost]
public string CreateInAjaxPost(string data)
{
try
{
dynamic obj = JsonConvert.DeserializeObject(data);
tToDo todo = new tToDo();
todo.fTitle = obj.fTitle;
todo.fImage = obj.fImage;
todo.fDate = obj.fDate;
dbentity.tToDoes.Add(todo);
dbentity.SaveChanges();
return “Save.”;
}
catch
{
return “Fail to save.”;
}
}
10. Web API
ASP.NET Web API 可以創建RESTful應用(提供Get/PUT),提供跨平臺的HTTP服務給用戶端瀏覽器及手機移動等設備使用.相對于web service ,WCF,WEB API在提供的數據格式,數據大小,部署方式方面更具有優勢.
Eg:一個WEB API Controller的例子
Public class DefaultController:ApiController
{
// GET: api/ContextTable/5
[WebApiNew.Helper.JWTFilter]
[HttpGet]
public IEnumerable<dynamic> GetList(string paramStr)
{
var paramDyn = System.Web.Helpers.Json.Decode(paramStr);
using (WorkTempEntities wkTmpEnti = new WorkTempEntities())
{
var query = wkTmpEnti.ContextTables.AsEnumerable();//.Where (o=> true);
string title = paramDyn["Title"];
if (!string.IsNullOrEmpty(title))
{
query = query.Where(o => o.Title.Contains(title));
}
string addTimeFrom = paramDyn["AddTimeFrom"];
DateTime dtFrom;
if (!string.IsNullOrEmpty(addTimeFrom) && DateTime.TryParse(addTimeFrom, out dtFrom))
{
query = query.Where(o => o.AddTime >= dtFrom);
}
return query.ToList();
}
}}
<待續>