之前,我们学习了mvc最基本的架构和用法。

在学习了真正的属性、委托和列表之后,我们就可以使用微软提倡的模型了。

需要注意的是,这种模型以及它的工作方式,身上有着浓浓的微软印记。在方便的同时,也要自行考虑各种风险。这一点,以后不再提。

把模型运用到mvc框架中,可以看到微软提供的各种高效率的写法和工具。

关于模型

有别于我们以前提到的模型,mvc(这里特指微软的mvc架构,下同)中的模型,属性必须是标准属性,不能是字段。否则很多情况下,无法和其他代码互动。

对数据库的操作,可以使用EF框架,借助“数据库上下文”类来高效地完成。

关于这些,微软都进行了很好的封装。利用vs,我们掌握起来也比较轻松。如果模型是咖啡馆负责打水的小工,数据库里的数据是井里的水,那么相比于我们以前类似绳子和桶的数据库操作方法,EF框架就像是抽水机一样方便高效。

详情请参阅:

在access当中使用ef框架 (学校教室的机器(vs2013,nuget版本也不够)无法做出效果,可以在自己的机器上完成)

在sqlserver中使用ef框架

注意:每张表和对应的模型中,必须有主Key。

可以看到,vs帮我们写好了数据库上下文(dbcontext)类和模型。利用实体的“SaveChanges”方法,可以把各种数据库修改保存到库中。十分方便。

具体的模型对应数据库的操作,大家可以参考着list文章里的内容自行类比学习,不难。

学会了这些,再看看模型的一些常用操作

模型在C和V中的使用

按照上面的方法,配置好模型和EF框架之后,我们来看看如何用新东西完成之前的小操作。

本例中,数据库上下文D1.CS代码如下:

