我用的是Microsoft Visual Studio Express 2012 for Web,免费么。
新建一个MVC4项目
确定
默认选项,确定
在Models目录中添加两个模型类Citry和ContactAddress
两个类的定义见下面,我加了一些标记(需要using System.ComponentModel),这样在用向导自动生成的视图中可以显示自定义的名称(DisplayName)。
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace Contact.Models
{
public class City
{
public int Id { get; set; }
[DisplayName("城市")]
public string Name { get; set; }
[DisplayName("联系人")]
public virtual ICollection<ContactAdress> Contacts { get; set; }
}
}
using System;
using System.ComponentModel;
namespace Contact.Models
{
public class ContactAdress
{
public int Id { get; set; }
[DisplayName("联系人")]
public string Name { get; set; }
[DisplayName("地址")]
public string Adress { get; set; }
[DisplayName("所在城市")]
public virtual City City { get; set; }
}
}
在项目根目录添加一个新目录DataAccess,放我们的数据库上下文ContactContext,这个类也是用向导添加修改而来,主要是修改以从DbContext继承(需要using System.Data.Entity),并添加实体类型,其他不用改,都使用默认配置。
using Contact.Models;
using System.Data.Entity;
namespace Contact.DataAccess
{
public class ContactContext : DbContext
{
public DbSet<City> Citys { get; set; }
public DbSet<ContactAdress> Contacts { get; set; }
}
}
下面是添加数据库连接字符串,我发现向导默认生成的Web.config中已经有一个数据库连接字符串:
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-Contact-20130223130627;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-Contact-20130223130627.mdf" providerName="System.Data.SqlClient" />
</connectionStrings>
我们就用它了,因为只是做个例子,就用LocalDB试试吧。这时可以修改这个连接字符串的名字以和数据库上下文ContactContext一致,这样Entity Framework可以自动找到;不过为了防止还有他用,我选择修改数据库上下文的配置直接使用而不是修改Web.config中的名称。修改很简单,就是添加一个构造函数,用连接字符串的名字调用基类的构造函数:
using Contact.Models;
using System.Data.Entity;
namespace Contact.DataAccess
{
public class ContactContext : DbContext
{
public ContactContext()
: base("name=DefaultConnection")
{
}
public DbSet<City> Citys { get; set; }
public DbSet<ContactAdress> Contacts { get; set; }
}
}
OK,建模完成,下面是生成(编译)一下项目,以使模型类和数据库上下文生效,顺便看看一次输入的代码有没有什么错误。
结果很令人满意
下面添加控制器和视图,在Controller目录上添加控制器,控制器名称为City,选择的模板、模型类和数据上下文类见图,其余默认:
我们希望在一页上完成所有的数据操作,所以需要修改生成的代码,首先是Index.html:
<div id="divContact">
@model IEnumerable<Contact.Models.City>
@{
ViewBag.Title = "Index";
}
<p>
@Ajax.ActionLink("增添", "Create", new AjaxOptions { UpdateTargetId = "divEdit" })
</p>
<table>
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th></th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Ajax.ActionLink("修改", "Edit", new { id = item.Id }, new AjaxOptions { UpdateTargetId = "divEdit" }) |
@Ajax.ActionLink("详情", "Details", new { id = item.Id }, new AjaxOptions { UpdateTargetId = "divEdit" }) |
@Ajax.ActionLink("删除", "Delete", new { id = item.Id }, new AjaxOptions { UpdateTargetId = "divEdit" })
</td>
</tr>
}
</table>
</div>
<div id="divEdit"></div>
@section scripts{
@Scripts.Render("~/bundles/jqueryval")
}
将Create、Edit、Details、Delete操作全部改成用Ajax方式实现,同时添加两个<div>标签用来显示结果,添加一个Javascrit脚本辅助完成Ajax。
Create.html
@model Contact.Models.City
@{
ViewBag.Title = "Create";
}
<h2>增加新的城市</h2>
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>City</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
<p>
<input type="submit" value="新增" />
</p>
</fieldset>
}
@if (!IsAjax)
{
<div>
@Html.ActionLink("返回", "Index")
</div>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Details.html@model Contact.Models.City
@{
ViewBag.Title = "Details";
}
<h2>城市详情</h2>
<fieldset>
<legend>City</legend>
<div class="display-label">
@Html.DisplayNameFor(model => model.Name)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.Name)
</div>
</fieldset>
<p>
@if (IsAjax)
{
@Ajax.ActionLink("修改", "Edit", new { id = Model.Id }, new AjaxOptions { UpdateTargetId = "divEdit" })
}
else
{
@Html.ActionLink("返回", "Index") <text> | </text>
@Html.ActionLink("修改", "Edit", new { id = Model.Id })
}
</p>
修改控制器返回部分视图:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Contact.Models;
using Contact.DataAccess;
namespace Contact.Controllers
{
public class CityController : Controller
{
private ContactContext db = new ContactContext();
//
// GET: /City/
public ActionResult Index()
{
var citys = db.Citys.ToList();
if (Request.IsAjaxRequest())
{
return PartialView(citys);
}
return View(citys);
}
//
// GET: /City/Details/5
public ActionResult Details(int id = 0)
{
City city = db.Citys.Find(id);
if (city == null)
{
return HttpNotFound();
}
if (Request.IsAjaxRequest())
{
return PartialView(city);
}
return View(city);
}
//
// GET: /City/Create
public ActionResult Create()
{
if (Request.IsAjaxRequest())
{
return PartialView();
}
return View();
}
//
// POST: /City/Create
[HttpPost]
public ActionResult Create(City city)
{
if (ModelState.IsValid)
{
db.Citys.Add(city);
db.SaveChanges();
return RedirectToAction("Index");
}
if (Request.IsAjaxRequest())
{
return PartialView(city);
}
return View(city);
}
//
// GET: /City/Edit/5
public ActionResult Edit(int id = 0)
{
City city = db.Citys.Find(id);
if (city == null)
{
return HttpNotFound();
}
if (Request.IsAjaxRequest())
{
return PartialView(city);
}
return View(city);
}
//
// POST: /City/Edit/5
[HttpPost]
public ActionResult Edit(City city)
{
if (ModelState.IsValid)
{
db.Entry(city).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
if (Request.IsAjaxRequest())
{
return PartialView(city);
}
return View(city);
}
//
// GET: /City/Delete/5
public ActionResult Delete(int id = 0)
{
City city = db.Citys.Find(id);
if (city == null)
{
return HttpNotFound();
}
if (Request.IsAjaxRequest())
{
return PartialView(city);
}
return View(city);
}
//
// POST: /City/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
City city = db.Citys.Find(id);
db.Citys.Remove(city);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}
Edit.html
@model Contact.Models.City
@{
ViewBag.Title = "Edit";
}
<h2>修改城市名称</h2>
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>City</legend>
@Html.HiddenFor(model => model.Id)
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
<p>
<input type="submit" value="保存" />
</p>
</fieldset>
}
@if (!IsAjax)
{
<div>
@Html.ActionLink("返回", "Index")
</div>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Delete.html@model Contact.Models.City
@{
ViewBag.Title = "Delete";
}
<h2>删除城市</h2>
<h3>你确认要删除这个城市吗?</h3>
<fieldset>
<legend>City</legend>
<div class="display-label">
@Html.DisplayNameFor(model => model.Name)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.Name)
</div>
</fieldset>
@using (Html.BeginForm())
{
<p>
<input type="submit" value="删除" />
@if (!IsAjax)
{
<text> | </text>
@Html.ActionLink("返回", "Index")
}
</p>
}
现在,可以运行一下看看效果了。对了,为了方便可以修改一下路由默认打开我们的Contact控制器的Index视图:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "City", action = "Index", id = UrlParameter.Optional }
);
}
}
运行效果:
现在增加、修改、详情都显示在同一页了。
太细太长,分下部分再写地址的数据操作了。