MVC5学习笔记,其实就是敲了一遍官网代码,官网地址:http://www.asp.net/mvc
接着上一篇 MVC5学习系列——从控制器访问模型的数据(添加、修改、删除),这次我们详细说一下编辑操作,不过在这之前先修改一下列表页面。先将页面中的英文处理掉,还有就是如果你创建了一个不是空的MVC程序,那么程序中默认集成了Bootstrap ,这里我们也自己动手添加Bootstrap 样式。按照自动生成的MVC非空程序模板,我们也把样式文件放到根目录的Content文件夹中。
看一下修改之后的Index.cshtml页面:
@model IEnumerable<DDZ.MVC5Test.Models.Movie>
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>我的电影</title>
<link href="~/Content/Bootstrap/3.3.6/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<div class="container">
<p>
@Html.ActionLink("添加电影", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
<th>
@Html.DisplayNameFor(model => model.ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.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", new { id = item.ID }) |
@Html.ActionLink("详情", "Details", new { id = item.ID }) |
@Html.ActionLink("删除", "Delete", new { id = item.ID })
</td>
</tr>
}
</table>
</div>
</body>
</html>
还有修改之后的Edit.cshtml页面:
@model DDZ.MVC5Test.Models.Movie
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>我的电影—编辑</title>
<link href="~/Content/Bootstrap/3.3.6/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<div class="container">
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>我的电影—编辑</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.ID)
<div class="form-group">
@Html.LabelFor(model => model.Title, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Title, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Title, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ReleaseDate, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.ReleaseDate, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.ReleaseDate, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Genre, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Genre, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Genre, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="保 存" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("返回列表", "Index")
</div>
</div>
</body>
</html>
此外,按照官网的步骤,修改一下Movie模型类:
public class Movie
{
public int ID { get; set; }
[Display(Name = "电影名称")]
public string Title { get; set; }
[Display(Name = "发行日期")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }
[Display(Name = "电影类型")]
public string Genre { get; set; }
[Display(Name = "电影售价")]
public decimal Price { get; set; }
}
别忘了这个:using System.ComponentModel.DataAnnotations;
官方注释:The Display attribute specifies what to display for the name of a field (in this case "发行日期" instead of "ReleaseDate"). The DataType attribute specifies the type of the data, in this case it's a date, so the time information stored in the field is not displayed. The DisplayFormat attribute is needed for a bug in the Chrome browser that renders date formats incorrectly.
下面调试一下:
你可以点击“编辑”还可以在浏览器中输入:http://localhost:56544/Movies/Edit?id=1
好像是比之前好看多了,多谢Bootstrap。
下面看一下控制器MoviesController中自动生成的Edit方法:
// GET: Movies/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
return View(movie);
}
// POST: Movies/Edit/5
// 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关
// 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (ModelState.IsValid)
{
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
很明显,第一个方法应该是页面加载获取电影详情用的,首先判断主键id是否为空。然后是
Movie movie = db.Movies.Find(id);
我们先不管db.Movies是如何获取电影列表的,以后在慢慢研究吧!而第二个方法是保存用的。
官方解释:The Bind attribute is another important security mechanism that keeps hackers from over-posting data to your model.The ValidateAntiForgeryToken attribute is used to prevent forgery of a request and is paired up with @Html.AntiForgeryToken()
in the edit view file (Views\Movies\Edit.cshtml).
Edit.cshtml页面代码上面已给出,自己寻找@Html.AntiForgeryToken()。
官方注释:@Html.AntiForgeryToken()
generates a hidden form anti-forgery token that must match in the Edit
method of the Movies
controller.
The ValidateAntiForgeryToken attribute validates the XSRF token generated by the @Html.AntiForgeryToken()
call in the view.
先添加一个电影:速度与激情2。我们看一下截图:
点击保存之后,我们用Fiddler 来看一个这个POST请求:
哎,菜啊!没有理解@Html.AntiForgeryToken()和[ValidateAntiForgeryToken]的深意。上面的验证应该是来自服务器端的,现在我们完全可以在客户端做这些处理。毕竟Jquery很牛逼,还有新兴的AngularJS等。这篇就写到这里吧!客户端验证就不写了。个人还是喜欢AngularJS,改天试一下吧!谢谢!
2015-12-26 修改
这里我们利用超链接看看如何传递多个参数,先看看自动生成的代码:
@Html.ActionLink("编辑", "Edit", new { id = item.ID,otherP = new { StuName = "qq"})
再看看浏览器解析之后的代码:
<a href="/Movies/Edit/6">编辑</a>
现在我们试着添加多个参数,这里我直接添加了一个匿名对象:
@Html.ActionLink("编辑", "Edit", new { id = item.ID, otherP = new { StuName = "qq", StuAge = "1" } })
再看看浏览器解析之后的代码:
<a href="/Movies/Edit/6?otherP=%7B%20StuName%20%3D%20qq%2C%20StuAge%20%3D%201%20%7D">编辑</a>
哈哈,被编码了。不管了,直接调试看看什么情况:
嘿嘿,不错。传个对象都没问题!但是之后测试 传非匿名对象(DDZ.MVC5Test.Controllers.Student)就不可以了,泛型List< DDZ.MVC5Test.Controllers.Student>就更不用提了(我也是试了)。估计是弄到URL上不好弄!