public partial class D1 : DbContext
{
public D1()
: base(@"server=(localdb)\mssqllocaldb;initial catalog=d1;user ID=sa;password=xxx;")
{
} public virtual DbSet<t1> t1 { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
}

实体类t1.CS代码如下:

public partial class t1
{
[Key]
[StringLength()]
public string xm { get; set; } public short? nl { get; set; }
}

以上代码大半自动生成,很方便。

要读出数据库中的学生信息,并且向库中添加内容。

新建控制器,在index方法中考虑呈现数据:

public ActionResult Index()
{
D1 d1 = new D1();
return View(d1.t1.ToList());
}

其中“return View(d1.t1.ToList());”表示把t1表里的内容转换成List带给视图,视图里用“model”来接收。

除了呈现,再加一个“添加”表单。对应的视图代码如下:

@model List<WebApplication1.Models.t1>
@*上面这一行表示接收过来的数据类型,和控制器方法中return过来的数据类型一致。*@
@{
Layout = null;
} <!DOCTYPE html> <html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>@*呈现代码,简单写*@
@foreach (var item in Model)
{
<text>@item.xm</text><text>@item.nl</text><br />
}
</div>
<hr />
<form action="/home/add">
姓名:<input type="text" name="xm" />年龄:<input type="text" name="nl" /><br />
<input type="submit" name="m" value="添加" />
</form>
</body>
</html>

注意:1、第一行的内容和注释;2、foreach中in后面的集合名称;3、表单中两个文本框的name属性和模型里的属性是对应的。

接收提交表单的action是add,代码如下:

public ActionResult Add(t1 student)
{
if(ModelState.IsValid)
{
D1 d1 = new D1();
d1.t1.Add(student);
d1.SaveChanges();
ViewData["msg"] = "ok";
}
else
{
ViewData["msg"] = "fail";
}
return View();
}

由于视图提交过来的是一个“属性对应”的学生信息(http://xxx/home/add?xm=zd&nl=100&m=%E6%B7%BB%E5%8A%A0),在这里,就可以用一个t1的对象student来接收参数。系统会自动试图把传递过来的name和nl两个字段的内容往student里放。

代码部分的“ModelState.IsValid”就是用来测试这个赋值是否成功。一旦成功,就可以调用模型里的方法【d1.SaveChanges()】写入数据库。

add对应的view很简单,主要代码为:

<div>
@ViewData["msg"] <br />
<a href="/home/index">返回操作页</a>
</div>

程序运行效果如下:

填写内容“test1”,“50”,点击“添加”后:

返回操作页:

从上面的简单例子,能够体会到mvc模型给控制器和视图带来的简化效果。

关于控制器

转书上P65

接书上P85

关于书上控制器的返回部分,稍微讲两个地方。方便起见,这里mvc的模型全部用模拟模型

1、关于Json

  在c#中对数据进行Json序列化和反序列化,常规方法可以参看这里

  控制器中的Json方法也可以对任意类型进行序列化。示例如下:

 public ActionResult Index()
{
myDatabase d1 = new myDatabase();
return Json(d1.t1,JsonRequestBehavior.AllowGet);
}

  效果:

  用作webapi提供数据的时候很有用。

2、关于partialview

  mvc中的视图有一种包含关系:母版包含视图(即我们常用的view),视图包含局部视图。

  创建母版的方法如下:

命名后可以对母版进行编辑,如下:

<!DOCTYPE html>

<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
</head>
<body>
<div>这里应该放本站所有页的标题……之类的东西</div>
<div>
@RenderBody()
</div>
<div>版权信息等等东西应该在这里</div>
</body>
</html>

其中“@RenderBody()”就是各个视图的内容,其余部分相对稳定,一般不改变。

在添加视图的时候选择布局页,就可以使用这个母版:

视图里的内容可以很简单:

@{
ViewBag.Title = "Index";
Layout = "~/Views/_LayoutPage1.cshtml";
} <h2>这是我的Index页面</h2>

运行效果:

此外,可以根据需要创建局部视图。

例如,在新建的局部视图控制器中,新建一个返回局部视图的action,设法包含在刚刚的view里。

action代码如下:

public class PartialController : Controller
{
// GET: Partial
public ActionResult ShowData()
{
myDatabase d1 = new myDatabase();
return PartialView(d1.t1.ToList());
}
}

对应的视图ShowData.cshtml代码如下:

@model List<WebApplication1.Models.Person>
@if (Model != null)
{
foreach (var item in Model)
{
<text>@item.Xm</text><text>@item.Nl</text><br />
}
}
else
{
<text>没有可以显示的数据</text>
}

在正常视图中,调用该局部页(分布视图)时,需要区分“Html.Action”和“Html.Partial”两种调用方法。前者通过控制器调用,后者直接调用视图。

如下例:

@{
ViewBag.Title = "Index";
Layout = "~/Views/_LayoutPage1.cshtml";
} <h2>这是我的Index页面</h2>
Html.Action直接调用视图的结果:<br />
@Html.Action("ShowData", "Partial")<br />
Html.Partial直接调用视图的结果:<br />
@Html.Partial("~/Views/Partial/ShowData.cshtml")

运行结果如下:

和普通视图一样,分布式视图一样可以接收传递过来的模型或其他数据,一般用作“页面类的方法”。即,反复使用的小页面部分(如显示某固定类型的数据等等)

 关于视图

刚刚为了介绍控制器的各种ActionResult返回值,提到了一部分视图的内容。它们包括1、母版、视图、分部视图;2、返回view时携带模型,及视图中应用模型。

除此之外,微软还为视图提供了一些写法。微软说,这些写法能减轻程序员的工作量,大家在学习的时候,自行考虑成本和收益。

转书上P103

接书上P113

强类型“视图/模型/控制器”联动

以下两个例子着重表现微软自动生成代码的强大,也就是之前付出“学习成本”的“收获”。

综合例1:创建综合控制器

按照之前的内容,使用EF框架连接数据库之后,在添加控制器的时候,可以利用“读/写”选项自动创建一系列的Action,不用我们手动编码。如下图:

选定名称后,出来的控制器里包含的内容如下:

 public class Home1Controller : Controller
{
// GET: Home1
public ActionResult Index()
{
return View();
} // GET: Home1/Details/5
public ActionResult Details(int id)
{
return View();
} // GET: Home1/Create
public ActionResult Create()
{
return View();
} // POST: Home1/Create
[HttpPost]
public ActionResult Create(FormCollection collection)
{
try
{
// TODO: Add insert logic here return RedirectToAction("Index");
}
catch
{
return View();
}
} // GET: Home1/Edit/5
public ActionResult Edit(int id)
{
return View();
} // POST: Home1/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
try
{
// TODO: Add update logic here return RedirectToAction("Index");
}
catch
{
return View();
}
} // GET: Home1/Delete/5
public ActionResult Delete(int id)
{
return View();
} // POST: Home1/Delete/5
[HttpPost]
public ActionResult Delete(int id, FormCollection collection)
{
try
{
// TODO: Add delete logic here return RedirectToAction("Index");
}
catch
{
return View();
}
}
}

可以看到列表、呈现单条数据、增删改的控制器全部写好,不用我们动手。

不过瘾?看下面。

综合例二:

在添加控制器的时候,选择“包含视图”。如下图:

在弹出的对话框中选择对应内容:

其中D1是库,t1是表(里面的记录)

vs创建完毕后,运行,结果为下图:

这个界面不稀奇,神奇的是……所有链接下的功能,都可以工作!!!你做了什么?你一个字的代码都没写。

以“创建”为例,提交后自动的Action为:

 [HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "id,nl")] t1 t1)
{
if (ModelState.IsValid)
{
db.t1.Add(t1);
db.SaveChanges();
return RedirectToAction("Index");
} return View(t1);
}

