当前位置: 首页 > news >正文

ASP.NET MVC添加模型示例

ASP.NET MVC高效构建Web应用ASP.NET MVC

我们总在谈“模型”,那到底什么是模型?简单说来,模型就是当我们使用软件去解决真实世界中各种实际问题的时候,对那些我们关心的实际事物的抽象和简化。比如,我们在软件系统中设计“人”这个事物类型的时候,通常只会考虑姓名、性别和年龄等一些系统用得着的必要属性,而不会把性格、血型和生辰八字等我们不关心的东西放进去。

进一步讲,我们会谈领域模型(Domain Model)。“领域”两个字显然给出了抽象和简化的范围,不同的软件系统所属的领域是不同的,比如金融软件、医疗软件和社交软件等。如今领域模型的概念包含了比其原本范围定义以外更多的内容,我们会更关注这个领域范围内各个模型实体之间的关系。

MVC中的“模型”说的是“模型层”,它正是由上述的领域模型来实现的,可是当我们提到这一层的时候,它包含了模型上承载的实实在在的业务数据,还有不同数据间的关联关系。因此,我们在谈模型层的时候,有时候会更关心领域模型这一抽象概念本身,有时候则会更关心数据本身。

3.4.1  模型的实现方式

在ASP.NET MVC(Model-View-Controller)架构中,模型(Model)通常指的是数据访问层,它负责数据的存取。具体实现时候,模型(Model)可以定义为一组类,描述了要处理的数据以及修改和操作数据的业务规则。即,模型是描述程序设计人员感兴趣问题域的一些类,这些类通常封装存储在数据库中的数据,以及操作这些数据和执行特定域业务逻辑的代码。在ASP.NET MVC中,模型就像使用了某种工具的数据访问层(Data Access Layer),这种工具包括实体框架(Entity Framework,该框架用于访问数据库)或者与包含特定域逻辑的自定义代码组合在一起的其他实体框架。

所有需要进行数据访问的操作都须依赖Model提供的服务。简单地说,Model负责通过数据库、AD(Active Directory)、Web Service及其他方式取得数据,或者将用户输入的数据保存到数据库、AD、Web Service等中。Model的独立性很高,如果VS解决方案中有多个要开发的项目,一般会将Model独立成一个项目,好让Model项目在不同的项目之间共享。但我们刚开始学,不必弄得如此复杂,而且为了照顾初学者,我们这里不会一上来就弄数据库,就简简单单弄个类对象作为数据源。后面章节再逐步扩展到数据库,这样让学习曲线尽可能地平缓。

3.4.2  新建项目添加类

我们将添加一个不与数据库直接关联的模型,这个模型类就是一个普通的类,且不需要继承自任何特殊的基类或实现任何接口。

【例3.3】在MVC项目中添加类

(1)打开VS,新建一个基于MVC的ASP.NET项目,项目名称是test。

(2)在解决方案资源管理器中,右键单击“Models”文件夹图标,选择“添加”,然后选择“类”,如图3-21所示。

图3-21

在“添加新项”对话框上,在“名称”旁边输入“person”,这个名称也就是我们要新添加的类的名称(简称类名),然后点击右下角的“添加”按钮,此时一个person.cs文件就在Models文件夹下自动生成了,我们在解决方案资源管理的“Models”下也可以看到person.cs,后续就在该文件中添加类成员,而且VS已经在该文件中自动添加了一个空类person,现在我们为这个类添加2个属性,代码如下:

namespace test.Models{public class person{public int Id { get; set; }public string Name { get; set; }}}

这里,我们为person类添加两个属性 Id和Name。这个模型不需要任何数据库上下文或表映射,因此它是非数据库的。然后,我们可以在控制器中实例化和使用这个模型。

由于新建项目时候,VS已经自动新建了HomeController这个控制器,因此我们可以直接在该控制器中使用模型,具体是在Index方法中实例化person类,在解决方案资源管理器中双击打开HomeController/HomeController.cs,然后在Index方法中添加代码如下:

public ActionResult Index(){var p = new person(){Id = 1001,Name = "Jim",};return View();}

粗体部分就是我们添加的代码,这里我们创建了一个类person的对象p。这个模型不会与数据库进行交互,因此不需要数据库上下文。那下一步该干什么呢?当然是要在视图上显示对象了,但在显示之前,首先要把数据(比如对象p)传递给视图,这里有多种方法,我们一一做个说明。

3.4.3  ViewData方式传递数据到视图

我们利用ViewData以键值对的形式来存储上述实例化的对象。另外,要说明一下,由于不同的传递数据方式功能类似,为了防止冲突,后面的讲解将复制一份例3.3形成新的实例,然后在新实例上修改。这样,我们就不会把四种方式都放在一个实例中,避免把代码弄得乱七八糟。

【例3.4】ViewData方式传递数据到视图

(1)复制例3.3作为本实例的项目,然后在VS中打开新项目,即双击test.sln打开解决方案。

(2)在HomeController/HomeController.cs中的Index方法的return语句前加入一行代码:

ViewData["Person"] = p;

此时,Index方法的内容如下所示:

public ActionResult Index(){var p = new person(){Id = 1001,Name = "Jim",};ViewData["Person"] = p;  //存储实例化的对象return View();}

接下来,在视图中把从ViewData中获取存储的值并转换成对象,打开Views/Home/Index.cshtml,然后在该文件开头添加代码如下:

@using test.Models;  @{ViewBag.Title = "Home Page";var p = (person)ViewData["myPerson"];    //从ViewData中获取存储的值并转换成对象}<div class="jumbotron"><h1>ASP.NET</h1><h1>Person</h1><h3>@p.Id</h3>  <h3>@p.Name</h3>

图3-22

粗体字部分是我们新增的。代码中,我们首先通过@using来引用模型,然后从ViewData中获取存储的值并转换成对象(这里是p),最后就可以通过@p.Id和@p.Name的方式来得到对象成员的值,@只是表示其后面跟随的代码是C#语句而已,而using、p.id和p.Name等方式都是C#中的写法,学过C#的朋友应该不陌生。

此时运行项目,可以看到Person字符串下面能正确输出当前p.id和p.Name的值了,如图3-22所示。

至此,我们成功地通过ViewData方式把类person中的成员Id和Name的值传递到视图中。

3.4.4  ViewBag方式传递数据到视图

这种方式比ViewData简单一些,ViewBag将创建动态表达式来进行。在ASP.NET MVC中,有一个特殊的ViewBag对象,ViewBag是一个dynamic动态类型,定义在ControllerBase类中,可以在此对象上定义任意的属性,且还可以在控制器和视图之间传递数据。

ViewBag和ViewData生命周期相同,也是对当前View有效,不同的是ViewBag的类型不再是字典的键值对结构,而是dynamic动态类型

我们将复制一份例3.3项目,然后在新实例基础上讲解。

【例3.5】ViewBag方式传递数据到视图

(1)复制例3.3到某个文件夹下作为本例的新项目,然后在VS中打开新项目,即双击test.sln打开解决方案。

(2)在HomeController/HomeController.cs中Index方法的return语句前加入一行代码:

ViewBag.myPerson = p;   //通过ViewBag存储对象p

ViewBag是一个特殊对象,它可以用来存储任何类型数据,包括对象,这里存储了对象p, myPerson这个名字随便起,起Person也可以。接下来,就可以在视图中我们从ViewData中获取存储的值并转换成对象,打开Views/Home/Index.cshtml,然后在该文件开头添加代码如下:

@using test.Models;@{ViewBag.Title = "Home Page";var p1 = ViewBag.myPerson;  //将对象存于变量p1中}<div class="jumbotron"><h1>ASP.NET</h1><h3>@p1.Id</h3><h3>@p1.Name</h3>

图3-23

粗体字部分是我们新增的。可以看到基本也是三部曲,首先是通过using引用模型,然后通过ViewBag获取myPerson中存储的对象p,最后就是使用对象中的成员Id和Name。p1是个var类型的变量,可以存储任意类型,包括对象。

(3)按ctrl+F5运行项目,运行结果如图3-23所示。

3.4.5  通过返回View传递数据到视图

前面两种方法都是借助了“中介”服务,比如ViewData和ViewBag,现在我们在控制器中将数据对象作为View的参数返回,而且可以不必是对象做View参数,还可以单独让一个普通变量(比如整型变量)做View参数,然后在视图中使用该整型变量。

【例3.6】通过返回View传递对象到视图

(1)复制例5.3到某个文件夹下作为本例的新项目,然后在VS中打开新项目,即双击test.sln打开解决方案。

(2)在控制器中修改代码。在解决方案资源管理器中打开Controllers/HomeController.cs,然后在Index方法末尾将return View();改为return View(p);,也就是将对象p作为View的参数后再返回视图。

(3)在视图中添加代码。打开Views/Home/Index.cshtml,然后在该文件开头中添加代码如下:

@using test.Models;@model person

第一行通过using来引用命名空间test.Models,命名空间test.Models是我们在Models/person.cs中定义的。第二行的“@model”是一个Razor中的指令,该指令用一个简单而干净的方式实现视图文件对强类型模型的引用,这里的模型是类person。

然后再在“<h1>ASP.NET</h1>”下添加代码如下:

<div class="jumbotron"><h1>ASP.NET</h1><h2>@Model.Id</h2><h2>@Model.Name</h2>

图3-24

粗体部分是我们添加的。这里的Model相当于person对象,这是因为在HomeController.cs中对象p作为View的参数后返回给视图,因此视图中可以获得该对象。有了对象,我们就可以直接使用Id和Name成员了。

(4)运行项目,运行结果如图3-24所示。

除了从模型中传递对象给视图,我们还可以只传递一个普通的整型变量。在下面的实例中,我们将模型项System.Int32传递给视图Index.cshtml。神奇吧,整型竟然是模型项!这没有什么好惊讶的,因为在MVC中,所谓的模型就只是一些C#类型,而System.Int32本身就是一个类型,所以,可以被当做模型项处理也是很正常的。

【例3.7】通过返回View传递整型到视图

(1)复制例3.3到某个文件夹下作为本例的新项目,然后在VS中打开新项目,即双击test.sl打开解决方案。

(2)在控制器中修改代码。在解决方案资源管理器中打开Controllers/HomeController.cs,然后在Index方法末尾将return View();改为return View(p.Id),也就是将整型变量p.Id作为View的参数再返回给视图。

(3)在视图中添加代码。打开Views/Home/Index.cshtml,然后在该文件开头中添加代码如下:

@model System.Int32

该行代码通过@model指令引用强类型模型(这里是System.Int32)。这里或许有同学疑惑,为何不用using来导入命名空间了,这是因为我们这里已经把命名空间System直接写在Int32前头了,导入模型必须指定命名空间,Int32的命名空间就是System,如果想直接写@model Int32,则要在它前头导入命名空间:

@using System

这样才会用到System这个命名空间中的Int32。另外,不写@using System其实也没事,因为VS一看Int32就知道来自哪里了。但如果是我们自定义的类型,就必须完整地指定该类型的命名空间。然后就可以使用到变量值了,在“<h1>ASP.NET</h1>”后面添加代码如下:

<h1>ASP.NET</h1><h2>@Model</h2>

粗体部分是我们添加的代码。这里的Model相当于p.Id,这是因为在HomeController.cs中变量p.Id作为View的参数后返回给视图,因此视图中可以获得该变量。使用的时候,也是使用@(也就是Razor语法),@Model就是使用该模型的值。当然,如果是自定义的类型,而且是包含有方法的类型,就可以通过@Model.method来调用相关的方法。

(4)运行项目,我们可以在“ASP.NET”下方看到1001,如下所示:

1001

这个实例中,我们传递了整型变量,如果想传递其他类型变量也简单,比如现在想要传递一个浮点型变量,可以在Index方法中,把浮点数作为View的参数,再返回:

return View(3.14);

然后就可以直接使用了,比如:

<h2>@Model</h2>

此时页面上将输出3.14。是不是觉得很简单,有些人或许还想传递字符串,但字符串比较特殊,不能这样传递给视图。我们来看一下面的实例。

【例3.8】传数据给指定网页

(1)复制例3.3到某个文件夹下作为本例的新项目,然后在VS中打开新项目,即双击test.sln打开解决方案。

(2)在控制器中修改代码。在解决方案资源管理器中打开Controllers/HomeController.cs,然后在Index方法末尾将return View();改为return View("aaa")。

(3)在视图中添加代码。打开Views/Home/Index.cshtml,然后在该文件开头中添加代码如下:

<h2>@Model</h2>

运行后就报错了。错误结果如图3-25所示。

图3-25

原因是我们在地址栏输入http://localhost:44316/Home/Index,会查找HomeController类下的Index方法并执行,当执行return View("aaa"),即返回字符串类型的参数View的时候,系统会查找视图Views/Home下的aaa.cshtml并返回,如果没有该文件,会查找Shared文件夹下是否有,如果也没有,则会报错。因此,需要在Views/Home下提供aaa.cshtml,我们可以解决方案资源管理中,选中Views/Home下的index.cshtml,然后按键ctrl+c,复制出一份“Index - 复制.cshtml”,将其重命名为aaa.csthml,然后双击打开aaa.cshtml,删除该文件全部内容,并添加这一句:

<h1>hi</h1>

此时,运行项目,在浏览器地址栏输入http://localhost:44316/Home/Index,就可以看到aaa.cshtml的内容了,如图3-26所示。

现在我们知道了,return View("aaa");的执行结果是查找aaa.cshtml,那么我们如何传数据给aaa.cshtml呢?这个简单,给View第二个参数赋值即可,比如,我们准备把对象p传给视图文件aaa.cshtml,可以在Index方法中这样返回:

return View("aaa",p);

然后在aaa.cshtml中新增代码如下:

@using test.Models;@model person<h1>hi</h1><h2>@Model.Name</h2>

这些代码依旧是三部曲,大家应该很熟悉了。此时运行项目,在浏览器地址栏输入http://localhost:44316/Home/Index,就可以看到对象p的成员Name值了,如图3-27所示。

好了,现在我们知道了如何传数据给指定网页了。有同学还想知道如何传递字符串,可以使用ViewData、ViewBag或把字符串作为对象成员,然后把对象作为View的参数再返回吧,反正View中若用字符串做参数,那就是要访问名称为该字符串的网页,切记!另外,还可以通过方法名的方式来访问指定视图页面。例如:

public ActionResult KK(){...return View();}

此时会去Views/Home/下查找KK.cshtml文件,这也是指定访问网页的一种方法。比如,我们可以在HomeController类中增加一个aaa方法,代码如下:

public ActionResult aaa(){var p = new person(){Id = 1001,Name = " Peter ",};return View(p);}

运行项目,在浏览器地址栏输入http://localhost:44316/Home/aaa,这里URL指定了aaa,因此会访问方法aaa(),此时就可以看到对象p的成员Name值Peter了,如图3-28所示。

                 

3.4.6  TempData方式传递数据给视图

TempData从字面意思来理解,我们会误认为是临时对象,好像就使用一次就不会再用了,确实是这样吗?事实上不是这样,当然其生命周期确实很短。该对象是将数据从一个控制器的方法传递到另外一个方法上。什么意思呢?我们想象这样一个场景:当我们在控制器的Info方法上添加一个Person的信息后,将跳转到另外一个方法TempDataObject上来显示该对象已经成功被创建。

ViewData和ViewBag不可以跨页面传递数据,而TempData可以跨页面传递数据。但TempData跨页面传递的数据是一次性的,在每次调用结束后,数据就会被清除。TempData数据保存机制是Session,但又不完全等同Session,它分两种情况:

  • TempData保存数据后,如果被使用,就会被清除,因此后面的请求将不能再次使用。
  • TempData保存数据后,如果没有被使用,则它保存的时间是Session的生存期。

在一个Action存入TempData,在后续的Action一旦被读取一次,数据自动销毁。TempDta默认就是依赖于Session实现的,所以Session过期后,即使没有读取也会被销毁。TempData 保存在Session中,Controller每次执行请求的时候,会从Session中先获取 TempData,而后清除Session;获取完TempData数据,虽然保存在内部字典对象中,但是其集合中的每个条目访问一次后就从字典表中删除。具体代码层面,TempData获取过程是通过SessionStateTempDataProvider.LoadTempData方法从ControllerContext的Session中读取数据,而后清除Session,故TempData只能跨Controller传递一次。

ViewData只在当前 Action中有效,生命周期和View相同,而TempData的数据至多只能经过一次Controller传递,并且每个元素至多只能被访问一次,访问以后,自动被删除。TempData一般用于临时的缓存内容或抛出错误页面时传递错误信息,可以将TempData在使用之前存储到相应的ViewData中以备循环使用。

下面我们来看一个实例,传递字符串给视图。

【例3.9】通过TempData传递字符串给视图

(1)复制例3.3到某个文件夹下作为本例的新项目,然后在VS中打开新项目,即双击test.sln打开解决方案。

(2)在控制器中修改代码。在解决方案资源管理器中打开Controllers/HomeController.cs,然后在Index方法末尾的return View();前添加一行代码:

TempData["msg"] = "Hello word!";

(3)在视图中添加代码。打开Views/Home/Index.cshtml,然后在该文件的“<h1>ASP.NET</h1>”下方增加一行代码:

<h3>@TempData["msg"]</h3>

此时运行项目,运行结果如下:

Hello word!

是不是感觉使用TempData也很简单。它和ViewData、ViewBag用法类似,均是在当前控制器与视图之间的数据传递。如果需要从一个控制器传递到另一个控制器,那就应该用TempData。

至此,我们基本了解了控制器、视图和模型了,虽然用到的东西都很简单,但对初学者来讲非常友好,比如模型就用了一些最基本的类,也没有用到数据库等,这就使得我们的学习曲线非常平缓。

相关文章:

  • 全志科技携飞凌嵌入式T527核心板亮相OpenHarmony开发者大会
  • springboot项目下面的单元测试注入的RedisConnectionFactory类redisConnectionFactory值为什么为空呢?
  • 鸿蒙OSUniApp导航栏组件开发:打造清新简约的用户界面#三方框架 #Uniapp
  • WordPress主题代码优化深度指南
  • 【嵌入式Linux】zlog日志库
  • Oralce RAC DRM详解
  • JAVA学习-练习试用Java实现“一个简单的多臂老虎机问题 :探索与利用权衡。
  • JAVA学习-练习试用Java实现“一个简单的Q-learning算法 :用于解决迷宫问题”
  • AI Agent在测试设计中的应用
  • Postgre数据库分区生产实战
  • 美国服务器文件系统的基本功能和命令
  • 论文阅读笔记——FLOW MATCHING FOR GENERATIVE MODELING
  • XUANYING炫影-移动版-智能轻云盒SY900Pro和SY910_RK3528芯片_免拆机通刷固件包
  • 在大型中实施访问控制 语言模型
  • BERT***
  • docker环境添加安装包持久性更新
  • Warm-Flow发布1.7.3 端午节(设计器流和流程图大升级)
  • Unity UI系统中RectTransform详解
  • C#面试问题41-60
  • gitLab 切换中文模式
  • 小企业网站建设多少钱/青岛网站制作
  • pc28网站开发/怎么制作网站?
  • 重庆网站设计系统/自媒体平台app
  • 网站平台建设要多久/2345网址导航浏览器下载
  • 高端医疗网站建设/企业网站seo服务
  • 百度百科分类方法/seo工具网站