自动生成的视图为:

 @model WebApplication3.Models.t1

 @{
Layout = null;
} <!DOCTYPE html> <html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Create</title>
</head>
<body>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken() <div class="form-horizontal">
<h4>t1</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.id, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.id, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.id, "", new { @class = "text-danger" })
</div>
</div> <div class="form-group">
@Html.LabelFor(model => model.nl, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.nl, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.nl, "", 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>
</body>
</html>

所有的一切,都很完美。所有的代码,差不多都认识。

你现在只需要在这个程序的基础上做你需要的修改(美工、逻辑等等)就可以了。而我们前面讲的代码(辅助方法、视图、兰姆达表达式等等)都是为了让你会修改准备的。

至此,前面的付出似乎都有回报了。

ps:要实现这种全自动,需要全程循规蹈矩。比如,用整数id做索引,设置key等等。。。。

mvc_第二遍的更多相关文章

  1. 微信内置浏览器http请求10秒内接收不到数据会自动重发第二遍请求

    微信内置浏览器http请求10秒内接收不到数据会自动重发第二遍请求     这是个坑

  2. 深入理解计算机系统 第八章 异常控制流 Part2 第二遍

    第二遍读这本书,每周花两到三小时时间,能读多少读多少(这次看了第 508~530 页,共 23 页) 第一遍对应笔记链接 https://www.cnblogs.com/stone94/p/10206 ...

  3. 深入理解计算机系统 第八章 异常控制流 Part1 第二遍

    第二遍读这本书,每周花两到三小时时间,能读多少读多少(这次看了第 500~507 页,共 8 页) 第一遍对应笔记链接 https://www.cnblogs.com/stone94/p/101651 ...

  4. 深入理解计算机系统 第二章 信息的表示和处理 Part2 第二遍

    <深入理解计算机系统> 第三版 第二遍读这本书,每周花两到三小时时间,能读多少读多少(这次看了 29 ~ 34 页) 第一遍对应笔记链接 https://www.cnblogs.com/s ...

  5. 深入理解计算机系统 第二章 信息的表示和处理 Part1 第二遍

    <深入理解计算机系统> 第三版 第二遍读这本书,每周花两到三小时时间,能读多少读多少(这次看了 22 ~ 28 页) 第一遍对应笔记链接 https://www.cnblogs.com/s ...

  6. 深入理解计算机系统 第九章 虚拟内存 Part1 第二遍

    这次花了4小时40分钟,看了第 559~575 页,共 17 页 第一遍对应地址 https://www.cnblogs.com/stone94/p/10264044.html 注意:本章的练习题一定 ...

  7. 深入理解计算机系统 第三章 程序的机器级表示 Part2 第二遍

    第一遍对应笔记链接 https://www.cnblogs.com/stone94/p/9943779.html 本章汇编代码中常出现的几个指令及其含义 1.push 操作数的个数:1 将操作数(一般 ...

  8. 深入理解计算机系统 第三章 程序的机器级表示 Part1 第二遍

    第一遍对应笔记链接 https://www.cnblogs.com/stone94/p/9905345.html 机器级代码 计算机系统使用了多种不同形式的抽象,利用更简单的抽象模型来隐藏实现的细节. ...

  9. javascript第二遍基础学习笔记(二)

    一.操作符 1.一元操作符: 自加自减(分前置和后置2种):++.-- 区别:前置的先自加或自减,后进行计算:而后置的是先进行计算,后自加或自减(在其会产生负面影响时才能体现区别): ; i++; / ...

随机推荐

  1. Mac启动MySQL

    启动MySQL服务 sudo /usr/local/Cellar/mysql//bin/mysql.server start 停止MySQL服务 sudo /usr/local/Cellar/mysq ...

  2. Windows下面startup.bat启动Tomcat偶发死锁问题

    Windows下面startup.bat启动Tomcat时,因为日志都打印到了cmd里面,存在偶发卡死Tomcat的问题,该问题确认是Windows系统的问题,而且一直没有解决.解决的办法是把日志重定 ...

  3. BeyondCompare4破解方法

    因为工作需要,经常会用到BeyondCompare4这个软件,但是从官方下载的BeyondCompare4只有一个月的试用期,点击输入密钥又一直打开购买软件的页面,所以就一开始就用了最笨的方法,软件的 ...

  4. Anaconda 下载

    Anaconda官网:https://repo.anaconda.com/archive/清华大学镜像站:https://mirrors.tuna.tsinghua.edu.cn/anaconda/a ...

  5. Comet OJ 计算机(computer)

    Comet OJ 计算机(computer) 题目传送门 题目描述 小 X 有一台奇怪的计算机. 这台计算机首先会读入一个正整数 nn,然后生成一个包含 nn 个数的序列 aa. 一开始 a_i(1 ...

  6. NOIP 2012 Vigenère 密码

    洛谷 P1079 Vigenère 密码 https://www.luogu.org/problemnew/show/P1079 JDOJ 1779: [NOIP2012]Vigenèr密码 D1 T ...

  7. 4.Vue双向绑定

    1.什么是双向数据绑定 Vue.js 是一个 MVVM 框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化.这也算是 Vue.js 的精髓之处了 ...

  8. [Taro] taro 缓存

    taro 缓存 Taro.clearStorageSync() 清除全部缓存 Taro.setStorage(key,value)设置缓存 Taro.getStorage(key)获取缓存 Taro. ...

  9. 原生js-input框全选

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. [探究] [Luogu4550]收集邮票的概率意义

    自认为这道题是一道比较简单的扩展题--?此处采用了和别的题解思路不同的,纯概率意义上的解法. 首先考虑一个简化版问题: 每次随机一个\([1,n]\)的整数,问期望几次能凑出所有数 这东西我写过一个b ...